integrationCodeMappings.spec.jsx 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173
  1. import selectEvent from 'react-select-event';
  2. import {
  3. render,
  4. renderGlobalModal,
  5. screen,
  6. userEvent,
  7. } from 'sentry-test/reactTestingLibrary';
  8. import ModalStore from 'sentry/stores/modalStore';
  9. import ProjectsStore from 'sentry/stores/projectsStore';
  10. import IntegrationCodeMappings from 'sentry/views/organizationIntegrations/integrationCodeMappings';
  11. describe('IntegrationCodeMappings', function () {
  12. const projects = [
  13. TestStubs.Project(),
  14. TestStubs.Project({
  15. id: '3',
  16. slug: 'some-project',
  17. name: 'Some Project',
  18. }),
  19. ];
  20. const org = TestStubs.Organization();
  21. const integration = TestStubs.GitHubIntegration();
  22. const repos = [
  23. TestStubs.Repository({
  24. integrationId: integration.id,
  25. }),
  26. TestStubs.Repository({
  27. integrationId: integration.id,
  28. id: '5',
  29. name: 'example/hello-there',
  30. }),
  31. ];
  32. const pathConfig1 = TestStubs.RepositoryProjectPathConfig({
  33. project: projects[0],
  34. repo: repos[0],
  35. integration,
  36. stackRoot: 'stack/root',
  37. sourceRoot: 'source/root',
  38. });
  39. const pathConfig2 = TestStubs.RepositoryProjectPathConfig({
  40. project: projects[1],
  41. repo: repos[1],
  42. integration,
  43. id: '12',
  44. stackRoot: 'one/path',
  45. sourceRoot: 'another/root',
  46. });
  47. beforeEach(() => {
  48. ModalStore.init();
  49. ProjectsStore.loadInitialData(projects);
  50. MockApiClient.addMockResponse({
  51. url: `/organizations/${org.slug}/code-mappings/`,
  52. body: [pathConfig1, pathConfig2],
  53. });
  54. MockApiClient.addMockResponse({
  55. url: `/organizations/${org.slug}/repos/`,
  56. body: repos,
  57. });
  58. });
  59. afterEach(() => {
  60. // Clear the fields from the GlobalModal after every test
  61. ModalStore.reset();
  62. ProjectsStore.reset();
  63. MockApiClient.clearMockResponses();
  64. });
  65. it('shows the paths', () => {
  66. render(<IntegrationCodeMappings organization={org} integration={integration} />);
  67. for (const repo of repos) {
  68. expect(screen.getByText(repo.name)).toBeInTheDocument();
  69. }
  70. });
  71. it('create new config', async () => {
  72. const stackRoot = 'my/root';
  73. const sourceRoot = 'hey/dude';
  74. const defaultBranch = 'release';
  75. const url = `/organizations/${org.slug}/code-mappings/`;
  76. const createMock = MockApiClient.addMockResponse({
  77. url,
  78. method: 'POST',
  79. body: TestStubs.RepositoryProjectPathConfig({
  80. project: projects[1],
  81. repo: repos[1],
  82. integration,
  83. stackRoot,
  84. sourceRoot,
  85. defaultBranch,
  86. }),
  87. });
  88. render(<IntegrationCodeMappings organization={org} integration={integration} />);
  89. const {waitForModalToHide} = renderGlobalModal();
  90. userEvent.click(screen.getByRole('button', {name: 'Add Code Mapping'}));
  91. expect(screen.getByRole('dialog')).toBeInTheDocument();
  92. await selectEvent.select(screen.getByText('Choose Sentry project'), projects[1].slug);
  93. await selectEvent.select(screen.getByText('Choose repo'), repos[1].name);
  94. userEvent.type(screen.getByRole('textbox', {name: 'Stack Trace Root'}), stackRoot);
  95. userEvent.type(screen.getByRole('textbox', {name: 'Source Code Root'}), sourceRoot);
  96. userEvent.clear(screen.getByRole('textbox', {name: 'Branch'}));
  97. userEvent.type(screen.getByRole('textbox', {name: 'Branch'}), defaultBranch);
  98. userEvent.click(screen.getByRole('button', {name: 'Save Changes'}));
  99. await waitForModalToHide();
  100. expect(createMock).toHaveBeenCalledWith(
  101. url,
  102. expect.objectContaining({
  103. data: expect.objectContaining({
  104. projectId: projects[1].id,
  105. repositoryId: repos[1].id,
  106. stackRoot,
  107. sourceRoot,
  108. defaultBranch,
  109. integrationId: integration.id,
  110. }),
  111. })
  112. );
  113. });
  114. it('edit existing config', async () => {
  115. const stackRoot = 'new/root';
  116. const sourceRoot = 'source/root';
  117. const defaultBranch = 'master';
  118. const url = `/organizations/${org.slug}/code-mappings/${pathConfig1.id}/`;
  119. const editMock = MockApiClient.addMockResponse({
  120. url,
  121. method: 'PUT',
  122. body: TestStubs.RepositoryProjectPathConfig({
  123. project: projects[0],
  124. repo: repos[0],
  125. integration,
  126. stackRoot,
  127. sourceRoot,
  128. defaultBranch,
  129. }),
  130. });
  131. render(<IntegrationCodeMappings organization={org} integration={integration} />);
  132. const {waitForModalToHide} = renderGlobalModal();
  133. userEvent.click(screen.getAllByRole('button', {name: 'edit'})[0]);
  134. userEvent.clear(screen.getByRole('textbox', {name: 'Stack Trace Root'}));
  135. userEvent.type(screen.getByRole('textbox', {name: 'Stack Trace Root'}), stackRoot);
  136. userEvent.click(screen.getByRole('button', {name: 'Save Changes'}));
  137. await waitForModalToHide();
  138. expect(editMock).toHaveBeenCalledWith(
  139. url,
  140. expect.objectContaining({
  141. data: expect.objectContaining({
  142. defaultBranch,
  143. projectId: '2',
  144. repositoryId: '4',
  145. sourceRoot,
  146. stackRoot,
  147. }),
  148. })
  149. );
  150. });
  151. });