listContent.spec.tsx 5.9 KB

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