projectDetail.spec.tsx 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132
  1. import {ProjectFixture} from 'sentry-fixture/project';
  2. import {initializeOrg} from 'sentry-test/initializeOrg';
  3. import {render, screen, userEvent, waitFor} from 'sentry-test/reactTestingLibrary';
  4. import {fetchOrganizationDetails} from 'sentry/actionCreators/organization';
  5. import * as pageFilters from 'sentry/actionCreators/pageFilters';
  6. import ProjectsStore from 'sentry/stores/projectsStore';
  7. import * as useApi from 'sentry/utils/useApi';
  8. import ProjectDetail from './projectDetail';
  9. jest.mock('sentry/actionCreators/organization');
  10. describe('ProjectDetail', function () {
  11. const {organization, router, projects} = initializeOrg();
  12. const project = projects[0];
  13. beforeEach(function () {
  14. ProjectsStore.init();
  15. });
  16. afterEach(function () {
  17. ProjectsStore.reset();
  18. });
  19. it('Render an error if project not found', async function () {
  20. ProjectsStore.loadInitialData([{...project, slug: 'slug'}]);
  21. const api = new MockApiClient();
  22. jest.spyOn(useApi, 'default').mockReturnValue(api);
  23. render(
  24. <ProjectDetail
  25. organization={organization}
  26. params={{projectId: project.id, orgId: organization.slug}}
  27. router={router}
  28. location={router.location}
  29. routes={router.routes}
  30. routeParams={router.params}
  31. route={{}}
  32. />
  33. );
  34. expect(await screen.findByText(/project could not be found/)).toBeInTheDocument();
  35. // By clicking on the retry button, we should attempt to fetch the organization details again
  36. await userEvent.click(screen.getByRole('button', {name: 'Retry'}));
  37. expect(fetchOrganizationDetails).toHaveBeenCalledWith(
  38. api,
  39. organization.slug,
  40. true,
  41. false
  42. );
  43. });
  44. it('Render warning if user is not a member of the project', async function () {
  45. ProjectsStore.loadInitialData([{...project, hasAccess: false}]);
  46. render(
  47. <ProjectDetail
  48. organization={organization}
  49. params={{projectId: project.id, orgId: organization.slug}}
  50. router={router}
  51. location={router.location}
  52. routes={router.routes}
  53. routeParams={router.params}
  54. route={{}}
  55. />
  56. );
  57. expect(
  58. await screen.findByText(/ask an admin to add your team to this project/i)
  59. ).toBeInTheDocument();
  60. });
  61. it('Render project details', async function () {
  62. ProjectsStore.loadInitialData([project]);
  63. MockApiClient.addMockResponse({
  64. url: `/projects/org-slug/project-slug/`,
  65. method: 'GET',
  66. body: ProjectFixture(),
  67. });
  68. render(
  69. <ProjectDetail
  70. organization={organization}
  71. params={{projectId: project.id, orgId: organization.slug}}
  72. router={router}
  73. location={router.location}
  74. routes={router.routes}
  75. routeParams={router.params}
  76. route={{}}
  77. />
  78. );
  79. expect(await screen.findByText(/project details/i)).toBeInTheDocument();
  80. });
  81. it('Sync project with slug', async function () {
  82. ProjectsStore.loadInitialData([project]);
  83. jest.spyOn(pageFilters, 'updateProjects');
  84. MockApiClient.addMockResponse({
  85. url: `/projects/org-slug/project-slug/`,
  86. method: 'GET',
  87. body: ProjectFixture(),
  88. });
  89. render(
  90. <ProjectDetail
  91. organization={organization}
  92. params={{projectId: project.id, orgId: organization.slug}}
  93. router={router}
  94. location={{
  95. ...router.location,
  96. query: {project: 'different-slug'},
  97. }}
  98. routes={router.routes}
  99. routeParams={router.params}
  100. route={{}}
  101. />
  102. );
  103. await waitFor(() => {
  104. expect(pageFilters.updateProjects).toHaveBeenCalledWith(
  105. [Number(project.id)],
  106. router
  107. );
  108. });
  109. });
  110. });