listContent.spec.tsx 6.1 KB

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