index.spec.tsx 6.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218
  1. import {EventFixture} from 'sentry-fixture/event';
  2. import {OrganizationFixture} from 'sentry-fixture/organization';
  3. import {ProjectFixture} from 'sentry-fixture/project';
  4. import {RRWebInitFrameEventsFixture} from 'sentry-fixture/replay/rrweb';
  5. import {ReplayErrorFixture} from 'sentry-fixture/replayError';
  6. import {ReplayRecordFixture} from 'sentry-fixture/replayRecord';
  7. import {render, screen} from 'sentry-test/reactTestingLibrary';
  8. import EventReplay from 'sentry/components/events/eventReplay';
  9. import {
  10. useHasOrganizationSentAnyReplayEvents,
  11. useReplayOnboardingSidebarPanel,
  12. } from 'sentry/utils/replays/hooks/useReplayOnboarding';
  13. import useReplayReader from 'sentry/utils/replays/hooks/useReplayReader';
  14. import ReplayReader from 'sentry/utils/replays/replayReader';
  15. import useProjects from 'sentry/utils/useProjects';
  16. import type {ReplayError} from 'sentry/views/replays/types';
  17. jest.mock('sentry/utils/replays/hooks/useReplayOnboarding');
  18. jest.mock('sentry/utils/replays/hooks/useReplayReader');
  19. jest.mock('sentry/utils/useProjects');
  20. // Replay clip preview is very heavy, mock it out
  21. jest.mock(
  22. 'sentry/components/events/eventReplay/replayClipPreview',
  23. () =>
  24. function () {
  25. return <div data-test-id="replay-clip" />;
  26. }
  27. );
  28. const mockEventTimestamp = new Date('2022-09-22T16:59:41Z');
  29. const mockReplayId = '761104e184c64d439ee1014b72b4d83b';
  30. const mockErrors: ReplayError[] = [
  31. ReplayErrorFixture({
  32. id: '1',
  33. issue: 'JAVASCRIPT-101',
  34. 'issue.id': 101,
  35. 'error.value': ['Something bad happened.'],
  36. 'error.type': ['error'],
  37. 'project.name': 'javascript',
  38. timestamp: mockEventTimestamp.toISOString(),
  39. title: 'Something bad happened.',
  40. }),
  41. ReplayErrorFixture({
  42. id: '2',
  43. issue: 'JAVASCRIPT-102',
  44. 'issue.id': 102,
  45. 'error.value': ['Something bad happened 2.'],
  46. 'error.type': ['error'],
  47. 'project.name': 'javascript',
  48. timestamp: mockEventTimestamp.toISOString(),
  49. title: 'Something bad happened 2.',
  50. }),
  51. ];
  52. const mockReplay = ReplayReader.factory({
  53. replayRecord: ReplayRecordFixture({
  54. browser: {
  55. name: 'Chrome',
  56. version: '110.0.0',
  57. },
  58. }),
  59. errors: mockErrors,
  60. attachments: RRWebInitFrameEventsFixture({
  61. timestamp: new Date('Sep 22, 2022 4:58:39 PM UTC'),
  62. }),
  63. });
  64. jest.mocked(useReplayReader).mockImplementation(() => {
  65. return {
  66. attachments: [],
  67. errors: mockErrors,
  68. fetchError: undefined,
  69. fetching: false,
  70. onRetry: jest.fn(),
  71. projectSlug: ProjectFixture().slug,
  72. replay: mockReplay,
  73. replayId: mockReplayId,
  74. replayRecord: ReplayRecordFixture(),
  75. };
  76. });
  77. const mockIsFullscreen = jest.fn();
  78. jest.mock('screenfull', () => ({
  79. enabled: true,
  80. get isFullscreen() {
  81. return mockIsFullscreen();
  82. },
  83. request: jest.fn(),
  84. exit: jest.fn(),
  85. on: jest.fn(),
  86. off: jest.fn(),
  87. }));
  88. describe('EventReplay', function () {
  89. const MockUseReplayOnboardingSidebarPanel = jest.mocked(
  90. useReplayOnboardingSidebarPanel
  91. );
  92. const MockUseHasOrganizationSentAnyReplayEvents = jest.mocked(
  93. useHasOrganizationSentAnyReplayEvents
  94. );
  95. const organization = OrganizationFixture({
  96. features: ['session-replay'],
  97. });
  98. const mockEvent = EventFixture({
  99. entries: [],
  100. tags: [],
  101. platform: 'javascript',
  102. dateCreated: mockEventTimestamp.getTime(),
  103. });
  104. const defaultProps = {
  105. event: mockEvent,
  106. projectSlug: 'project-slug',
  107. };
  108. beforeEach(function () {
  109. const project = ProjectFixture({platform: 'javascript'});
  110. MockApiClient.addMockResponse({
  111. url: `/organizations/${organization.slug}/replay-count/`,
  112. method: 'GET',
  113. body: {},
  114. });
  115. jest.mocked(useProjects).mockReturnValue({
  116. fetchError: null,
  117. fetching: false,
  118. hasMore: false,
  119. initiallyLoaded: false,
  120. onSearch: () => Promise.resolve(),
  121. placeholders: [],
  122. projects: [project],
  123. });
  124. MockUseHasOrganizationSentAnyReplayEvents.mockReturnValue({
  125. hasOrgSentReplays: false,
  126. fetching: false,
  127. });
  128. MockUseReplayOnboardingSidebarPanel.mockReturnValue({
  129. activateSidebar: jest.fn(),
  130. });
  131. });
  132. it('should render the replay inline onboarding component when replays are enabled and the project supports replay', async function () {
  133. MockUseHasOrganizationSentAnyReplayEvents.mockReturnValue({
  134. hasOrgSentReplays: false,
  135. fetching: false,
  136. });
  137. MockUseReplayOnboardingSidebarPanel.mockReturnValue({
  138. activateSidebar: jest.fn(),
  139. });
  140. MockApiClient.addMockResponse({
  141. url: '/organizations/org-slug/prompts-activity/',
  142. body: {data: {dismissed_ts: null}},
  143. });
  144. render(<EventReplay {...defaultProps} />, {organization});
  145. expect(
  146. await screen.findByText('Watch the errors and latency issues your users face')
  147. ).toBeInTheDocument();
  148. });
  149. it('should render a replay when there is a replayId from tags', async function () {
  150. MockUseHasOrganizationSentAnyReplayEvents.mockReturnValue({
  151. hasOrgSentReplays: true,
  152. fetching: false,
  153. });
  154. MockUseReplayOnboardingSidebarPanel.mockReturnValue({
  155. activateSidebar: jest.fn(),
  156. });
  157. render(
  158. <EventReplay
  159. {...defaultProps}
  160. event={EventFixture({
  161. entries: [],
  162. tags: [{key: 'replayId', value: '761104e184c64d439ee1014b72b4d83b'}],
  163. platform: 'javascript',
  164. })}
  165. />,
  166. {organization}
  167. );
  168. expect(await screen.findByTestId('replay-clip')).toBeInTheDocument();
  169. });
  170. it('should render a replay when there is a replay_id from contexts', async function () {
  171. MockUseHasOrganizationSentAnyReplayEvents.mockReturnValue({
  172. hasOrgSentReplays: true,
  173. fetching: false,
  174. });
  175. MockUseReplayOnboardingSidebarPanel.mockReturnValue({
  176. activateSidebar: jest.fn(),
  177. });
  178. render(
  179. <EventReplay
  180. {...defaultProps}
  181. event={EventFixture({
  182. entries: [],
  183. tags: [],
  184. contexts: {
  185. replay: {
  186. replay_id: '761104e184c64d439ee1014b72b4d83b',
  187. },
  188. },
  189. platform: 'javascript',
  190. })}
  191. />,
  192. {organization}
  193. );
  194. expect(await screen.findByTestId('replay-clip')).toBeInTheDocument();
  195. });
  196. });