index.spec.tsx 5.0 KB

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