index.spec.tsx 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193
  1. import selectEvent from 'react-select-event';
  2. import pick from 'lodash/pick';
  3. import {Organization} from 'sentry-fixture/organization';
  4. import {SentryApp} from 'sentry-fixture/sentryApp';
  5. import {render, screen, userEvent, waitFor} from 'sentry-test/reactTestingLibrary';
  6. import {textWithMarkupMatcher} from 'sentry-test/utils';
  7. import type {Organization as TOrganization} from 'sentry/types';
  8. import SentryAppExternalInstallation from 'sentry/views/sentryAppExternalInstallation';
  9. describe('SentryAppExternalInstallation', () => {
  10. let sentryApp: ReturnType<typeof TestStubs.SentryApp>,
  11. getOrgsMock: ReturnType<typeof MockApiClient.addMockResponse>,
  12. getOrgMock: ReturnType<typeof MockApiClient.addMockResponse>,
  13. getAppMock: ReturnType<typeof MockApiClient.addMockResponse>,
  14. getInstallationsMock: ReturnType<typeof MockApiClient.addMockResponse>,
  15. getFeaturesMock: ReturnType<typeof MockApiClient.addMockResponse>,
  16. org1: TOrganization,
  17. org1Lite: Pick<TOrganization, 'slug' | 'name' | 'id'>,
  18. org2: TOrganization,
  19. org2Lite: Pick<TOrganization, 'slug' | 'name' | 'id'>;
  20. beforeEach(() => {
  21. MockApiClient.clearMockResponses();
  22. org1 = Organization({
  23. slug: 'org1',
  24. name: 'Organization 1',
  25. });
  26. org2 = Organization({
  27. slug: 'org2',
  28. name: 'Organization 2',
  29. });
  30. org1Lite = pick(org1, ['slug', 'name', 'id']);
  31. org2Lite = pick(org2, ['slug', 'name', 'id']);
  32. sentryApp = SentryApp({
  33. status: 'published',
  34. redirectUrl: 'https://google.com',
  35. });
  36. getAppMock = MockApiClient.addMockResponse({
  37. url: `/sentry-apps/${sentryApp.slug}/`,
  38. body: sentryApp,
  39. });
  40. getFeaturesMock = MockApiClient.addMockResponse({
  41. url: `/sentry-apps/${sentryApp.slug}/features/`,
  42. body: [],
  43. });
  44. MockApiClient.addMockResponse({
  45. url: `/sentry-apps/${sentryApp.slug}/interaction/`,
  46. method: 'POST',
  47. statusCode: 200,
  48. body: {},
  49. });
  50. });
  51. describe('single organization', () => {
  52. beforeEach(() => {
  53. getOrgsMock = MockApiClient.addMockResponse({
  54. url: '/organizations/',
  55. body: [org1Lite],
  56. });
  57. getOrgMock = MockApiClient.addMockResponse({
  58. url: `/organizations/${org1.slug}/`,
  59. body: org1,
  60. });
  61. getInstallationsMock = MockApiClient.addMockResponse({
  62. url: `/organizations/${org1.slug}/sentry-app-installations/`,
  63. body: [],
  64. });
  65. });
  66. it('sets the org automatically', () => {
  67. render(
  68. <SentryAppExternalInstallation
  69. {...TestStubs.routeComponentProps()}
  70. params={{sentryAppSlug: sentryApp.slug}}
  71. />
  72. );
  73. expect(getAppMock).toHaveBeenCalled();
  74. expect(getOrgsMock).toHaveBeenCalled();
  75. expect(getOrgMock).toHaveBeenCalled();
  76. expect(getInstallationsMock).toHaveBeenCalled();
  77. expect(
  78. screen.getByText(
  79. textWithMarkupMatcher(
  80. 'You are installing Sample App for organization Organization 1'
  81. )
  82. )
  83. ).toBeInTheDocument();
  84. expect(screen.queryByText('Select an organization')).not.toBeInTheDocument();
  85. });
  86. it('installs and redirects', async () => {
  87. const installUrl = `/organizations/${org1.slug}/sentry-app-installations/`;
  88. const install = {
  89. uuid: 'fake-id',
  90. code: 'some-code',
  91. };
  92. const installMock = MockApiClient.addMockResponse({
  93. url: installUrl,
  94. method: 'POST',
  95. body: install,
  96. });
  97. render(
  98. <SentryAppExternalInstallation
  99. {...TestStubs.routeComponentProps()}
  100. params={{sentryAppSlug: sentryApp.slug}}
  101. />
  102. );
  103. await userEvent.click(await screen.findByTestId('install'));
  104. expect(installMock).toHaveBeenCalledWith(
  105. installUrl,
  106. expect.objectContaining({
  107. data: {slug: sentryApp.slug},
  108. })
  109. );
  110. await waitFor(() => {
  111. expect(window.location.assign).toHaveBeenCalledWith(
  112. `https://google.com/?code=${install.code}&installationId=${install.uuid}&orgSlug=${org1.slug}`
  113. );
  114. });
  115. (window.location.assign as jest.Mock).mockClear();
  116. });
  117. });
  118. describe('multiple organizations', () => {
  119. beforeEach(() => {
  120. getOrgsMock = MockApiClient.addMockResponse({
  121. url: '/organizations/',
  122. body: [org1Lite, org2Lite],
  123. });
  124. });
  125. it('renders org dropdown', () => {
  126. render(
  127. <SentryAppExternalInstallation
  128. {...TestStubs.routeComponentProps()}
  129. params={{sentryAppSlug: sentryApp.slug}}
  130. />
  131. );
  132. expect(getAppMock).toHaveBeenCalled();
  133. expect(getOrgsMock).toHaveBeenCalled();
  134. expect(screen.getByText('Select an organization')).toBeInTheDocument();
  135. });
  136. it('selecting org from dropdown loads the org through the API', async () => {
  137. getOrgMock = MockApiClient.addMockResponse({
  138. url: `/organizations/${org2.slug}/`,
  139. body: org2,
  140. });
  141. getInstallationsMock = MockApiClient.addMockResponse({
  142. url: `/organizations/${org2.slug}/sentry-app-installations/`,
  143. body: [],
  144. });
  145. render(
  146. <SentryAppExternalInstallation
  147. {...TestStubs.routeComponentProps()}
  148. params={{sentryAppSlug: sentryApp.slug}}
  149. />
  150. );
  151. await selectEvent.select(screen.getByText('Select an organization'), 'org2');
  152. expect(getOrgMock).toHaveBeenCalledTimes(1);
  153. expect(getOrgMock).toHaveBeenLastCalledWith(
  154. '/organizations/org2/',
  155. expect.anything()
  156. );
  157. expect(getInstallationsMock).toHaveBeenCalled();
  158. expect(getFeaturesMock).toHaveBeenCalled();
  159. await waitFor(() => expect(screen.getByTestId('install')).toBeEnabled());
  160. });
  161. });
  162. });