listContent.spec.tsx 5.6 KB

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