index.spec.tsx 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183
  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. projects: [ProjectFixture({isMember: true})],
  75. }),
  76. params: {
  77. orgId: organization.slug,
  78. },
  79. ...routeProps,
  80. };
  81. render(<UserFeedback {...params} />);
  82. expect(await screen.findByTestId('user-feedback-empty')).toBeInTheDocument();
  83. });
  84. it('renders empty state with project query', async function () {
  85. MockApiClient.addMockResponse({
  86. url: '/organizations/org-slug/user-feedback/',
  87. body: [],
  88. });
  89. const params = {
  90. ...routeProps,
  91. organization: OrganizationFixture({
  92. projects: [ProjectFixture({isMember: true})],
  93. }),
  94. location: {
  95. ...routeProps.location,
  96. pathname: 'sentry',
  97. query: {project: '112'},
  98. search: '',
  99. },
  100. params: {
  101. orgId: organization.slug,
  102. },
  103. };
  104. render(<UserFeedback {...params} />);
  105. expect(await screen.findByTestId('user-feedback-empty')).toBeInTheDocument();
  106. });
  107. it('renders issue status filter', async function () {
  108. const params = {
  109. organization: OrganizationFixture({
  110. projects: [ProjectFixture({isMember: true})],
  111. }),
  112. params: {
  113. orgId: organization.slug,
  114. },
  115. ...routeProps,
  116. };
  117. render(<UserFeedback {...params} />);
  118. // "Unresolved" is selected by default
  119. const unresolved = screen.getByRole('radio', {name: 'Unresolved'});
  120. expect(unresolved).toBeInTheDocument();
  121. expect(unresolved).toBeChecked();
  122. // Select "All Issues"
  123. const all = screen.getByRole('radio', {name: 'All Issues'});
  124. expect(all).toBeInTheDocument();
  125. expect(all).not.toBeChecked();
  126. await userEvent.click(all);
  127. expect(router.replace).toHaveBeenCalledWith(
  128. expect.objectContaining({query: {status: ''}})
  129. );
  130. });
  131. it('renders empty state with multi project query', async function () {
  132. MockApiClient.addMockResponse({
  133. url: '/organizations/org-slug/user-feedback/',
  134. body: [],
  135. });
  136. const params = {
  137. ...routeProps,
  138. organization: OrganizationFixture({
  139. projects: [ProjectFixture({isMember: true})],
  140. }),
  141. location: {
  142. ...routeProps.location,
  143. pathname: 'sentry',
  144. query: {project: ['112', '113']},
  145. search: '',
  146. },
  147. params: {
  148. orgId: organization.slug,
  149. },
  150. };
  151. render(<UserFeedback {...params} />);
  152. expect(await screen.findByTestId('user-feedback-empty')).toBeInTheDocument();
  153. });
  154. });