From ea3c26711032be83b12037b0c7eaf2411817155c Mon Sep 17 00:00:00 2001 From: Maham Akif Date: Tue, 3 Sep 2024 15:09:45 +0500 Subject: [PATCH] fix: actively playing video restarts due to query re-fetches --- src/components/video/VideoJS.jsx | 3 +- src/components/video/tests/VideoJS.test.jsx | 74 ++++++++++++++++++++- 2 files changed, 75 insertions(+), 2 deletions(-) diff --git a/src/components/video/VideoJS.jsx b/src/components/video/VideoJS.jsx index 8684949bd6..8a610116ee 100644 --- a/src/components/video/VideoJS.jsx +++ b/src/components/video/VideoJS.jsx @@ -74,7 +74,8 @@ const VideoJS = ({ options, onReady, customOptions }) => { videoRef.current.appendChild(videoElement); playerRef.current = videojs(videoElement, playerOptions, handlePlayerReady); - } else { + } else if (playerOptions?.sources[0]?.src !== playerRef?.current?.currentSrc()) { + // Only update player if the source changes playerRef.current.autoplay(playerOptions.autoplay); playerRef.current.src(playerOptions.sources); diff --git a/src/components/video/tests/VideoJS.test.jsx b/src/components/video/tests/VideoJS.test.jsx index b8ab9ee2dd..67e67639aa 100644 --- a/src/components/video/tests/VideoJS.test.jsx +++ b/src/components/video/tests/VideoJS.test.jsx @@ -2,7 +2,7 @@ import React from 'react'; import { waitFor } from '@testing-library/react'; import { renderWithRouter } from '../../../utils/tests'; import VideoJS from '../VideoJS'; -import { useTranscripts } from '../data'; +import { useTranscripts, usePlayerOptions } from '../data'; // Mocking the 'videojs-vjstranscribe' and 'useTranscripts' hook jest.mock('videojs-vjstranscribe'); @@ -185,4 +185,76 @@ describe('VideoJS', () => { expect(container.querySelector('video-js')).toBeFalsy(); }); }); + + it('Updates player source when src changes', () => { + // Mock video.js + jest.mock('video.js', () => { + const actualVideoJs = jest.requireActual('video.js'); + return { + ...actualVideoJs, + videojs: jest.fn().mockImplementation(() => ({ + playbackRates: jest.fn(), + src: jest.fn(), + dispose: jest.fn(), + autoplay: jest.fn(), + on: jest.fn(), + off: jest.fn(), + ready: jest.fn(), + isDisposed: jest.fn(), + currentSrc: jest.fn(), + })), + }; + }); + const mockPlayerInstance = { + autoplay: jest.fn(), + src: jest.fn(), + currentSrc: jest.fn(), + }; + + // Mock the implementation of videojs + // eslint-disable-next-line global-require + require('video.js').videojs.mockImplementation(() => mockPlayerInstance); + + // Initial mock return value for currentSrc + mockPlayerInstance.currentSrc.mockReturnValue('https://initial-domain.com/initial.m3u8'); + + // Mock the initial playerOptions + const initialOptions = { + autoplay: true, + responsive: true, + fluid: true, + controls: true, + sources: [{ src: 'https://initial-domain.com/initial.m3u8', type: 'application/x-mpegURL' }], + }; + + // Mock the updated playerOptions + const updatedOptions = { + autoplay: true, + responsive: true, + fluid: true, + controls: true, + sources: [{ src: 'https://test-domain.com/test-prefix/id.m3u8', type: 'application/x-mpegURL' }], + }; + + // Set mock return value for usePlayerOptions + usePlayerOptions.mockReturnValueOnce(initialOptions).mockReturnValueOnce(updatedOptions); + + // Simulate the logic that checks and updates the player source + const mockUpdatePlayerSource = (playerOptions) => { + if (playerOptions?.sources[0]?.src !== mockPlayerInstance.currentSrc()) { + // Only update player if the source changes + mockPlayerInstance.autoplay(playerOptions.autoplay); + mockPlayerInstance.src(playerOptions.sources); + } + }; + + // Simulate the initial state + mockUpdatePlayerSource(initialOptions); + + // Simulate the source change + mockUpdatePlayerSource(updatedOptions); + + // Verify src has been called with updated options + expect(mockPlayerInstance.src).toHaveBeenCalledWith([{ src: 'https://test-domain.com/test-prefix/id.m3u8', type: 'application/x-mpegURL' }]); + }); });