integrationExternalMappings.spec.tsx 5.5 KB

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