integrationDetailedView.spec.tsx 9.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292
  1. import {render, screen, userEvent, waitFor} from 'sentry-test/reactTestingLibrary';
  2. import IntegrationDetailedView from 'sentry/views/settings/organizationIntegrations/integrationDetailedView';
  3. describe('IntegrationDetailedView', function () {
  4. const ENDPOINT = '/organizations/org-slug/';
  5. const org = TestStubs.Organization({
  6. access: ['org:integrations', 'org:write'],
  7. });
  8. beforeEach(() => {
  9. MockApiClient.clearMockResponses();
  10. MockApiClient.addMockResponse({
  11. url: `/organizations/${org.slug}/config/integrations/?provider_key=bitbucket`,
  12. body: {
  13. providers: [
  14. {
  15. canAdd: true,
  16. canDisable: false,
  17. features: ['commits', 'issue-basic'],
  18. key: 'bitbucket',
  19. metadata: {
  20. aspects: {},
  21. author: 'The Sentry Team',
  22. description:
  23. 'Connect your Sentry organization to Bitbucket, enabling the following features:',
  24. features: [],
  25. issue_url:
  26. 'https://github.com/getsentry/sentry/issues/new?template=bug.yml&title=Bitbucket%20Integration:%20&labels=Component%3A%20Integrations',
  27. noun: 'Installation',
  28. source_url:
  29. 'https://github.com/getsentry/sentry/tree/master/src/sentry/integrations/bitbucket',
  30. },
  31. name: 'Bitbucket',
  32. setupDialog: {
  33. height: 600,
  34. url: '/organizations/sentry/integrations/bitbucket/setup/',
  35. width: 600,
  36. },
  37. slug: 'bitbucket',
  38. },
  39. ],
  40. },
  41. });
  42. MockApiClient.addMockResponse({
  43. url: `/organizations/${org.slug}/integrations/?provider_key=bitbucket&includeConfig=0`,
  44. body: [
  45. {
  46. accountType: null,
  47. configData: {},
  48. configOrganization: [],
  49. domainName: 'bitbucket.org/%7Bfb715533-bbd7-4666-aa57-01dc93dd9cc0%7D',
  50. icon: 'https://secure.gravatar.com/avatar/8b4cb68e40b74c90427d8262256bd1c8?d=https%3A%2F%2Favatar-management--avatars.us-west-2.prod.public.atl-paas.net%2Finitials%2FNN-0.png',
  51. id: '4',
  52. name: '{fb715533-bbd7-4666-aa57-01dc93dd9cc0}',
  53. provider: {
  54. aspects: {},
  55. canAdd: true,
  56. canDisable: false,
  57. features: ['commits', 'issue-basic'],
  58. key: 'bitbucket',
  59. name: 'Bitbucket',
  60. slug: 'bitbucket',
  61. },
  62. status: 'active',
  63. },
  64. ],
  65. });
  66. });
  67. it('shows integration name, status, and install button', function () {
  68. render(
  69. <IntegrationDetailedView
  70. {...TestStubs.routeComponentProps()}
  71. params={{integrationSlug: 'bitbucket'}}
  72. location={TestStubs.location({query: {}})}
  73. />
  74. );
  75. expect(screen.getByText('Bitbucket')).toBeInTheDocument();
  76. expect(screen.getByText('Installed')).toBeInTheDocument();
  77. expect(screen.getByRole('button', {name: 'Add integration'})).toBeEnabled();
  78. });
  79. it('view configurations', function () {
  80. render(
  81. <IntegrationDetailedView
  82. {...TestStubs.routeComponentProps()}
  83. params={{integrationSlug: 'bitbucket'}}
  84. location={TestStubs.location({query: {tab: 'configurations'}})}
  85. />
  86. );
  87. expect(screen.getByTestId('integration-name')).toHaveTextContent(
  88. '{fb715533-bbd7-4666-aa57-01dc93dd9cc0}'
  89. );
  90. expect(screen.getByRole('button', {name: 'Configure'})).toBeEnabled();
  91. });
  92. it('disables configure for members without access', function () {
  93. render(
  94. <IntegrationDetailedView
  95. {...TestStubs.routeComponentProps()}
  96. params={{integrationSlug: 'bitbucket'}}
  97. location={TestStubs.location({query: {tab: 'configurations'}})}
  98. />,
  99. {organization: TestStubs.Organization({access: ['org:read']})}
  100. );
  101. expect(screen.getByRole('button', {name: 'Configure'})).toBeDisabled();
  102. });
  103. it('allows members to configure github/gitlab', function () {
  104. MockApiClient.addMockResponse({
  105. url: `/organizations/${org.slug}/config/integrations/?provider_key=github`,
  106. body: {
  107. providers: [TestStubs.GitHubIntegrationProvider()],
  108. },
  109. });
  110. MockApiClient.addMockResponse({
  111. url: `/organizations/${org.slug}/integrations/?provider_key=github&includeConfig=0`,
  112. body: [
  113. {
  114. accountType: null,
  115. configData: {},
  116. configOrganization: [],
  117. domainName: 'github.com/%7Bfb715533-bbd7-4666-aa57-01dc93dd9cc0%7D',
  118. icon: 'https://secure.gravatar.com/avatar/8b4cb68e40b74c90427d8262256bd1c8?d=https%3A%2F%2Favatar-management--avatars.us-west-2.prod.public.atl-paas.net%2Finitials%2FNN-0.png',
  119. id: '4',
  120. name: '{fb715533-bbd7-4666-aa57-01dc93dd9cc0}',
  121. provider: {
  122. aspects: {},
  123. canAdd: true,
  124. canDisable: false,
  125. features: ['commits', 'issue-basic'],
  126. key: 'github',
  127. name: 'GitHub',
  128. slug: 'github',
  129. },
  130. status: 'active',
  131. },
  132. ],
  133. });
  134. render(
  135. <IntegrationDetailedView
  136. {...TestStubs.routeComponentProps()}
  137. params={{integrationSlug: 'github'}}
  138. location={TestStubs.location({query: {tab: 'configurations'}})}
  139. />,
  140. {organization: TestStubs.Organization({access: ['org:read']})}
  141. );
  142. expect(screen.getByRole('button', {name: 'Configure'})).toBeEnabled();
  143. });
  144. it('shows features tab for github only', function () {
  145. MockApiClient.addMockResponse({
  146. url: `/organizations/${org.slug}/config/integrations/?provider_key=github`,
  147. body: {
  148. providers: [TestStubs.GitHubIntegrationProvider()],
  149. },
  150. });
  151. MockApiClient.addMockResponse({
  152. url: `/organizations/${org.slug}/integrations/?provider_key=github&includeConfig=0`,
  153. body: [
  154. {
  155. accountType: null,
  156. configData: {},
  157. configOrganization: [],
  158. domainName: 'github.com/%7Bfb715533-bbd7-4666-aa57-01dc93dd9cc0%7D',
  159. icon: 'https://secure.gravatar.com/avatar/8b4cb68e40b74c90427d8262256bd1c8?d=https%3A%2F%2Favatar-management--avatars.us-west-2.prod.public.atl-paas.net%2Finitials%2FNN-0.png',
  160. id: '4',
  161. name: '{fb715533-bbd7-4666-aa57-01dc93dd9cc0}',
  162. provider: {
  163. aspects: {},
  164. canAdd: true,
  165. canDisable: false,
  166. features: ['commits', 'issue-basic'],
  167. key: 'github',
  168. name: 'GitHub',
  169. slug: 'github',
  170. },
  171. status: 'active',
  172. },
  173. ],
  174. });
  175. render(
  176. <IntegrationDetailedView
  177. {...TestStubs.routeComponentProps()}
  178. params={{integrationSlug: 'github'}}
  179. organization={org}
  180. location={TestStubs.location({query: {}})}
  181. />
  182. );
  183. expect(screen.getByText('features')).toBeInTheDocument();
  184. });
  185. it('cannot enable PR bot without GitHub integration', async function () {
  186. org.features.push('integrations-open-pr-comment');
  187. MockApiClient.addMockResponse({
  188. url: `/organizations/${org.slug}/config/integrations/?provider_key=github`,
  189. body: {
  190. providers: [TestStubs.GitHubIntegrationProvider()],
  191. },
  192. });
  193. MockApiClient.addMockResponse({
  194. url: `/organizations/${org.slug}/integrations/?provider_key=github&includeConfig=0`,
  195. body: [],
  196. });
  197. render(
  198. <IntegrationDetailedView
  199. {...TestStubs.routeComponentProps()}
  200. params={{integrationSlug: 'github'}}
  201. organization={org}
  202. location={TestStubs.location({query: {}})}
  203. />
  204. );
  205. await userEvent.click(screen.getByText('features'));
  206. expect(
  207. screen.getByRole('checkbox', {name: /Enable Comments on Suspect Pull Requests/})
  208. ).toBeDisabled();
  209. expect(
  210. screen.getByRole('checkbox', {name: /Enable Comments on Open Pull Requests/})
  211. ).toBeDisabled();
  212. });
  213. it('can enable github comment bots', async function () {
  214. org.features.push('integrations-open-pr-comment');
  215. MockApiClient.addMockResponse({
  216. url: `/organizations/${org.slug}/config/integrations/?provider_key=github`,
  217. body: {
  218. providers: [TestStubs.GitHubIntegrationProvider()],
  219. },
  220. });
  221. MockApiClient.addMockResponse({
  222. url: `/organizations/${org.slug}/integrations/?provider_key=github&includeConfig=0`,
  223. body: [TestStubs.GitHubIntegration()],
  224. });
  225. render(
  226. <IntegrationDetailedView
  227. {...TestStubs.routeComponentProps()}
  228. params={{integrationSlug: 'github'}}
  229. organization={org}
  230. location={TestStubs.location({query: {}})}
  231. />
  232. );
  233. await userEvent.click(screen.getByText('features'));
  234. const mock = MockApiClient.addMockResponse({
  235. url: ENDPOINT,
  236. method: 'PUT',
  237. });
  238. await userEvent.click(
  239. screen.getByRole('checkbox', {name: /Enable Comments on Suspect Pull Requests/})
  240. );
  241. await waitFor(() => {
  242. expect(mock).toHaveBeenCalledWith(
  243. ENDPOINT,
  244. expect.objectContaining({
  245. data: {githubPRBot: true},
  246. })
  247. );
  248. });
  249. await userEvent.click(
  250. screen.getByRole('checkbox', {name: /Enable Comments on Open Pull Requests/})
  251. );
  252. await waitFor(() => {
  253. expect(mock).toHaveBeenCalledWith(
  254. ENDPOINT,
  255. expect.objectContaining({
  256. data: {githubOpenPRBot: true},
  257. })
  258. );
  259. });
  260. });
  261. });