integrationExternalMappings.spec.tsx 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185
  1. import {GitHubIntegrationFixture} from 'sentry-fixture/githubIntegration';
  2. import {initializeOrg} from 'sentry-test/initializeOrg';
  3. import {
  4. render,
  5. renderGlobalModal,
  6. screen,
  7. userEvent,
  8. waitForElementToBeRemoved,
  9. } from 'sentry-test/reactTestingLibrary';
  10. import IntegrationExternalMappings from './integrationExternalMappings';
  11. describe('IntegrationExternalMappings', function () {
  12. const {organization, router} = initializeOrg();
  13. const onCreateMock = jest.fn();
  14. const onDeleteMock = jest.fn();
  15. const MOCK_USER_SUGGESTIONS = ['@peter', '@ned', '@mj'];
  16. const MOCK_TEAM_SUGGESTIONS = [
  17. '@getsentry/snacks',
  18. '@getsentry/sports',
  19. '@getsentry/hype',
  20. ];
  21. const MOCK_USER_MAPPINGS = [
  22. {
  23. id: '1',
  24. userId: '1',
  25. externalName: '@gwen',
  26. sentryName: 'gwen@mcu.org',
  27. },
  28. {
  29. id: '2',
  30. userId: '2',
  31. externalName: '@eddie',
  32. sentryName: 'eddie@mcu.org',
  33. },
  34. ];
  35. const MOCK_TEAM_MAPPINGS = [
  36. {
  37. id: '1',
  38. teamId: '1',
  39. externalName: '@getsentry/animals',
  40. sentryName: '#zoo',
  41. },
  42. {
  43. id: '2',
  44. teamId: '2',
  45. externalName: '@getsentry/ghosts',
  46. sentryName: '#boo',
  47. },
  48. ];
  49. const createMockSuggestions = () => {
  50. MockApiClient.addMockResponse({
  51. url: `/organizations/${organization.slug}/codeowners-associations/`,
  52. method: 'GET',
  53. body: {
  54. 'project-1': {
  55. errors: {
  56. missing_external_users: MOCK_USER_SUGGESTIONS,
  57. missing_external_teams: MOCK_TEAM_SUGGESTIONS,
  58. },
  59. },
  60. },
  61. });
  62. };
  63. it('renders empty if not mappings are provided or found', async function () {
  64. MockApiClient.addMockResponse({
  65. url: `/organizations/${organization.slug}/codeowners-associations/`,
  66. method: 'GET',
  67. body: {},
  68. });
  69. const {container} = render(
  70. <IntegrationExternalMappings
  71. integration={GitHubIntegrationFixture()}
  72. mappings={[]}
  73. type="user"
  74. onCreate={onCreateMock}
  75. onDelete={onDeleteMock}
  76. defaultOptions={[]}
  77. dataEndpoint="/organizations/org-slug/codeowners-associations/"
  78. getBaseFormEndpoint={() => '/organizations/org-slug/codeowners-associations/'}
  79. sentryNamesMapper={data => data}
  80. />,
  81. {
  82. router,
  83. }
  84. );
  85. await waitForElementToBeRemoved(() => screen.queryByTestId('loading-indicator'));
  86. expect(container).toHaveTextContent('Set up External User Mappings.');
  87. });
  88. it('still renders suggestions if no mappings are provided', async function () {
  89. createMockSuggestions();
  90. render(
  91. <IntegrationExternalMappings
  92. integration={GitHubIntegrationFixture()}
  93. mappings={[]}
  94. type="user"
  95. onCreate={onCreateMock}
  96. onDelete={onDeleteMock}
  97. defaultOptions={[]}
  98. dataEndpoint="/organizations/org-slug/codeowners-associations/"
  99. getBaseFormEndpoint={() => '/organizations/org-slug/codeowners-associations/'}
  100. sentryNamesMapper={data => data}
  101. />,
  102. {
  103. router,
  104. }
  105. );
  106. expect(await screen.findByTestId('mapping-table')).toBeInTheDocument();
  107. for (const user of MOCK_USER_SUGGESTIONS) {
  108. expect(screen.getByText(user)).toBeInTheDocument();
  109. }
  110. expect(screen.getAllByTestId('more-information')).toHaveLength(3);
  111. });
  112. it('renders suggestions along with the provided mappings', async function () {
  113. createMockSuggestions();
  114. render(
  115. <IntegrationExternalMappings
  116. integration={GitHubIntegrationFixture()}
  117. mappings={MOCK_TEAM_MAPPINGS}
  118. type="team"
  119. onCreate={onCreateMock}
  120. onDelete={onDeleteMock}
  121. defaultOptions={[]}
  122. dataEndpoint="/organizations/org-slug/codeowners-associations/"
  123. getBaseFormEndpoint={() => '/organizations/org-slug/codeowners-associations/'}
  124. sentryNamesMapper={data => data}
  125. />,
  126. {
  127. router,
  128. }
  129. );
  130. expect(await screen.findByTestId('mapping-table')).toBeInTheDocument();
  131. for (const team of MOCK_TEAM_SUGGESTIONS) {
  132. expect(screen.getByText(team)).toBeInTheDocument();
  133. }
  134. expect(screen.getAllByRole('button', {name: 'Remove user mapping'})).toHaveLength(2);
  135. for (const team of MOCK_TEAM_MAPPINGS) {
  136. expect(screen.getByText(team.externalName)).toBeInTheDocument();
  137. expect(screen.getByText(team.sentryName)).toBeInTheDocument();
  138. }
  139. expect(screen.getAllByTestId('more-information')).toHaveLength(3);
  140. });
  141. it('uses the methods passed down from props appropriately', async function () {
  142. createMockSuggestions();
  143. render(
  144. <IntegrationExternalMappings
  145. integration={GitHubIntegrationFixture()}
  146. mappings={MOCK_USER_MAPPINGS}
  147. type="user"
  148. onCreate={onCreateMock}
  149. onDelete={onDeleteMock}
  150. defaultOptions={[]}
  151. dataEndpoint="/organizations/org-slug/codeowners-associations/"
  152. getBaseFormEndpoint={() => '/organizations/org-slug/codeowners-associations/'}
  153. sentryNamesMapper={data => data}
  154. />,
  155. {
  156. router,
  157. }
  158. );
  159. renderGlobalModal();
  160. expect(await screen.findByTestId('mapping-table')).toBeInTheDocument();
  161. await userEvent.click(screen.getByTestId('add-mapping-button'));
  162. expect(onCreateMock).toHaveBeenCalled();
  163. await userEvent.click(
  164. screen.getAllByRole('button', {name: 'Remove user mapping'})[0]!
  165. );
  166. await userEvent.click(screen.getByTestId('confirm-button'));
  167. expect(onDeleteMock).toHaveBeenCalled();
  168. });
  169. });