import { beforeEach, describe, expect, it, vi } from 'vitest' import { fireEvent, render, screen } from '@testing-library/react' import type { AudioTrack, VideoQuality } from '../../types' import { SettingsMenu } from './SettingsMenu' const { contextState } = vi.hoisted(() => ({ contextState: { value: null as any, }, })) vi.mock('../../contexts/PlayerContext', () => ({ usePlayerContext: () => contextState.value, })) const audioTracks: AudioTrack[] = [ { name: 'English', language: 'en', url: '', groupId: 'audio', }, ] const qualities: VideoQuality[] = [ { label: '1080p', height: 1080, levelIndex: 0 }, { label: '720p', height: 720, levelIndex: 1 }, ] const subtitles = [{ src: '/sub.vtt', lang: 'en', label: 'English' }] describe('SettingsMenu', () => { beforeEach(() => { contextState.value = { uiState: { controlsVisible: true, settingsOpen: true, volumeControlOpen: false, qualityMenuOpen: false, subtitleMenuOpen: false, }, videoState: { playing: false, currentTime: 0, duration: 0, buffered: 0, volume: 1, muted: false, playbackRate: 1, fullscreen: false, pictureInPicture: false, loading: false, error: null, seeking: false, isLiveBroadcast: false, }, settings: { quality: null, subtitle: null, subtitleStyle: {}, audioTrack: null, playbackRate: 1, }, setPlaybackRate: vi.fn(), setSubtitle: vi.fn(), setSubtitleStyle: vi.fn(), saveSubtitleStyle: vi.fn(), revertSubtitleStyle: vi.fn(), setAudioTrack: vi.fn(), setQuality: vi.fn(), toggleSettings: vi.fn(), subtitleStyleEditorEnabled: true, translations: { noSubtitlesAvailable: 'No subtitles available', subtitles: 'Subtitles', subtitleStyle: 'Subtitle Style', preview: 'Preview', save: 'Save', cancel: 'Cancel', reset: 'Reset', off: 'Off', auto: 'Auto', quality: 'Quality', speed: 'Speed', fontSize: 'Font Size', fontWeight: 'Font Weight', textColor: 'Text Color', backgroundColor: 'Background Color', backgroundOpacity: 'Background Opacity', normal: 'Normal', default: 'Default', audioTrack: 'Audio Track', settings: 'Settings', level: 'Level', play: 'Play', pause: 'Pause', mute: 'Mute', unmute: 'Unmute', enterFullscreen: 'Enter fullscreen', exitFullscreen: 'Exit fullscreen', enterPictureInPicture: 'Enter picture-in-picture', exitPictureInPicture: 'Exit picture-in-picture', videoProgress: 'Video progress', volume: 'Volume', live: 'LIVE', }, } }) it('does not render when settings are closed', () => { contextState.value.uiState.settingsOpen = false render() expect(screen.queryByText('Settings')).not.toBeInTheDocument() }) it('changes playback speed from speed submenu', () => { render() fireEvent.click(screen.getByText('Speed')) fireEvent.click(screen.getByText('1.5x')) expect(contextState.value.setPlaybackRate).toHaveBeenCalledWith(1.5) }) it('selects subtitle from submenu', () => { render() fireEvent.click(screen.getByText('Subtitles')) fireEvent.click(screen.getByRole('button', { name: 'English' })) expect(contextState.value.setSubtitle).toHaveBeenCalledWith(subtitles[0]) }) it('selects audio track from submenu', () => { render() fireEvent.click(screen.getByText('Audio Track')) fireEvent.click(screen.getByRole('button', { name: 'English' })) expect(contextState.value.setAudioTrack).toHaveBeenCalledWith(audioTracks[0]) }) it('selects quality from submenu', () => { render() fireEvent.click(screen.getByText('Quality')) fireEvent.click(screen.getByText('720p')) expect(contextState.value.setQuality).toHaveBeenCalledWith(qualities[1]) }) it('saves subtitle style from subtitle style editor', () => { render() fireEvent.click(screen.getByText('Subtitles')) fireEvent.click(screen.getByRole('button', { name: /Subtitle Style/i })) fireEvent.change(screen.getByLabelText('Font Size'), { target: { value: '30' } }) fireEvent.click(screen.getByRole('button', { name: 'Save' })) expect(contextState.value.saveSubtitleStyle).toHaveBeenCalledWith( expect.objectContaining({ fontSize: 30, }) ) }) })