index.spec.tsx 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175
  1. import {EnvironmentsFixture} from 'sentry-fixture/environments';
  2. import {OrganizationFixture} from 'sentry-fixture/organization';
  3. import {ProjectFixture} from 'sentry-fixture/project';
  4. import {UserFeedbackFixture} from 'sentry-fixture/userFeedback';
  5. import {initializeOrg} from 'sentry-test/initializeOrg';
  6. import {render, screen, userEvent} from 'sentry-test/reactTestingLibrary';
  7. import ProjectsStore from 'sentry/stores/projectsStore';
  8. import UserFeedback from 'sentry/views/userFeedback';
  9. describe('UserFeedback', function () {
  10. const {organization, router} = initializeOrg();
  11. const pageLinks =
  12. '<https://sentry.io/api/0/organizations/sentry/user-feedback/?statsPeriod=14d&cursor=0:0:1>; rel="previous"; results="false"; cursor="0:0:1", ' +
  13. '<https://sentry.io/api/0/organizations/sentry/user-feedback/?statsPeriod=14d&cursor=0:100:0>; rel="next"; results="true"; cursor="0:100:0"';
  14. const project = ProjectFixture({isMember: true});
  15. const routeProps = {
  16. routes: router.routes,
  17. route: {},
  18. router,
  19. location: router.location,
  20. routeParams: router.params,
  21. };
  22. beforeEach(function () {
  23. ProjectsStore.loadInitialData([project]);
  24. MockApiClient.addMockResponse({
  25. url: '/organizations/org-slug/user-feedback/',
  26. body: [UserFeedbackFixture()],
  27. headers: {Link: pageLinks},
  28. });
  29. MockApiClient.addMockResponse({
  30. url: '/organizations/org-slug/environments/',
  31. body: EnvironmentsFixture(),
  32. });
  33. });
  34. afterEach(function () {
  35. ProjectsStore.reset();
  36. });
  37. it('renders', async function () {
  38. const params = {
  39. organization: OrganizationFixture(),
  40. params: {
  41. orgId: organization.slug,
  42. },
  43. ...routeProps,
  44. };
  45. MockApiClient.addMockResponse({
  46. url: '/organizations/org-slug/projects/',
  47. body: [project],
  48. headers: {Link: pageLinks},
  49. });
  50. render(<UserFeedback {...params} />);
  51. expect(await screen.findByText('Something bad happened')).toBeInTheDocument();
  52. });
  53. it('renders no project message', function () {
  54. ProjectsStore.loadInitialData([]);
  55. const params = {
  56. organization: OrganizationFixture(),
  57. params: {
  58. orgId: organization.slug,
  59. },
  60. ...routeProps,
  61. };
  62. render(<UserFeedback {...params} />);
  63. expect(
  64. screen.getByText('You need at least one project to use this view')
  65. ).toBeInTheDocument();
  66. });
  67. it('renders empty state', async function () {
  68. MockApiClient.addMockResponse({
  69. url: '/organizations/org-slug/user-feedback/',
  70. body: [],
  71. });
  72. const params = {
  73. organization: OrganizationFixture(),
  74. params: {
  75. orgId: organization.slug,
  76. },
  77. ...routeProps,
  78. };
  79. render(<UserFeedback {...params} />);
  80. expect(await screen.findByTestId('user-feedback-empty')).toBeInTheDocument();
  81. });
  82. it('renders empty state with project query', async function () {
  83. MockApiClient.addMockResponse({
  84. url: '/organizations/org-slug/user-feedback/',
  85. body: [],
  86. });
  87. const params = {
  88. ...routeProps,
  89. organization: OrganizationFixture(),
  90. location: {
  91. ...routeProps.location,
  92. pathname: 'sentry',
  93. query: {project: '112'},
  94. search: '',
  95. },
  96. params: {
  97. orgId: organization.slug,
  98. },
  99. };
  100. render(<UserFeedback {...params} />);
  101. expect(await screen.findByTestId('user-feedback-empty')).toBeInTheDocument();
  102. });
  103. it('renders issue status filter', async function () {
  104. const params = {
  105. organization: OrganizationFixture(),
  106. params: {
  107. orgId: organization.slug,
  108. },
  109. ...routeProps,
  110. };
  111. render(<UserFeedback {...params} />);
  112. // "Unresolved" is selected by default
  113. const unresolved = screen.getByRole('radio', {name: 'Unresolved'});
  114. expect(unresolved).toBeInTheDocument();
  115. expect(unresolved).toBeChecked();
  116. // Select "All Issues"
  117. const all = screen.getByRole('radio', {name: 'All Issues'});
  118. expect(all).toBeInTheDocument();
  119. expect(all).not.toBeChecked();
  120. await userEvent.click(all);
  121. expect(router.replace).toHaveBeenCalledWith(
  122. expect.objectContaining({query: {status: ''}})
  123. );
  124. });
  125. it('renders empty state with multi project query', async function () {
  126. MockApiClient.addMockResponse({
  127. url: '/organizations/org-slug/user-feedback/',
  128. body: [],
  129. });
  130. const params = {
  131. ...routeProps,
  132. organization: OrganizationFixture(),
  133. location: {
  134. ...routeProps.location,
  135. pathname: 'sentry',
  136. query: {project: ['112', '113']},
  137. search: '',
  138. },
  139. params: {
  140. orgId: organization.slug,
  141. },
  142. };
  143. render(<UserFeedback {...params} />);
  144. expect(await screen.findByTestId('user-feedback-empty')).toBeInTheDocument();
  145. });
  146. });