listContent.spec.tsx 5.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193
  1. import {Organization} from 'sentry-fixture/organization';
  2. import {render, screen, waitFor} from 'sentry-test/reactTestingLibrary';
  3. import {Organization as TOrganization} from 'sentry/types';
  4. import useReplayList from 'sentry/utils/replays/hooks/useReplayList';
  5. import {
  6. useHaveSelectedProjectsSentAnyReplayEvents,
  7. useReplayOnboardingSidebarPanel,
  8. } from 'sentry/utils/replays/hooks/useReplayOnboarding';
  9. import useOrganization from 'sentry/utils/useOrganization';
  10. import useProjectSdkNeedsUpdate from 'sentry/utils/useProjectSdkNeedsUpdate';
  11. import ListPage from 'sentry/views/replays/list/listContent';
  12. jest.mock('sentry/utils/replays/hooks/useReplayOnboarding');
  13. jest.mock('sentry/utils/replays/hooks/useReplayPageview');
  14. jest.mock('sentry/utils/useOrganization');
  15. jest.mock('sentry/utils/useProjectSdkNeedsUpdate');
  16. jest.mock('sentry/utils/replays/hooks/useReplayList', () => {
  17. return {
  18. __esModule: true,
  19. default: jest.fn(() => {
  20. return {
  21. fetchError: undefined,
  22. isFetching: false,
  23. pageLinks: null,
  24. replays: [],
  25. };
  26. }),
  27. };
  28. });
  29. const mockUseReplayList = jest.mocked(useReplayList);
  30. const mockUseHaveSelectedProjectsSentAnyReplayEvents = jest.mocked(
  31. useHaveSelectedProjectsSentAnyReplayEvents
  32. );
  33. const mockUseProjectSdkNeedsUpdate = jest.mocked(useProjectSdkNeedsUpdate);
  34. const mockUseReplayOnboardingSidebarPanel = jest.mocked(useReplayOnboardingSidebarPanel);
  35. mockUseReplayOnboardingSidebarPanel.mockReturnValue({activateSidebar: jest.fn()});
  36. const AM1_FEATURES = [];
  37. const AM2_FEATURES = ['session-replay'];
  38. function getMockOrganization({features}: {features: string[]}) {
  39. const mockOrg = Organization({
  40. features,
  41. access: [],
  42. });
  43. jest.mocked(useOrganization).mockReturnValue(mockOrg);
  44. return mockOrg;
  45. }
  46. function getMockContext(mockOrg: TOrganization) {
  47. return TestStubs.routerContext([{organization: mockOrg}]);
  48. }
  49. describe('ReplayList', () => {
  50. beforeEach(() => {
  51. mockUseReplayList.mockClear();
  52. mockUseHaveSelectedProjectsSentAnyReplayEvents.mockClear();
  53. mockUseProjectSdkNeedsUpdate.mockClear();
  54. MockApiClient.clearMockResponses();
  55. MockApiClient.addMockResponse({
  56. url: '/organizations/org-slug/tags/',
  57. body: [],
  58. });
  59. });
  60. it('should render the onboarding panel when the org is on AM1', async () => {
  61. const mockOrg = getMockOrganization({features: AM1_FEATURES});
  62. mockUseHaveSelectedProjectsSentAnyReplayEvents.mockReturnValue({
  63. fetching: false,
  64. hasSentOneReplay: false,
  65. });
  66. mockUseProjectSdkNeedsUpdate.mockReturnValue({
  67. isError: false,
  68. isFetching: false,
  69. needsUpdate: false,
  70. });
  71. render(<ListPage />, {
  72. context: getMockContext(mockOrg),
  73. });
  74. await waitFor(() =>
  75. expect(screen.getByText('Get to the root cause faster')).toBeInTheDocument()
  76. );
  77. expect(mockUseReplayList).not.toHaveBeenCalled();
  78. });
  79. it('should render the onboarding panel when the org is on AM1 and has sent some replays', async () => {
  80. const mockOrg = getMockOrganization({features: AM1_FEATURES});
  81. mockUseHaveSelectedProjectsSentAnyReplayEvents.mockReturnValue({
  82. fetching: false,
  83. hasSentOneReplay: true,
  84. });
  85. mockUseProjectSdkNeedsUpdate.mockReturnValue({
  86. isError: false,
  87. isFetching: false,
  88. needsUpdate: false,
  89. });
  90. render(<ListPage />, {
  91. context: getMockContext(mockOrg),
  92. });
  93. await waitFor(() =>
  94. expect(screen.getByText('Get to the root cause faster')).toBeInTheDocument()
  95. );
  96. expect(mockUseReplayList).not.toHaveBeenCalled();
  97. });
  98. it('should render the onboarding panel when the org is on AM2 and has never sent a replay', async () => {
  99. const mockOrg = getMockOrganization({features: AM2_FEATURES});
  100. mockUseHaveSelectedProjectsSentAnyReplayEvents.mockReturnValue({
  101. fetching: false,
  102. hasSentOneReplay: false,
  103. });
  104. mockUseProjectSdkNeedsUpdate.mockReturnValue({
  105. isError: false,
  106. isFetching: false,
  107. needsUpdate: false,
  108. });
  109. render(<ListPage />, {
  110. context: getMockContext(mockOrg),
  111. });
  112. await waitFor(() =>
  113. expect(screen.getByText('Get to the root cause faster')).toBeInTheDocument()
  114. );
  115. expect(mockUseReplayList).not.toHaveBeenCalled();
  116. });
  117. it('should render the rage-click sdk update banner when the org is AM2, has sent replays, but the sdk version is low', async () => {
  118. const mockOrg = getMockOrganization({features: AM2_FEATURES});
  119. mockUseHaveSelectedProjectsSentAnyReplayEvents.mockReturnValue({
  120. fetching: false,
  121. hasSentOneReplay: true,
  122. });
  123. mockUseProjectSdkNeedsUpdate.mockReturnValue({
  124. isError: false,
  125. isFetching: false,
  126. needsUpdate: true,
  127. });
  128. mockUseReplayList.mockReturnValue({
  129. replays: [],
  130. isFetching: false,
  131. fetchError: undefined,
  132. pageLinks: null,
  133. });
  134. render(<ListPage />, {
  135. context: getMockContext(mockOrg),
  136. });
  137. await waitFor(() => {
  138. expect(screen.queryByText('Introducing Rage and Dead Clicks')).toBeInTheDocument();
  139. expect(screen.queryByTestId('replay-table')).toBeInTheDocument();
  140. });
  141. expect(mockUseReplayList).toHaveBeenCalled();
  142. });
  143. it('should fetch the replay table and show dead/rage tables when the org is on AM2, has sent some replays, and has a newer SDK version', async () => {
  144. const mockOrg = getMockOrganization({features: AM2_FEATURES});
  145. mockUseHaveSelectedProjectsSentAnyReplayEvents.mockReturnValue({
  146. fetching: false,
  147. hasSentOneReplay: true,
  148. });
  149. mockUseProjectSdkNeedsUpdate.mockReturnValue({
  150. isError: false,
  151. isFetching: false,
  152. needsUpdate: false,
  153. });
  154. mockUseReplayList.mockReturnValue({
  155. replays: [],
  156. isFetching: false,
  157. fetchError: undefined,
  158. pageLinks: null,
  159. });
  160. render(<ListPage />, {
  161. context: getMockContext(mockOrg),
  162. });
  163. await waitFor(() => expect(screen.queryAllByTestId('replay-table')).toHaveLength(3));
  164. expect(mockUseReplayList).toHaveBeenCalled();
  165. });
  166. });