ticketRuleModal.spec.jsx 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192
  1. import selectEvent from 'react-select-event';
  2. import fetchMock from 'jest-fetch-mock';
  3. import {initializeOrg} from 'sentry-test/initializeOrg';
  4. import {render, screen, userEvent} from 'sentry-test/reactTestingLibrary';
  5. import {addSuccessMessage} from 'sentry/actionCreators/indicator';
  6. import TicketRuleModal from 'sentry/views/alerts/rules/issue/ticketRuleModal';
  7. jest.unmock('sentry/utils/recreateRoute');
  8. jest.mock('sentry/actionCreators/indicator');
  9. jest.mock('sentry/actionCreators/onboardingTasks');
  10. describe('ProjectAlerts -> TicketRuleModal', function () {
  11. const closeModal = jest.fn();
  12. const modalElements = {
  13. Header: p => p.children,
  14. Body: p => p.children,
  15. Footer: p => p.children,
  16. };
  17. beforeEach(function () {
  18. fetchMock.enableMocks();
  19. fetch.resetMocks();
  20. addSuccessMessage.mockReset();
  21. });
  22. afterEach(function () {
  23. closeModal.mockReset();
  24. MockApiClient.clearMockResponses();
  25. });
  26. const doSubmit = async () =>
  27. await userEvent.click(screen.getByRole('button', {name: 'Apply Changes'}));
  28. const submitSuccess = async () => {
  29. await doSubmit();
  30. expect(addSuccessMessage).toHaveBeenCalled();
  31. expect(closeModal).toHaveBeenCalled();
  32. };
  33. const submitErrors = async errorCount => {
  34. await doSubmit();
  35. expect(screen.getAllByText('Field is required')).toHaveLength(errorCount);
  36. expect(closeModal).toHaveBeenCalledTimes(0);
  37. };
  38. const addMockConfigsAPICall = (otherFields = {}) => {
  39. return MockApiClient.addMockResponse({
  40. url: '/organizations/org-slug/integrations/1/?ignored=Sprint',
  41. method: 'GET',
  42. body: {
  43. createIssueConfig: [
  44. {
  45. name: 'project',
  46. label: 'Jira Project',
  47. choices: [['10000', 'TEST']],
  48. default: '10000',
  49. type: 'select',
  50. updatesForm: true,
  51. },
  52. {
  53. name: 'issuetype',
  54. label: 'Issue Type',
  55. default: '10001',
  56. type: 'select',
  57. choices: [
  58. ['10001', 'Improvement'],
  59. ['10002', 'Task'],
  60. ['10003', 'Sub-task'],
  61. ['10004', 'New Feature'],
  62. ['10005', 'Bug'],
  63. ['10000', 'Epic'],
  64. ],
  65. updatesForm: true,
  66. required: true,
  67. },
  68. otherFields,
  69. ],
  70. },
  71. });
  72. };
  73. /**
  74. * We need to use this alternate mocking scheme because `fetch` isn't available.
  75. * @param names String[]
  76. */
  77. const addMockUsersAPICall = (names = []) => {
  78. fetch.mockResponseOnce(
  79. JSON.stringify(
  80. names.map(name => {
  81. return {
  82. label: name,
  83. value: name,
  84. };
  85. })
  86. )
  87. );
  88. };
  89. const renderComponent = (props = {}) => {
  90. const {organization, routerContext} = initializeOrg(props);
  91. addMockConfigsAPICall({
  92. label: 'Reporter',
  93. required: true,
  94. choices: [['a', 'a']],
  95. type: 'select',
  96. name: 'reporter',
  97. });
  98. return render(
  99. <TicketRuleModal
  100. {...modalElements}
  101. closeModal={closeModal}
  102. formFields={{}}
  103. link=""
  104. ticketType=""
  105. instance={{...(props.data || {}), integration: 1}}
  106. index={0}
  107. onSubmitAction={() => {}}
  108. organization={organization}
  109. />,
  110. {context: routerContext}
  111. );
  112. };
  113. describe('Create Rule', function () {
  114. it('should render the Ticket Rule modal', function () {
  115. renderComponent();
  116. expect(screen.getByRole('button', {name: 'Apply Changes'})).toBeInTheDocument();
  117. expect(screen.getByRole('textbox', {name: 'Title'})).toBeInTheDocument();
  118. expect(screen.getByRole('textbox', {name: 'Description'})).toBeInTheDocument();
  119. });
  120. it('should save the modal data when "Apply Changes" is clicked with valid data', async function () {
  121. renderComponent();
  122. await selectEvent.select(screen.getByRole('textbox', {name: 'Reporter'}), 'a');
  123. await submitSuccess();
  124. });
  125. it('should raise validation errors when "Apply Changes" is clicked with invalid data', async function () {
  126. // This doesn't test anything TicketRules specific but I'm leaving it here as an example.
  127. renderComponent();
  128. await submitErrors(1);
  129. });
  130. it('should reload fields when an "updatesForm" field changes', async function () {
  131. renderComponent();
  132. await selectEvent.select(screen.getByRole('textbox', {name: 'Reporter'}), 'a');
  133. addMockConfigsAPICall({
  134. label: 'Assignee',
  135. required: true,
  136. choices: [['b', 'b']],
  137. type: 'select',
  138. name: 'assignee',
  139. });
  140. await selectEvent.select(screen.getByRole('textbox', {name: 'Issue Type'}), 'Epic');
  141. await selectEvent.select(screen.getByRole('textbox', {name: 'Assignee'}), 'b');
  142. await submitSuccess();
  143. });
  144. it('should persist values when the modal is reopened', async function () {
  145. renderComponent({data: {reporter: 'a'}});
  146. await submitSuccess();
  147. });
  148. it('should get async options from URL', async function () {
  149. renderComponent();
  150. addMockConfigsAPICall({
  151. label: 'Assignee',
  152. required: true,
  153. url: 'http://example.com',
  154. type: 'select',
  155. name: 'assignee',
  156. });
  157. await selectEvent.select(screen.getByRole('textbox', {name: 'Issue Type'}), 'Epic');
  158. addMockUsersAPICall(['Marcos']);
  159. const menu = screen.getByRole('textbox', {name: 'Assignee'});
  160. selectEvent.openMenu(menu);
  161. await userEvent.type(menu, 'Marc{Escape}');
  162. await selectEvent.select(menu, 'Marcos');
  163. await submitSuccess();
  164. });
  165. });
  166. });