integrationCodeMappings.spec.jsx 5.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215
  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. projects[0],
  43. repos[0],
  44. integration,
  45. {
  46. stackRoot: 'stack/root',
  47. sourceRoot: 'source/root',
  48. }
  49. );
  50. const pathConfig2 = TestStubs.RepositoryProjectPathConfig(
  51. projects[1],
  52. repos[1],
  53. integration,
  54. {
  55. id: '12',
  56. stackRoot: 'one/path',
  57. sourceRoot: 'another/root',
  58. }
  59. );
  60. let wrapper;
  61. beforeEach(() => {
  62. ModalStore.init();
  63. Client.clearMockResponses();
  64. mockResponse([
  65. [`/organizations/${org.slug}/code-mappings/`, [pathConfig1, pathConfig2]],
  66. [`/organizations/${org.slug}/repos/`, repos],
  67. ]);
  68. wrapper = mountWithTheme(
  69. <IntegrationCodeMappings organization={org} integration={integration} />
  70. );
  71. });
  72. afterEach(() => {
  73. // Clear the fields from the GlobalModal after every test
  74. ModalStore.reset();
  75. ModalStore.teardown();
  76. });
  77. it('shows the paths', () => {
  78. expect(wrapper.find('RepoName').length).toEqual(2);
  79. expect(wrapper.find('RepoName').at(0).text()).toEqual(repos[0].name);
  80. expect(wrapper.find('RepoName').at(1).text()).toEqual(repos[1].name);
  81. });
  82. it('opens modal', async () => {
  83. const modal = await mountGlobalModal();
  84. expect(modal.find('input[name="stackRoot"]')).toHaveLength(0);
  85. wrapper.find('button[data-test-id="add-mapping-button"]').first().simulate('click');
  86. await tick();
  87. modal.update();
  88. expect(modal.find('input[name="stackRoot"]')).toHaveLength(1);
  89. });
  90. it('requires permissions to click', async () => {
  91. const invalidContext = TestStubs.routerContext([{organization: invalidOrg}]);
  92. wrapper = mountWithTheme(
  93. <IntegrationCodeMappings organization={invalidOrg} integration={integration} />,
  94. invalidContext
  95. );
  96. const modal = await mountGlobalModal(invalidContext);
  97. expect(modal.find('input[name="stackRoot"]')).toHaveLength(0);
  98. const addMappingButton = wrapper
  99. .find('Button[data-test-id="add-mapping-button"]')
  100. .first();
  101. expect(addMappingButton.prop('disabled')).toBe(true);
  102. addMappingButton.simulate('click');
  103. await tick();
  104. modal.update();
  105. expect(modal.find('input[name="stackRoot"]')).toHaveLength(0);
  106. });
  107. it('create new config', async () => {
  108. const stackRoot = 'my/root';
  109. const sourceRoot = 'hey/dude';
  110. const defaultBranch = 'release';
  111. const url = `/organizations/${org.slug}/code-mappings/`;
  112. const createMock = Client.addMockResponse({
  113. url,
  114. method: 'POST',
  115. body: TestStubs.RepositoryProjectPathConfig(projects[1], repos[1], integration, {
  116. stackRoot,
  117. sourceRoot,
  118. defaultBranch,
  119. }),
  120. });
  121. wrapper.find('button[data-test-id="add-mapping-button"]').first().simulate('click');
  122. const modal = await mountGlobalModal();
  123. selectByValue(modal, projects[1].id, {control: true, name: 'projectId'});
  124. selectByValue(modal, repos[1].id, {control: true, name: 'repositoryId'});
  125. modal
  126. .find('input[name="stackRoot"]')
  127. .simulate('change', {target: {value: stackRoot}});
  128. modal
  129. .find('input[name="sourceRoot"]')
  130. .simulate('change', {target: {value: sourceRoot}});
  131. modal
  132. .find('input[name="defaultBranch"]')
  133. .simulate('change', {target: {value: defaultBranch}});
  134. modal.find('form').simulate('submit');
  135. expect(createMock).toHaveBeenCalledWith(
  136. url,
  137. expect.objectContaining({
  138. data: expect.objectContaining({
  139. projectId: projects[1].id,
  140. repositoryId: repos[1].id,
  141. stackRoot,
  142. sourceRoot,
  143. defaultBranch,
  144. integrationId: integration.id,
  145. }),
  146. })
  147. );
  148. });
  149. it('edit existing config', async () => {
  150. const stackRoot = 'new/root';
  151. const sourceRoot = 'source/root';
  152. const defaultBranch = 'master';
  153. const url = `/organizations/${org.slug}/code-mappings/${pathConfig1.id}/`;
  154. const editMock = Client.addMockResponse({
  155. url,
  156. method: 'PUT',
  157. body: TestStubs.RepositoryProjectPathConfig(projects[0], repos[0], integration, {
  158. stackRoot,
  159. sourceRoot,
  160. defaultBranch,
  161. }),
  162. });
  163. wrapper.find('button[aria-label="edit"]').first().simulate('click');
  164. await tick();
  165. const modal = await mountGlobalModal();
  166. modal
  167. .find('input[name="stackRoot"]')
  168. .simulate('change', {target: {value: stackRoot}});
  169. modal.find('form').simulate('submit');
  170. expect(editMock).toHaveBeenCalledWith(
  171. url,
  172. expect.objectContaining({
  173. data: expect.objectContaining({
  174. defaultBranch,
  175. projectId: '2',
  176. repositoryId: '4',
  177. sourceRoot,
  178. stackRoot,
  179. }),
  180. })
  181. );
  182. });
  183. });