replayPreview.spec.tsx 4.8 KB

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