replayPreview.spec.tsx 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181
  1. import {Organization} from 'sentry-fixture/organization';
  2. import {RRWebInitFrameEvents} from 'sentry-fixture/replay/rrweb';
  3. import {ReplayRecordFixture} from 'sentry-fixture/replayRecord';
  4. import {initializeOrg} from 'sentry-test/initializeOrg';
  5. import {render as baseRender, screen} from 'sentry-test/reactTestingLibrary';
  6. import useReplayReader from 'sentry/utils/replays/hooks/useReplayReader';
  7. import ReplayReader from 'sentry/utils/replays/replayReader';
  8. import type RequestError from 'sentry/utils/requestError/requestError';
  9. import {OrganizationContext} from 'sentry/views/organizationContext';
  10. import {RouteContext} from 'sentry/views/routeContext';
  11. import ReplayPreview from './replayPreview';
  12. jest.mock('sentry/utils/replays/hooks/useReplayReader');
  13. const mockUseReplayReader = jest.mocked(useReplayReader);
  14. const mockOrgSlug = 'sentry-emerging-tech';
  15. const mockReplaySlug = 'replays:761104e184c64d439ee1014b72b4d83b';
  16. const mockReplayId = '761104e184c64d439ee1014b72b4d83b';
  17. const mockEventTimestampMs = new Date('2022-09-22T16:59:41Z').getTime();
  18. const mockButtonHref = `/organizations/${mockOrgSlug}/replays/761104e184c64d439ee1014b72b4d83b/?referrer=%2Forganizations%2F%3AorgId%2Fissues%2F%3AgroupId%2Freplays%2F&t=62&t_main=errors`;
  19. // Mock screenfull library
  20. jest.mock('screenfull', () => ({
  21. enabled: true,
  22. isFullscreen: false,
  23. request: jest.fn(),
  24. exit: jest.fn(),
  25. on: jest.fn(),
  26. off: jest.fn(),
  27. }));
  28. // Get replay data with the mocked replay reader params
  29. const mockReplay = ReplayReader.factory(
  30. {
  31. replayRecord: ReplayRecordFixture({
  32. browser: {
  33. name: 'Chrome',
  34. version: '110.0.0',
  35. },
  36. }),
  37. errors: [],
  38. attachments: RRWebInitFrameEvents({
  39. timestamp: new Date('Sep 22, 2022 4:58:39 PM UTC'),
  40. }),
  41. },
  42. {}
  43. );
  44. mockUseReplayReader.mockImplementation(() => {
  45. return {
  46. attachments: [],
  47. errors: [],
  48. fetchError: undefined,
  49. fetching: false,
  50. onRetry: jest.fn(),
  51. projectSlug: TestStubs.Project().slug,
  52. replay: mockReplay,
  53. replayId: mockReplayId,
  54. replayRecord: ReplayRecordFixture(),
  55. };
  56. });
  57. const render: typeof baseRender = children => {
  58. const {router, routerContext} = initializeOrg({
  59. router: {
  60. routes: [
  61. {path: '/'},
  62. {path: '/organizations/:orgId/issues/:groupId/'},
  63. {path: 'replays/'},
  64. ],
  65. location: {
  66. pathname: '/organizations/org-slug/replays/',
  67. query: {},
  68. },
  69. },
  70. });
  71. return baseRender(
  72. <RouteContext.Provider
  73. value={{
  74. router,
  75. location: router.location,
  76. params: router.params,
  77. routes: router.routes,
  78. }}
  79. >
  80. <OrganizationContext.Provider value={Organization()}>
  81. {children}
  82. </OrganizationContext.Provider>
  83. </RouteContext.Provider>,
  84. {context: routerContext}
  85. );
  86. };
  87. describe('ReplayPreview', () => {
  88. it('Should render a placeholder when is fetching the replay data', () => {
  89. // Change the mocked hook to return a loading state
  90. mockUseReplayReader.mockImplementationOnce(() => {
  91. return {
  92. attachments: [],
  93. errors: [],
  94. fetchError: undefined,
  95. fetching: true,
  96. onRetry: jest.fn(),
  97. projectSlug: TestStubs.Project().slug,
  98. replay: mockReplay,
  99. replayId: mockReplayId,
  100. replayRecord: ReplayRecordFixture(),
  101. };
  102. });
  103. render(
  104. <ReplayPreview
  105. orgSlug={mockOrgSlug}
  106. replaySlug={mockReplaySlug}
  107. eventTimestampMs={mockEventTimestampMs}
  108. />
  109. );
  110. expect(screen.getByTestId('replay-loading-placeholder')).toBeInTheDocument();
  111. });
  112. it('Should throw error when there is a fetch error', () => {
  113. // Change the mocked hook to return a fetch error
  114. mockUseReplayReader.mockImplementationOnce(() => {
  115. return {
  116. attachments: [],
  117. errors: [],
  118. fetchError: {status: 400} as RequestError,
  119. fetching: false,
  120. onRetry: jest.fn(),
  121. projectSlug: TestStubs.Project().slug,
  122. replay: null,
  123. replayId: mockReplayId,
  124. replayRecord: ReplayRecordFixture(),
  125. };
  126. });
  127. render(
  128. <ReplayPreview
  129. orgSlug={mockOrgSlug}
  130. replaySlug={mockReplaySlug}
  131. eventTimestampMs={mockEventTimestampMs}
  132. />
  133. );
  134. expect(screen.getByTestId('replay-error')).toBeVisible();
  135. });
  136. it('Should render details button when there is a replay', () => {
  137. render(
  138. <ReplayPreview
  139. orgSlug={mockOrgSlug}
  140. replaySlug={mockReplaySlug}
  141. eventTimestampMs={mockEventTimestampMs}
  142. />
  143. );
  144. const detailButton = screen.getByLabelText('Open Replay');
  145. expect(detailButton).toHaveAttribute('href', mockButtonHref);
  146. });
  147. it('Should render all its elements correctly', () => {
  148. render(
  149. <ReplayPreview
  150. orgSlug={mockOrgSlug}
  151. replaySlug={mockReplaySlug}
  152. eventTimestampMs={mockEventTimestampMs}
  153. />
  154. );
  155. // Expect replay view to be rendered
  156. expect(screen.getByTestId('player-container')).toBeInTheDocument();
  157. });
  158. });