From 06a1aa87ef494c307ad0a977567970149ef03ea3 Mon Sep 17 00:00:00 2001 From: Maham Akif Date: Tue, 30 Jul 2024 21:15:27 +0500 Subject: [PATCH] fix: added test coverage and some nits --- .../microlearning/VideoDetailPage.jsx | 12 ++-- src/components/video/data/tests/hooks.test.js | 70 +++++++++++++++++++ src/components/video/tests/VideoJS.test.jsx | 66 ++++++++++++++++- .../video/tests/VideoPlayer.test.jsx | 2 +- 4 files changed, 143 insertions(+), 7 deletions(-) create mode 100644 src/components/video/data/tests/hooks.test.js diff --git a/src/components/microlearning/VideoDetailPage.jsx b/src/components/microlearning/VideoDetailPage.jsx index cc521a7989..e63b7784c8 100644 --- a/src/components/microlearning/VideoDetailPage.jsx +++ b/src/components/microlearning/VideoDetailPage.jsx @@ -78,11 +78,11 @@ const VideoDetailPage = () => {

{videoData?.courseTitle}

- + {videoData?.videoDuration && `(${videoData?.videoDuration} minutes)`} -

+

{videoData?.videoSummary}

{ videoData?.videoSkills?.length > 0 && ( @@ -110,9 +110,11 @@ const VideoDetailPage = () => { )} -
- -
+ { videoData?.videoUrl && ( +
+ +
+ )} {matches => matches && ( diff --git a/src/components/video/data/tests/hooks.test.js b/src/components/video/data/tests/hooks.test.js new file mode 100644 index 0000000000..1c0b24a2fb --- /dev/null +++ b/src/components/video/data/tests/hooks.test.js @@ -0,0 +1,70 @@ +import { renderHook } from '@testing-library/react-hooks'; +import { logError } from '@edx/frontend-platform/logging'; +import { useTranscripts } from '../hooks'; +import { fetchAndAddTranscripts } from '../service'; + +// Mocking dependencies +jest.mock('../service', () => ({ + fetchAndAddTranscripts: jest.fn(), +})); + +jest.mock('@edx/frontend-platform/logging', () => ({ + logError: jest.fn(), +})); + +describe('useTranscripts', () => { + const customOptions = { + showTranscripts: true, + transcriptUrls: { + en: 'https://example.com/transcript-en.txt', + }, + }; + const mockPlayer = {}; + + it('should set isLoading to true initially if showTranscripts is true', () => { + const { result } = renderHook(() => useTranscripts({ player: mockPlayer, customOptions })); + expect(result.current.isLoading).toBe(true); + }); + + it('should fetch and set textTracks and transcriptUrl correctly', async () => { + const textTracks = { en: 'https://example.com/transcript-en.txt' }; + fetchAndAddTranscripts.mockResolvedValueOnce(textTracks); + + const { result, waitForNextUpdate } = renderHook(() => useTranscripts({ player: mockPlayer, customOptions })); + + await waitForNextUpdate(); + + expect(result.current.isLoading).toBe(false); + expect(result.current.textTracks).toEqual(textTracks); + expect(result.current.transcriptUrl).toBe(textTracks.en); + }); + + it('should log error and set isLoading to false if fetching transcripts fails', async () => { + const errorMessage = 'Error fetching transcripts'; + fetchAndAddTranscripts.mockRejectedValueOnce(new Error(errorMessage)); + + const { result, waitForNextUpdate } = renderHook(() => useTranscripts({ player: mockPlayer, customOptions })); + + await waitForNextUpdate(); + + expect(logError).toHaveBeenCalledWith(`Error fetching transcripts for player: Error: ${errorMessage}`); + expect(result.current.isLoading).toBe(false); + expect(result.current.textTracks).toEqual([]); + expect(result.current.transcriptUrl).toBeNull(); + }); + + it('should not fetch transcripts if showTranscripts is false', async () => { + const customOptionsWithoutTranscripts = { + showTranscripts: false, + transcriptUrls: undefined, + }; + + const { result } = renderHook(() => useTranscripts({ + player: mockPlayer, + customOptions: customOptionsWithoutTranscripts, + })); + + expect(result.current.textTracks).toEqual([]); + expect(result.current.transcriptUrl).toBeNull(); + }); +}); diff --git a/src/components/video/tests/VideoJS.test.jsx b/src/components/video/tests/VideoJS.test.jsx index d2bcf0e8a5..c21aaf0be0 100644 --- a/src/components/video/tests/VideoJS.test.jsx +++ b/src/components/video/tests/VideoJS.test.jsx @@ -1,8 +1,15 @@ import React from 'react'; -import { VideoJS } from '..'; +import { waitFor } from '@testing-library/react'; import { renderWithRouter } from '../../../utils/tests'; +import VideoJS from '../VideoJS'; +import { useTranscripts } from '../data'; +// Mocking the 'videojs-vjstranscribe' and 'useTranscripts' hook jest.mock('videojs-vjstranscribe'); +jest.mock('../data', () => ({ + useTranscripts: jest.fn(), + usePlayerOptions: jest.fn(), +})); const hlsUrl = 'https://test-domain.com/test-prefix/id.m3u8'; const ytUrl = 'https://www.youtube.com/watch?v=oHg5SJYRHA0'; @@ -26,6 +33,14 @@ const YoutubeVideoOptions = { }; describe('VideoJS', () => { + beforeEach(() => { + useTranscripts.mockReturnValue({ + isLoading: false, + textTracks: {}, + transcriptUrl: null, + }); + }); + it('Renders VideoJS components correctly for HLS videos.', () => { const { container } = renderWithRouter(); expect(container.querySelector('.video-js-wrapper')).toBeTruthy(); @@ -39,4 +54,53 @@ describe('VideoJS', () => { expect(container.querySelector('.vjs-big-play-centered')).toBeTruthy(); expect(container.querySelector('video-js')).toBeTruthy(); }); + + it('Renders VideoJS components correctly with transcripts.', async () => { + const customOptions = { + showTranscripts: true, + transcriptUrls: { + en: 'https://example.com/transcript-en.txt', + }, + }; + + useTranscripts.mockReturnValue({ + isLoading: false, + textTracks: { + en: 'https://example.com/transcript-en.txt', + }, + transcriptUrl: 'https://example.com/transcript-en.txt', + }); + + const { container } = renderWithRouter(); + + await waitFor(() => { + expect(container.querySelector('.video-js-wrapper')).toBeTruthy(); + expect(container.querySelector('.vjs-big-play-centered')).toBeTruthy(); + expect(container.querySelector('video-js')).toBeTruthy(); + expect(container.querySelector('#vjs-transcribe')).toBeTruthy(); + }); + }); + + it('Does not initialize VideoJS player while transcripts are loading.', async () => { + const customOptions = { + showTranscripts: true, + transcriptUrls: { + en: 'https://example.com/transcript-en.txt', + }, + }; + + useTranscripts.mockReturnValue({ + isLoading: true, + textTracks: {}, + transcriptUrl: null, + }); + + const { container } = renderWithRouter(); + + await waitFor(() => { + expect(container.querySelector('.video-js-wrapper')).toBeTruthy(); + expect(container.querySelector('.vjs-big-play-centered')).toBeFalsy(); + expect(container.querySelector('video-js')).toBeFalsy(); + }); + }); }); diff --git a/src/components/video/tests/VideoPlayer.test.jsx b/src/components/video/tests/VideoPlayer.test.jsx index 83d0cd4a38..61711c6108 100644 --- a/src/components/video/tests/VideoPlayer.test.jsx +++ b/src/components/video/tests/VideoPlayer.test.jsx @@ -1,6 +1,6 @@ import React from 'react'; import { waitFor } from '@testing-library/react'; -import { VideoPlayer } from '..'; // Assuming VideoPlayer is exported as named export +import VideoPlayer from '../VideoPlayer'; import { renderWithRouter } from '../../../utils/tests'; const hlsUrl = 'https://test-domain.com/test-prefix/id.m3u8';