131 lines
4.7 KiB
TypeScript
131 lines
4.7 KiB
TypeScript
import { describe, it, expect, vi } from 'vitest';
|
|
import { render, waitFor } from '@testing-library/react';
|
|
import { VideoPlayer } from './VideoPlayer';
|
|
|
|
describe('VideoPlayer', () => {
|
|
const defaultProps = {
|
|
src: 'https://example.com/video.mp4',
|
|
};
|
|
|
|
it('renders video player container', () => {
|
|
const { container } = render(<VideoPlayer {...defaultProps} />);
|
|
expect(container.querySelector('.video-player')).toBeInTheDocument();
|
|
});
|
|
|
|
it('renders video element', () => {
|
|
const { container } = render(<VideoPlayer {...defaultProps} />);
|
|
const video = container.querySelector('video');
|
|
expect(video).toBeInTheDocument();
|
|
});
|
|
|
|
it('renders with autoplay prop', () => {
|
|
const { container } = render(<VideoPlayer {...defaultProps} autoplay />);
|
|
const video = container.querySelector('video');
|
|
// VideoElement handles autoplay programmatically via play() method
|
|
expect(video).toBeInTheDocument();
|
|
});
|
|
|
|
it('renders with muted prop', () => {
|
|
const { container } = render(<VideoPlayer {...defaultProps} muted />);
|
|
const video = container.querySelector('video');
|
|
// Muted state is managed through VideoElement
|
|
expect(video).toBeInTheDocument();
|
|
});
|
|
|
|
it('applies loop when enabled', () => {
|
|
const { container } = render(<VideoPlayer {...defaultProps} loop />);
|
|
const video = container.querySelector('video');
|
|
expect(video).toHaveAttribute('loop');
|
|
});
|
|
|
|
it('applies custom className', () => {
|
|
const className = 'custom-player';
|
|
const { container } = render(<VideoPlayer {...defaultProps} className={className} />);
|
|
expect(container.querySelector('.video-player')).toHaveClass('video-player', className);
|
|
});
|
|
|
|
it('calls onPlay callback when play event fires', async () => {
|
|
const onPlay = vi.fn();
|
|
const { container } = render(<VideoPlayer {...defaultProps} onPlay={onPlay} />);
|
|
|
|
const video = container.querySelector('video') as HTMLVideoElement;
|
|
video.dispatchEvent(new Event('play'));
|
|
|
|
await waitFor(() => {
|
|
expect(onPlay).toHaveBeenCalled();
|
|
});
|
|
});
|
|
|
|
it('calls onPause callback when pause event fires', async () => {
|
|
const onPause = vi.fn();
|
|
const { container } = render(<VideoPlayer {...defaultProps} onPause={onPause} />);
|
|
|
|
const video = container.querySelector('video') as HTMLVideoElement;
|
|
video.dispatchEvent(new Event('pause'));
|
|
|
|
await waitFor(() => {
|
|
expect(onPause).toHaveBeenCalled();
|
|
});
|
|
});
|
|
|
|
it('calls onEnded callback when ended event fires', async () => {
|
|
const onEnded = vi.fn();
|
|
const { container } = render(<VideoPlayer {...defaultProps} onEnded={onEnded} />);
|
|
|
|
const video = container.querySelector('video') as HTMLVideoElement;
|
|
video.dispatchEvent(new Event('ended'));
|
|
|
|
await waitFor(() => {
|
|
expect(onEnded).toHaveBeenCalled();
|
|
});
|
|
});
|
|
|
|
it('calls onTimeUpdate callback with current time', async () => {
|
|
const onTimeUpdate = vi.fn();
|
|
const { container } = render(<VideoPlayer {...defaultProps} onTimeUpdate={onTimeUpdate} />);
|
|
|
|
const video = container.querySelector('video') as HTMLVideoElement;
|
|
Object.defineProperty(video, 'currentTime', { value: 10.5, configurable: true });
|
|
video.dispatchEvent(new Event('timeupdate'));
|
|
|
|
await waitFor(() => {
|
|
expect(onTimeUpdate).toHaveBeenCalledWith(10.5);
|
|
});
|
|
});
|
|
|
|
it('renders with subtitles prop', () => {
|
|
const subtitles = [
|
|
{ src: 'subtitles-en.vtt', srcLang: 'en', label: 'English' },
|
|
{ src: 'subtitles-tr.vtt', srcLang: 'tr', label: 'Türkçe' },
|
|
];
|
|
const { container } = render(<VideoPlayer {...defaultProps} subtitles={subtitles} />);
|
|
|
|
const video = container.querySelector('video') as HTMLVideoElement;
|
|
// Subtitles are added dynamically by VideoElement
|
|
expect(video).toBeInTheDocument();
|
|
});
|
|
|
|
it('renders without errors', () => {
|
|
const onError = vi.fn();
|
|
const { container } = render(<VideoPlayer {...defaultProps} onError={onError} />);
|
|
|
|
const video = container.querySelector('video') as HTMLVideoElement;
|
|
expect(video).toBeInTheDocument();
|
|
// Error handling is tested separately in integration tests
|
|
});
|
|
|
|
it('hides controls when controls prop is false', () => {
|
|
const { container } = render(<VideoPlayer {...defaultProps} controls={false} />);
|
|
const controls = container.querySelector('.controls');
|
|
expect(controls).not.toBeInTheDocument();
|
|
});
|
|
|
|
it('applies custom style', () => {
|
|
const style = { width: '800px', height: '450px' };
|
|
const { container } = render(<VideoPlayer {...defaultProps} style={style} />);
|
|
const playerElement = container.querySelector('.video-player') as HTMLElement;
|
|
expect(playerElement.style.width).toBe('800px');
|
|
expect(playerElement.style.height).toBe('450px');
|
|
});
|
|
});
|