index.spec.tsx 8.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292
  1. import {ProjectFixture} from 'sentry-fixture/project';
  2. import {ProjectKeysFixture} from 'sentry-fixture/projectKeys';
  3. import {initializeOrg} from 'sentry-test/initializeOrg';
  4. import {
  5. render,
  6. renderGlobalModal,
  7. screen,
  8. userEvent,
  9. waitFor,
  10. } from 'sentry-test/reactTestingLibrary';
  11. import ProjectKeys from 'sentry/views/settings/project/projectKeys/list';
  12. describe('ProjectKeys', function () {
  13. const {organization, project, routerProps} = initializeOrg();
  14. const projectKeys = ProjectKeysFixture();
  15. let deleteMock: jest.Mock;
  16. beforeEach(function () {
  17. MockApiClient.clearMockResponses();
  18. MockApiClient.addMockResponse({
  19. url: `/projects/${organization.slug}/${project.slug}/keys/`,
  20. method: 'GET',
  21. body: projectKeys,
  22. });
  23. deleteMock = MockApiClient.addMockResponse({
  24. url: `/projects/${organization.slug}/${project.slug}/keys/${projectKeys[0].id}/`,
  25. method: 'DELETE',
  26. });
  27. });
  28. it('renders empty', function () {
  29. MockApiClient.clearMockResponses();
  30. MockApiClient.addMockResponse({
  31. url: `/projects/${organization.slug}/${project.slug}/keys/`,
  32. method: 'GET',
  33. body: [],
  34. });
  35. render(
  36. <ProjectKeys
  37. {...routerProps}
  38. project={project}
  39. params={{projectId: project.slug}}
  40. organization={organization}
  41. />
  42. );
  43. expect(
  44. screen.getByText('There are no keys active for this project.')
  45. ).toBeInTheDocument();
  46. });
  47. it('has clippable box', async function () {
  48. render(
  49. <ProjectKeys
  50. {...routerProps}
  51. organization={organization}
  52. params={{projectId: project.slug}}
  53. project={ProjectFixture()}
  54. />
  55. );
  56. const expandButton = screen.getByRole('button', {name: 'Expand'});
  57. await userEvent.click(expandButton);
  58. expect(expandButton).not.toBeInTheDocument();
  59. });
  60. it('renders for default project', function () {
  61. render(
  62. <ProjectKeys
  63. {...routerProps}
  64. organization={organization}
  65. params={{projectId: project.slug}}
  66. project={ProjectFixture({platform: 'other'})}
  67. />
  68. );
  69. const allDsn = screen.getAllByRole('textbox', {name: 'DSN URL'});
  70. expect(allDsn.length).toBe(1);
  71. const expandButton = screen.getByRole('button', {name: 'Expand'});
  72. const dsn = screen.getByRole('textbox', {name: 'DSN URL'});
  73. const minidumpEndpoint = screen.queryByRole('textbox', {
  74. name: 'Minidump Endpoint URL',
  75. });
  76. const unrealEndpoint = screen.queryByRole('textbox', {
  77. name: 'Unreal Engine Endpoint URL',
  78. });
  79. const securityHeaderEndpoint = screen.queryByRole('textbox', {
  80. name: 'Security Header Endpoint URL',
  81. });
  82. expect(expandButton).toBeInTheDocument();
  83. expect(dsn).toHaveValue(projectKeys[0].dsn.public);
  84. expect(minidumpEndpoint).toHaveValue(projectKeys[0].dsn.minidump);
  85. // this is empty in the default ProjectKey
  86. expect(unrealEndpoint).toHaveValue('');
  87. expect(securityHeaderEndpoint).toHaveValue(projectKeys[0].dsn.security);
  88. });
  89. it('renders for javascript project', function () {
  90. render(
  91. <ProjectKeys
  92. {...routerProps}
  93. organization={organization}
  94. params={{projectId: project.slug}}
  95. project={ProjectFixture({platform: 'javascript'})}
  96. />
  97. );
  98. const expandButton = screen.queryByRole('button', {name: 'Expand'});
  99. const dsn = screen.getByRole('textbox', {name: 'DSN URL'});
  100. const minidumpEndpoint = screen.queryByRole('textbox', {
  101. name: 'Minidump Endpoint URL',
  102. });
  103. const unrealEndpoint = screen.queryByRole('textbox', {
  104. name: 'Unreal Engine Endpoint URL',
  105. });
  106. const securityHeaderEndpoint = screen.queryByRole('textbox', {
  107. name: 'Security Header Endpoint URL',
  108. });
  109. expect(expandButton).not.toBeInTheDocument();
  110. expect(dsn).toHaveValue(projectKeys[0].dsn.public);
  111. expect(minidumpEndpoint).not.toBeInTheDocument();
  112. expect(unrealEndpoint).not.toBeInTheDocument();
  113. expect(securityHeaderEndpoint).not.toBeInTheDocument();
  114. // Loader Script is rendered
  115. expect(screen.getByText('Loader Script')).toBeInTheDocument();
  116. const loaderScript = screen.getByRole<HTMLInputElement>('textbox', {
  117. name: 'Loader Script',
  118. });
  119. expect(loaderScript).toHaveValue(
  120. `<script src='${projectKeys[0].dsn.cdn}' crossorigin="anonymous"></script>`
  121. );
  122. });
  123. it('renders for javascript-react project', function () {
  124. render(
  125. <ProjectKeys
  126. {...routerProps}
  127. organization={organization}
  128. params={{projectId: project.slug}}
  129. project={ProjectFixture({platform: 'javascript-react'})}
  130. />
  131. );
  132. const expandButton = screen.queryByRole('button', {name: 'Expand'});
  133. const dsn = screen.getByRole('textbox', {name: 'DSN URL'});
  134. const minidumpEndpoint = screen.queryByRole('textbox', {
  135. name: 'Minidump Endpoint URL',
  136. });
  137. const unrealEndpoint = screen.queryByRole('textbox', {
  138. name: 'Unreal Engine Endpoint URL',
  139. });
  140. const securityHeaderEndpoint = screen.queryByRole('textbox', {
  141. name: 'Security Header Endpoint URL',
  142. });
  143. expect(expandButton).not.toBeInTheDocument();
  144. expect(dsn).toHaveValue(projectKeys[0].dsn.public);
  145. expect(minidumpEndpoint).not.toBeInTheDocument();
  146. expect(unrealEndpoint).not.toBeInTheDocument();
  147. expect(securityHeaderEndpoint).not.toBeInTheDocument();
  148. expect(screen.queryByText('Loader Script')).not.toBeInTheDocument();
  149. });
  150. it('renders multiple keys', function () {
  151. const multipleProjectKeys = ProjectKeysFixture([
  152. {
  153. dsn: {
  154. secret:
  155. 'http://188ee45a58094d939428d8585aa6f662:a33bf9aba64c4bbdaf873bb9023b6d2c@dev.getsentry.net:8000/1',
  156. minidump:
  157. 'http://dev.getsentry.net:8000/api/1/minidump?sentry_key=188ee45a58094d939428d8585aa6f662',
  158. public: 'http://188ee45a58094d939428d8585aa6f662@dev.getsentry.net:8000/1',
  159. csp: 'http://dev.getsentry.net:8000/api/1/csp-report/?sentry_key=188ee45a58094d939428d8585aa6f662',
  160. security:
  161. 'http://dev.getsentry.net:8000/api/1/security-report/?sentry_key=188ee45a58094d939428d8585aa6f662',
  162. cdn: '',
  163. unreal: '',
  164. crons: '',
  165. },
  166. dateCreated: '2018-02-28T07:13:51.087Z',
  167. public: '188ee45a58094d939428d8585aa6f662',
  168. secret: 'a33bf9aba64c4bbdaf873bb9023b6d2c',
  169. name: 'Key 2',
  170. rateLimit: null,
  171. projectId: 1,
  172. id: '188ee45a58094d939428d8585aa6f662',
  173. isActive: true,
  174. label: 'Key 2',
  175. browserSdkVersion: 'latest',
  176. browserSdk: {
  177. choices: [
  178. ['latest', 'latest'],
  179. ['7.x', '7.x'],
  180. ['6.x', '6.x'],
  181. ['5.x', '5.x'],
  182. ['4.x', '4.x'],
  183. ],
  184. },
  185. dynamicSdkLoaderOptions: {
  186. hasPerformance: false,
  187. hasReplay: false,
  188. hasDebug: false,
  189. },
  190. },
  191. ]);
  192. MockApiClient.addMockResponse({
  193. url: `/projects/${organization.slug}/${project.slug}/keys/`,
  194. method: 'GET',
  195. body: multipleProjectKeys,
  196. });
  197. render(
  198. <ProjectKeys
  199. {...routerProps}
  200. organization={organization}
  201. params={{projectId: project.slug}}
  202. project={ProjectFixture({platform: 'other'})}
  203. />
  204. );
  205. const allDsn = screen.getAllByRole('textbox', {name: 'DSN URL'});
  206. expect(allDsn.length).toBe(2);
  207. });
  208. it('deletes key', async function () {
  209. render(
  210. <ProjectKeys
  211. {...routerProps}
  212. organization={organization}
  213. params={{projectId: project.slug}}
  214. project={ProjectFixture()}
  215. />
  216. );
  217. await userEvent.click(screen.getByRole('button', {name: 'Delete'}));
  218. renderGlobalModal();
  219. await userEvent.click(screen.getByTestId('confirm-button'));
  220. expect(deleteMock).toHaveBeenCalled();
  221. });
  222. it('disable and enables key', async function () {
  223. render(
  224. <ProjectKeys
  225. {...routerProps}
  226. organization={organization}
  227. params={{projectId: project.slug}}
  228. project={ProjectFixture()}
  229. />
  230. );
  231. const enableMock = MockApiClient.addMockResponse({
  232. url: `/projects/${organization.slug}/${project.slug}/keys/${projectKeys[0].id}/`,
  233. method: 'PUT',
  234. });
  235. renderGlobalModal();
  236. await userEvent.click(screen.getByRole('button', {name: 'Disable'}));
  237. await userEvent.click(screen.getByTestId('confirm-button'));
  238. await waitFor(() => {
  239. expect(screen.queryByRole('dialog')).not.toBeInTheDocument();
  240. });
  241. expect(enableMock).toHaveBeenCalledWith(
  242. expect.anything(),
  243. expect.objectContaining({
  244. data: {isActive: false},
  245. })
  246. );
  247. await userEvent.click(screen.getByRole('button', {name: 'Enable'}));
  248. await userEvent.click(screen.getByTestId('confirm-button'));
  249. expect(enableMock).toHaveBeenCalledWith(
  250. expect.anything(),
  251. expect.objectContaining({
  252. data: {isActive: true},
  253. })
  254. );
  255. });
  256. });