integrationCodeMappings.spec.jsx 5.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216
  1. import {mountWithTheme} from 'sentry-test/enzyme';
  2. import {mountGlobalModal} from 'sentry-test/modal';
  3. import {selectByValue} from 'sentry-test/select-new';
  4. import {Client} from 'sentry/api';
  5. import ModalStore from 'sentry/stores/modalStore';
  6. import ProjectsStore from 'sentry/stores/projectsStore';
  7. import IntegrationCodeMappings from 'sentry/views/organizationIntegrations/integrationCodeMappings';
  8. const mockResponse = mocks => {
  9. mocks.forEach(([url, body]) =>
  10. Client.addMockResponse({
  11. url,
  12. body,
  13. })
  14. );
  15. };
  16. describe('IntegrationCodeMappings', function () {
  17. const projects = [
  18. TestStubs.Project(),
  19. TestStubs.Project({
  20. id: '3',
  21. slug: 'some-project',
  22. name: 'Some Project',
  23. }),
  24. ];
  25. ProjectsStore.loadInitialData(projects);
  26. const org = TestStubs.Organization();
  27. const invalidOrg = TestStubs.Organization({
  28. access: [],
  29. });
  30. const integration = TestStubs.GitHubIntegration();
  31. const repos = [
  32. TestStubs.Repository({
  33. integrationId: integration.id,
  34. }),
  35. TestStubs.Repository({
  36. integrationId: integration.id,
  37. id: '5',
  38. name: 'example/hello-there',
  39. }),
  40. ];
  41. const pathConfig1 = TestStubs.RepositoryProjectPathConfig({
  42. project: projects[0],
  43. repo: repos[0],
  44. integration,
  45. stackRoot: 'stack/root',
  46. sourceRoot: 'source/root',
  47. });
  48. const pathConfig2 = TestStubs.RepositoryProjectPathConfig({
  49. project: projects[1],
  50. repo: repos[1],
  51. integration,
  52. id: '12',
  53. stackRoot: 'one/path',
  54. sourceRoot: 'another/root',
  55. });
  56. let wrapper;
  57. beforeEach(() => {
  58. ModalStore.init();
  59. Client.clearMockResponses();
  60. mockResponse([
  61. [`/organizations/${org.slug}/code-mappings/`, [pathConfig1, pathConfig2]],
  62. [`/organizations/${org.slug}/repos/`, repos],
  63. ]);
  64. wrapper = mountWithTheme(
  65. <IntegrationCodeMappings organization={org} integration={integration} />
  66. );
  67. });
  68. afterEach(() => {
  69. // Clear the fields from the GlobalModal after every test
  70. ModalStore.reset();
  71. });
  72. it('shows the paths', () => {
  73. expect(wrapper.find('RepoName').length).toEqual(2);
  74. expect(wrapper.find('RepoName').at(0).text()).toEqual(repos[0].name);
  75. expect(wrapper.find('RepoName').at(1).text()).toEqual(repos[1].name);
  76. });
  77. it('opens modal', async () => {
  78. const modal = await mountGlobalModal();
  79. expect(modal.find('input[name="stackRoot"]')).toHaveLength(0);
  80. wrapper.find('button[data-test-id="add-mapping-button"]').first().simulate('click');
  81. await tick();
  82. modal.update();
  83. expect(modal.find('input[name="stackRoot"]')).toHaveLength(1);
  84. });
  85. it('requires permissions to click', async () => {
  86. const invalidContext = TestStubs.routerContext([{organization: invalidOrg}]);
  87. wrapper = mountWithTheme(
  88. <IntegrationCodeMappings organization={invalidOrg} integration={integration} />,
  89. invalidContext
  90. );
  91. const modal = await mountGlobalModal(invalidContext);
  92. expect(modal.find('input[name="stackRoot"]')).toHaveLength(0);
  93. const addMappingButton = wrapper
  94. .find('Button[data-test-id="add-mapping-button"]')
  95. .first();
  96. expect(addMappingButton.prop('disabled')).toBe(true);
  97. addMappingButton.simulate('click');
  98. await tick();
  99. modal.update();
  100. expect(modal.find('input[name="stackRoot"]')).toHaveLength(0);
  101. });
  102. it('create new config', async () => {
  103. const stackRoot = 'my/root';
  104. const sourceRoot = 'hey/dude';
  105. const defaultBranch = 'release';
  106. const url = `/organizations/${org.slug}/code-mappings/`;
  107. const createMock = Client.addMockResponse({
  108. url,
  109. method: 'POST',
  110. body: TestStubs.RepositoryProjectPathConfig({
  111. project: projects[1],
  112. repo: repos[1],
  113. integration,
  114. stackRoot,
  115. sourceRoot,
  116. defaultBranch,
  117. }),
  118. });
  119. wrapper.find('button[data-test-id="add-mapping-button"]').first().simulate('click');
  120. const modal = await mountGlobalModal();
  121. selectByValue(modal, projects[1].id, {control: true, name: 'projectId'});
  122. selectByValue(modal, repos[1].id, {control: true, name: 'repositoryId'});
  123. modal
  124. .find('input[name="stackRoot"]')
  125. .simulate('change', {target: {value: stackRoot}});
  126. modal
  127. .find('input[name="sourceRoot"]')
  128. .simulate('change', {target: {value: sourceRoot}});
  129. modal
  130. .find('input[name="defaultBranch"]')
  131. .simulate('change', {target: {value: defaultBranch}});
  132. modal.find('form').simulate('submit');
  133. expect(createMock).toHaveBeenCalledWith(
  134. url,
  135. expect.objectContaining({
  136. data: expect.objectContaining({
  137. projectId: projects[1].id,
  138. repositoryId: repos[1].id,
  139. stackRoot,
  140. sourceRoot,
  141. defaultBranch,
  142. integrationId: integration.id,
  143. }),
  144. })
  145. );
  146. });
  147. it('edit existing config', async () => {
  148. const stackRoot = 'new/root';
  149. const sourceRoot = 'source/root';
  150. const defaultBranch = 'master';
  151. const url = `/organizations/${org.slug}/code-mappings/${pathConfig1.id}/`;
  152. const editMock = Client.addMockResponse({
  153. url,
  154. method: 'PUT',
  155. body: TestStubs.RepositoryProjectPathConfig({
  156. project: projects[0],
  157. repo: repos[0],
  158. integration,
  159. stackRoot,
  160. sourceRoot,
  161. defaultBranch,
  162. }),
  163. });
  164. wrapper.find('button[aria-label="edit"]').first().simulate('click');
  165. await tick();
  166. const modal = await mountGlobalModal();
  167. modal
  168. .find('input[name="stackRoot"]')
  169. .simulate('change', {target: {value: stackRoot}});
  170. modal.find('form').simulate('submit');
  171. expect(editMock).toHaveBeenCalledWith(
  172. url,
  173. expect.objectContaining({
  174. data: expect.objectContaining({
  175. defaultBranch,
  176. projectId: '2',
  177. repositoryId: '4',
  178. sourceRoot,
  179. stackRoot,
  180. }),
  181. })
  182. );
  183. });
  184. });