index.spec.tsx 8.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291
  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. },
  165. dateCreated: '2018-02-28T07:13:51.087Z',
  166. public: '188ee45a58094d939428d8585aa6f662',
  167. secret: 'a33bf9aba64c4bbdaf873bb9023b6d2c',
  168. name: 'Key 2',
  169. rateLimit: null,
  170. projectId: 1,
  171. id: '188ee45a58094d939428d8585aa6f662',
  172. isActive: true,
  173. label: 'Key 2',
  174. browserSdkVersion: 'latest',
  175. browserSdk: {
  176. choices: [
  177. ['latest', 'latest'],
  178. ['7.x', '7.x'],
  179. ['6.x', '6.x'],
  180. ['5.x', '5.x'],
  181. ['4.x', '4.x'],
  182. ],
  183. },
  184. dynamicSdkLoaderOptions: {
  185. hasPerformance: false,
  186. hasReplay: false,
  187. hasDebug: false,
  188. },
  189. },
  190. ]);
  191. MockApiClient.addMockResponse({
  192. url: `/projects/${organization.slug}/${project.slug}/keys/`,
  193. method: 'GET',
  194. body: multipleProjectKeys,
  195. });
  196. render(
  197. <ProjectKeys
  198. {...routerProps}
  199. organization={organization}
  200. params={{projectId: project.slug}}
  201. project={ProjectFixture({platform: 'other'})}
  202. />
  203. );
  204. const allDsn = screen.getAllByRole('textbox', {name: 'DSN URL'});
  205. expect(allDsn.length).toBe(2);
  206. });
  207. it('deletes key', async function () {
  208. render(
  209. <ProjectKeys
  210. {...routerProps}
  211. organization={organization}
  212. params={{projectId: project.slug}}
  213. project={ProjectFixture()}
  214. />
  215. );
  216. await userEvent.click(screen.getByRole('button', {name: 'Delete'}));
  217. renderGlobalModal();
  218. await userEvent.click(screen.getByTestId('confirm-button'));
  219. expect(deleteMock).toHaveBeenCalled();
  220. });
  221. it('disable and enables key', async function () {
  222. render(
  223. <ProjectKeys
  224. {...routerProps}
  225. organization={organization}
  226. params={{projectId: project.slug}}
  227. project={ProjectFixture()}
  228. />
  229. );
  230. const enableMock = MockApiClient.addMockResponse({
  231. url: `/projects/${organization.slug}/${project.slug}/keys/${projectKeys[0].id}/`,
  232. method: 'PUT',
  233. });
  234. renderGlobalModal();
  235. await userEvent.click(screen.getByRole('button', {name: 'Disable'}));
  236. await userEvent.click(screen.getByTestId('confirm-button'));
  237. await waitFor(() => {
  238. expect(screen.queryByRole('dialog')).not.toBeInTheDocument();
  239. });
  240. expect(enableMock).toHaveBeenCalledWith(
  241. expect.anything(),
  242. expect.objectContaining({
  243. data: {isActive: false},
  244. })
  245. );
  246. await userEvent.click(screen.getByRole('button', {name: 'Enable'}));
  247. await userEvent.click(screen.getByTestId('confirm-button'));
  248. expect(enableMock).toHaveBeenCalledWith(
  249. expect.anything(),
  250. expect.objectContaining({
  251. data: {isActive: true},
  252. })
  253. );
  254. });
  255. });