import { renderHook, act } from '@testing-library/react'; import { describe, it, expect, vi, beforeEach } from 'vitest'; import { AudioProvider, useAudio } from './AudioContext'; import { ReactNode } from 'react'; import { Track } from '@/types'; const wrapper = ({ children }: { children: ReactNode }) => ( {children} ); const mockTrack: Track = { id: '1', title: 'Test Track', artist: 'Test Artist', duration: '3:45', durationSec: 225, plays: 100, likes: 10, }; describe('AudioContext', () => { beforeEach(() => { vi.clearAllMocks(); vi.useFakeTimers(); }); afterEach(() => { vi.useRealTimers(); }); it('should provide audio context', () => { const { result } = renderHook(() => useAudio(), { wrapper }); expect(result.current).toBeDefined(); expect(result.current).toHaveProperty('currentTrack'); expect(result.current).toHaveProperty('isPlaying'); expect(result.current).toHaveProperty('queue'); expect(result.current).toHaveProperty('playTrack'); expect(result.current).toHaveProperty('togglePlay'); }); it('should have initial track', () => { const { result } = renderHook(() => useAudio(), { wrapper }); expect(result.current.currentTrack).toBeDefined(); expect(result.current.currentTrack).toHaveProperty('title'); }); it('should play a track', () => { const { result } = renderHook(() => useAudio(), { wrapper }); act(() => { result.current.playTrack(mockTrack); }); expect(result.current.currentTrack).toEqual(mockTrack); }); it('should toggle play/pause', () => { const { result } = renderHook(() => useAudio(), { wrapper }); const initialPlaying = result.current.isPlaying; act(() => { result.current.togglePlay(); }); expect(result.current.isPlaying).toBe(!initialPlaying); }); it('should set volume', () => { const { result } = renderHook(() => useAudio(), { wrapper }); act(() => { result.current.setVolume(50); }); expect(result.current.volume).toBe(50); }); it('should toggle mute', () => { const { result } = renderHook(() => useAudio(), { wrapper }); const initialMuted = result.current.isMuted; act(() => { result.current.toggleMute(); }); expect(result.current.isMuted).toBe(!initialMuted); }); it('should toggle shuffle', () => { const { result } = renderHook(() => useAudio(), { wrapper }); const initialShuffle = result.current.shuffle; act(() => { result.current.toggleShuffle(); }); expect(result.current.shuffle).toBe(!initialShuffle); }); it('should toggle repeat mode', () => { const { result } = renderHook(() => useAudio(), { wrapper }); act(() => { result.current.toggleRepeat(); }); expect(['off', 'all', 'one']).toContain(result.current.repeatMode); }); it('should seek to position', () => { const { result } = renderHook(() => useAudio(), { wrapper }); act(() => { result.current.seek(50); }); expect(result.current.progress).toBe(50); }); it('should add track to queue', () => { const { result } = renderHook(() => useAudio(), { wrapper }); const initialQueueLength = result.current.queue.length; act(() => { result.current.addToQueue(mockTrack); }); expect(result.current.queue.length).toBe(initialQueueLength + 1); }); it('should remove track from queue', () => { const { result } = renderHook(() => useAudio(), { wrapper }); const initialQueueLength = result.current.queue.length; if (initialQueueLength > 0) { const trackId = result.current.queue[0].id; act(() => { result.current.removeFromQueue(trackId); }); expect(result.current.queue.length).toBe(initialQueueLength - 1); } }); it('should clear queue', () => { const { result } = renderHook(() => useAudio(), { wrapper }); act(() => { result.current.clearQueue(); }); expect(result.current.queue.length).toBe(0); }); });