integrationRepos.spec.jsx 6.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209
  1. import {mountWithTheme} from 'sentry-test/enzyme';
  2. import {Client} from 'sentry/api';
  3. import RepositoryStore from 'sentry/stores/repositoryStore';
  4. import IntegrationRepos from 'sentry/views/organizationIntegrations/integrationRepos';
  5. describe('IntegrationRepos', function () {
  6. const org = TestStubs.Organization();
  7. const integration = TestStubs.GitHubIntegration();
  8. beforeEach(() => {
  9. Client.clearMockResponses();
  10. jest.spyOn(RepositoryStore, 'resetRepositories');
  11. });
  12. afterEach(() => {
  13. jest.restoreAllMocks();
  14. });
  15. describe('Getting repositories', function () {
  16. it('handles broken integrations', function () {
  17. Client.addMockResponse({
  18. url: `/organizations/${org.slug}/integrations/1/repos/`,
  19. statusCode: 400,
  20. body: {detail: 'Invalid grant'},
  21. });
  22. Client.addMockResponse({
  23. url: `/organizations/${org.slug}/repos/`,
  24. method: 'GET',
  25. body: [],
  26. });
  27. const wrapper = mountWithTheme(<IntegrationRepos integration={integration} />);
  28. expect(wrapper.find('PanelBody')).toHaveLength(0);
  29. expect(wrapper.find('Alert')).toHaveLength(1);
  30. });
  31. });
  32. describe('Adding repositories', function () {
  33. it('can save successfully', async function () {
  34. const addRepo = Client.addMockResponse({
  35. url: `/organizations/${org.slug}/repos/`,
  36. method: 'POST',
  37. body: TestStubs.Repository({integrationId: '1'}),
  38. });
  39. Client.addMockResponse({
  40. url: `/organizations/${org.slug}/integrations/1/repos/`,
  41. body: {
  42. repos: [{identifier: 'example/repo-name', name: 'repo-name'}],
  43. },
  44. });
  45. Client.addMockResponse({
  46. url: `/organizations/${org.slug}/repos/`,
  47. method: 'GET',
  48. body: [],
  49. });
  50. const wrapper = mountWithTheme(<IntegrationRepos integration={integration} />);
  51. wrapper.find('DropdownButton').simulate('click');
  52. wrapper.find('StyledListElement').simulate('click');
  53. expect(addRepo).toHaveBeenCalledWith(
  54. `/organizations/${org.slug}/repos/`,
  55. expect.objectContaining({
  56. data: {
  57. installation: '1',
  58. provider: 'integrations:github',
  59. identifier: 'example/repo-name',
  60. },
  61. })
  62. );
  63. await tick();
  64. wrapper.update();
  65. const name = wrapper.find('RepositoryRow').find('strong').first();
  66. expect(name).toHaveLength(1);
  67. expect(name.text()).toEqual('example/repo-name');
  68. expect(RepositoryStore.resetRepositories).toHaveBeenCalled();
  69. });
  70. it('handles failure during save', function () {
  71. const addRepo = Client.addMockResponse({
  72. url: `/organizations/${org.slug}/repos/`,
  73. method: 'POST',
  74. statusCode: 400,
  75. body: {
  76. errors: {
  77. __all__: 'Repository already exists.',
  78. },
  79. },
  80. });
  81. Client.addMockResponse({
  82. url: `/organizations/${org.slug}/integrations/1/repos/`,
  83. body: {
  84. repos: [{identifier: 'getsentry/sentry', name: 'sentry'}],
  85. },
  86. });
  87. Client.addMockResponse({
  88. url: `/organizations/${org.slug}/repos/`,
  89. method: 'GET',
  90. body: [],
  91. });
  92. const wrapper = mountWithTheme(<IntegrationRepos integration={integration} />);
  93. wrapper.find('DropdownButton').simulate('click');
  94. wrapper.find('StyledListElement').simulate('click');
  95. wrapper.update();
  96. expect(addRepo).toHaveBeenCalled();
  97. expect(wrapper.find('RepoOption')).toHaveLength(0);
  98. });
  99. it('does not disable add repo for members', function () {
  100. Client.addMockResponse({
  101. url: `/organizations/${org.slug}/integrations/1/repos/`,
  102. body: {
  103. repos: [{identifier: 'example/repo-name', name: 'repo-name'}],
  104. },
  105. });
  106. Client.addMockResponse({
  107. url: `/organizations/${org.slug}/repos/`,
  108. method: 'GET',
  109. body: [],
  110. });
  111. const wrapper = mountWithTheme(
  112. <IntegrationRepos
  113. integration={integration}
  114. organization={TestStubs.Organization({access: []})}
  115. />
  116. );
  117. expect(wrapper.find('DropdownButton').props().disabled).toBeFalsy();
  118. });
  119. });
  120. describe('migratable repo', function () {
  121. it('associates repository with integration', async () => {
  122. Client.addMockResponse({
  123. url: `/organizations/${org.slug}/repos/`,
  124. body: [
  125. TestStubs.Repository({
  126. integrationId: null,
  127. externalSlug: 'example/repo-name',
  128. provider: {
  129. id: 'integrations:github',
  130. name: 'GitHub',
  131. status: 'active',
  132. },
  133. }),
  134. ],
  135. });
  136. Client.addMockResponse({
  137. url: `/organizations/${org.slug}/integrations/${integration.id}/repos/`,
  138. body: {repos: [{identifier: 'example/repo-name', name: 'repo-name'}]},
  139. });
  140. const updateRepo = Client.addMockResponse({
  141. method: 'PUT',
  142. url: `/organizations/${org.slug}/repos/4/`,
  143. body: {},
  144. });
  145. const wrapper = mountWithTheme(<IntegrationRepos integration={integration} />);
  146. wrapper.find('DropdownButton').simulate('click');
  147. wrapper.find('StyledListElement').simulate('click');
  148. await tick();
  149. expect(updateRepo).toHaveBeenCalledWith(
  150. `/organizations/${org.slug}/repos/4/`,
  151. expect.objectContaining({
  152. data: {integrationId: '1'},
  153. })
  154. );
  155. expect(RepositoryStore.resetRepositories).toHaveBeenCalled();
  156. });
  157. it('uses externalSlug not name for comparison', () => {
  158. Client.addMockResponse({
  159. url: `/organizations/${org.slug}/repos/`,
  160. method: 'GET',
  161. body: [TestStubs.Repository({name: 'repo-name', externalSlug: 9876})],
  162. });
  163. const getItems = Client.addMockResponse({
  164. url: `/organizations/${org.slug}/integrations/${integration.id}/repos/`,
  165. method: 'GET',
  166. body: {
  167. repos: [{identifier: 9876, name: 'repo-name'}],
  168. },
  169. });
  170. const updateRepo = Client.addMockResponse({
  171. method: 'PUT',
  172. url: `/organizations/${org.slug}/repos/4/`,
  173. body: {},
  174. });
  175. const wrapper = mountWithTheme(<IntegrationRepos integration={integration} />);
  176. wrapper.find('DropdownButton').simulate('click');
  177. wrapper.find('StyledListElement').simulate('click');
  178. expect(getItems).toHaveBeenCalled();
  179. expect(updateRepo).toHaveBeenCalledWith(
  180. `/organizations/${org.slug}/repos/4/`,
  181. expect.objectContaining({
  182. data: {integrationId: '1'},
  183. })
  184. );
  185. });
  186. });
  187. });