123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291 |
- import {mountWithTheme} from 'sentry-test/enzyme';
- import {changeInputValue, selectByValue} from 'sentry-test/select-new';
- import {Client} from 'sentry/api';
- import SentryAppExternalIssueForm from 'sentry/components/group/sentryAppExternalIssueForm';
- import {addQueryParamsToExistingUrl} from 'sentry/utils/queryString';
- const optionLabelSelector = label => `[label="${label}"]`;
- describe('SentryAppExternalIssueForm', () => {
- let wrapper;
- let group;
- let sentryApp;
- let sentryAppInstallation;
- let component;
- let submitUrl;
- let externalIssueRequest;
- beforeEach(() => {
- group = TestStubs.Group({
- title: 'ApiError: Broken',
- shortId: 'SEN123',
- permalink: 'https://sentry.io/organizations/sentry/issues/123/?project=1',
- });
- component = TestStubs.SentryAppComponent();
- sentryApp = TestStubs.SentryApp();
- sentryAppInstallation = TestStubs.SentryAppInstallation({sentryApp});
- submitUrl = `/sentry-app-installations/${sentryAppInstallation.uuid}/external-issue-actions/`;
- externalIssueRequest = Client.addMockResponse({
- url: submitUrl,
- method: 'POST',
- body: {},
- });
- });
- describe('create', () => {
- beforeEach(() => {
- wrapper = mountWithTheme(
- <SentryAppExternalIssueForm
- group={group}
- sentryAppInstallation={sentryAppInstallation}
- appName={sentryApp.name}
- config={component.schema.create}
- action="create"
- api={new Client()}
- />
- );
- });
- it('renders each required_fields field', () => {
- component.schema.create.required_fields.forEach(field => {
- expect(wrapper.exists(`#${field.name}`)).toBe(true);
- });
- });
- it('does not submit form if required fields are not set', () => {
- wrapper.find('form').simulate('submit');
- expect(externalIssueRequest).not.toHaveBeenCalled();
- });
- it('submits to the New External Issue endpoint', () => {
- selectByValue(wrapper, 'number_1', {name: 'numbers', control: true});
- wrapper.find('form').simulate('submit');
- expect(externalIssueRequest).toHaveBeenCalledWith(
- submitUrl,
- expect.objectContaining({
- data: {
- action: 'create',
- description:
- 'Sentry Issue: [SEN123](https://sentry.io/organizations/sentry/issues/123/?project=1&referrer=Sample%20App)',
- groupId: '1',
- numbers: 'number_1',
- title: 'ApiError: Broken',
- },
- method: 'POST',
- })
- );
- });
- it('renders prepopulated defaults', () => {
- const titleField = wrapper.find('Input#title');
- const descriptionField = wrapper.find('TextArea#description');
- const url = addQueryParamsToExistingUrl(group.permalink, {
- referrer: sentryApp.name,
- });
- expect(titleField.prop('value')).toEqual(`${group.title}`);
- expect(descriptionField.prop('value')).toEqual(
- `Sentry Issue: [${group.shortId}](${url})`
- );
- });
- });
- describe('link', () => {
- beforeEach(() => {
- wrapper = mountWithTheme(
- <SentryAppExternalIssueForm
- group={group}
- sentryAppInstallation={sentryAppInstallation}
- appName={sentryApp.name}
- config={component.schema.link}
- action="link"
- api={new Client()}
- />
- );
- });
- it('renders each required_fields field', () => {
- component.schema.link.required_fields.forEach(field => {
- expect(wrapper.exists(`#${field.name}`)).toBe(true);
- });
- });
- it('submits to the New External Issue endpoint', () => {
- wrapper
- .find('input[name="issue"]')
- .simulate('change', {target: {value: 'my issue'}});
- wrapper.find('form').simulate('submit');
- expect(externalIssueRequest).toHaveBeenCalledWith(
- submitUrl,
- expect.objectContaining({
- data: {
- action: 'link',
- groupId: '1',
- issue: 'my issue',
- },
- method: 'POST',
- })
- );
- });
- });
- });
- describe('SentryAppExternalIssueForm Async Field', () => {
- let wrapper;
- let group;
- let sentryApp;
- let sentryAppInstallation;
- const component = TestStubs.SentryAppComponentAsync();
- beforeEach(() => {
- group = TestStubs.Group({
- title: 'ApiError: Broken',
- shortId: 'SEN123',
- permalink: 'https://sentry.io/organizations/sentry/issues/123/?project=1',
- });
- sentryApp = TestStubs.SentryApp();
- sentryAppInstallation = TestStubs.SentryAppInstallation({sentryApp});
- });
- afterEach(() => {
- Client.clearMockResponses();
- });
- describe('renders', () => {
- it('renders each required_fields field', async function () {
- const mockGetOptions = Client.addMockResponse({
- method: 'GET',
- url: '/sentry-app-installations/d950595e-cba2-46f6-8a94-b79e42806f98/external-requests/',
- body: {
- choices: [
- [1, 'Issue 1'],
- [2, 'Issue 2'],
- ],
- },
- });
- wrapper = mountWithTheme(
- <SentryAppExternalIssueForm
- group={group}
- sentryAppInstallation={sentryAppInstallation}
- appName={sentryApp.name}
- config={component.schema.create}
- action="create"
- api={new Client()}
- />
- );
- const thisInput = wrapper.find('input').at(0);
- changeInputValue(thisInput, 'I');
- await tick();
- wrapper.update();
- expect(mockGetOptions).toHaveBeenCalled();
- expect(wrapper.find(optionLabelSelector('Issue 1')).exists()).toBe(true);
- expect(wrapper.find(optionLabelSelector('Issue 2')).exists()).toBe(true);
- });
- });
- });
- describe('SentryAppExternalIssueForm Dependent fields', () => {
- let wrapper;
- let group;
- let sentryApp;
- let sentryAppInstallation;
- const component = TestStubs.SentryAppComponentDependent();
- beforeEach(() => {
- group = TestStubs.Group({
- title: 'ApiError: Broken',
- shortId: 'SEN123',
- permalink: 'https://sentry.io/organizations/sentry/issues/123/?project=1',
- });
- sentryApp = TestStubs.SentryApp();
- sentryAppInstallation = TestStubs.SentryAppInstallation({sentryApp});
- wrapper = mountWithTheme(
- <SentryAppExternalIssueForm
- group={group}
- sentryAppInstallation={sentryAppInstallation}
- appName={sentryApp.name}
- config={component.schema.create}
- action="create"
- api={new Client()}
- />
- );
- });
- afterEach(() => {
- Client.clearMockResponses();
- });
- describe('create', () => {
- it('load options for field that has dependencies when the dependent option is selected', async () => {
- const url = `/sentry-app-installations/${sentryAppInstallation.uuid}/external-requests/`;
- Client.addMockResponse({
- method: 'GET',
- url,
- body: {
- choices: [
- ['A', 'project A'],
- ['B', 'project B'],
- ],
- },
- match: [MockApiClient.matchQuery({uri: '/integrations/sentry/projects'})],
- });
- const boardMock = Client.addMockResponse({
- method: 'GET',
- url,
- body: {
- choices: [
- ['R', 'board R'],
- ['S', 'board S'],
- ],
- },
- match: [
- MockApiClient.matchQuery({
- uri: '/integrations/sentry/boards',
- dependentData: JSON.stringify({project_id: 'A'}),
- }),
- ],
- });
- const projectInput = wrapper.find('[data-test-id="project_id"] input').at(0);
- changeInputValue(projectInput, 'p');
- await tick();
- wrapper.update();
- expect(wrapper.find(optionLabelSelector('project A')).exists()).toBe(true);
- expect(wrapper.find(optionLabelSelector('project B')).exists()).toBe(true);
- // project select should be disabled and we shouldn't fetch the options yet
- expect(wrapper.find('SelectControl#board_id').prop('disabled')).toBe(true);
- expect(boardMock).not.toHaveBeenCalled();
- // when we set the value for project we should get the values for the board
- selectByValue(wrapper, 'A', {name: 'project_id'});
- await tick();
- wrapper.update();
- expect(boardMock).toHaveBeenCalled();
- expect(wrapper.find('SelectControl#board_id').prop('disabled')).toBe(false);
- const boardInput = wrapper.find('[data-test-id="board_id"] input').at(0);
- changeInputValue(boardInput, 'b');
- await tick();
- wrapper.update();
- expect(wrapper.find(optionLabelSelector('board R')).exists()).toBe(true);
- expect(wrapper.find(optionLabelSelector('board S')).exists()).toBe(true);
- });
- });
- });
|