mirror of
https://github.com/navidrome/navidrome.git
synced 2026-05-03 06:51:16 +00:00
145 lines
3.8 KiB
JavaScript
145 lines
3.8 KiB
JavaScript
import { renderHook, act } from '@testing-library/react-hooks'
|
|
import { usePreloading } from './usePreloading'
|
|
import { describe, it, beforeEach, afterEach, vi, expect } from 'vitest'
|
|
|
|
describe('usePreloading', () => {
|
|
const mockPlayerState = {
|
|
queue: [
|
|
{ uuid: '1', musicSrc: 'song1.mp3' },
|
|
{ uuid: '2', musicSrc: 'song2.mp3' },
|
|
],
|
|
current: { uuid: '1' },
|
|
}
|
|
|
|
beforeEach(() => {
|
|
vi.clearAllMocks()
|
|
// Mock Audio constructor
|
|
global.Audio = vi.fn().mockImplementation(function () {
|
|
this.src = ''
|
|
this.addEventListener = vi.fn()
|
|
})
|
|
})
|
|
|
|
afterEach(() => {
|
|
delete global.Audio
|
|
})
|
|
|
|
it('should initialize with preloaded false', () => {
|
|
const { result } = renderHook(() => usePreloading(mockPlayerState))
|
|
|
|
expect(result.current.preloaded).toBe(false)
|
|
expect(typeof result.current.preloadNextSong).toBe('function')
|
|
expect(typeof result.current.resetPreloading).toBe('function')
|
|
})
|
|
|
|
it('should preload next song when called', () => {
|
|
const { result } = renderHook(() => usePreloading(mockPlayerState))
|
|
|
|
act(() => {
|
|
result.current.preloadNextSong()
|
|
})
|
|
|
|
expect(result.current.preloaded).toBe(true)
|
|
expect(global.Audio).toHaveBeenCalled()
|
|
expect(global.Audio.mock.instances[0].src).toBe('song2.mp3')
|
|
})
|
|
|
|
it('should not preload if already preloaded', () => {
|
|
const { result } = renderHook(() => usePreloading(mockPlayerState))
|
|
|
|
act(() => {
|
|
result.current.preloadNextSong()
|
|
})
|
|
|
|
expect(result.current.preloaded).toBe(true)
|
|
|
|
// Call again - should not create new Audio instance
|
|
const audioCallCount = global.Audio.mock.calls.length
|
|
act(() => {
|
|
result.current.preloadNextSong()
|
|
})
|
|
|
|
expect(global.Audio.mock.calls.length).toBe(audioCallCount)
|
|
})
|
|
|
|
it('should return null when no next song exists', () => {
|
|
const stateWithNoNext = {
|
|
queue: [{ uuid: '1', musicSrc: 'song1.mp3' }],
|
|
current: { uuid: '1' },
|
|
}
|
|
|
|
const { result } = renderHook(() => usePreloading(stateWithNoNext))
|
|
|
|
act(() => {
|
|
result.current.preloadNextSong()
|
|
})
|
|
|
|
expect(result.current.preloaded).toBe(false)
|
|
expect(global.Audio).not.toHaveBeenCalled()
|
|
})
|
|
|
|
it('should reset preloading state', () => {
|
|
const { result } = renderHook(() => usePreloading(mockPlayerState))
|
|
|
|
act(() => {
|
|
result.current.preloadNextSong()
|
|
})
|
|
|
|
expect(result.current.preloaded).toBe(true)
|
|
|
|
act(() => {
|
|
result.current.resetPreloading()
|
|
})
|
|
|
|
expect(result.current.preloaded).toBe(false)
|
|
})
|
|
|
|
it('should handle Audio constructor errors gracefully', () => {
|
|
const consoleSpy = vi.spyOn(console, 'error').mockImplementation(() => {})
|
|
|
|
global.Audio = vi.fn().mockImplementation(() => {
|
|
throw new Error('Audio creation failed')
|
|
})
|
|
|
|
const { result } = renderHook(() => usePreloading(mockPlayerState))
|
|
|
|
act(() => {
|
|
result.current.preloadNextSong()
|
|
})
|
|
|
|
expect(consoleSpy).toHaveBeenCalledWith(
|
|
'Error during preloading:',
|
|
expect.any(Error),
|
|
)
|
|
expect(result.current.preloaded).toBe(false) // Should remain false on error
|
|
|
|
consoleSpy.mockRestore()
|
|
})
|
|
|
|
it('should handle audio load errors gracefully', () => {
|
|
const consoleSpy = vi.spyOn(console, 'error').mockImplementation(() => {})
|
|
|
|
global.Audio = vi.fn().mockImplementation(function () {
|
|
this.src = ''
|
|
this.addEventListener = vi.fn((event, callback) => {
|
|
if (event === 'error') {
|
|
callback(new Event('error'))
|
|
}
|
|
})
|
|
})
|
|
|
|
const { result } = renderHook(() => usePreloading(mockPlayerState))
|
|
|
|
act(() => {
|
|
result.current.preloadNextSong()
|
|
})
|
|
|
|
expect(consoleSpy).toHaveBeenCalledWith(
|
|
'Preloading error:',
|
|
expect.any(Event),
|
|
)
|
|
|
|
consoleSpy.mockRestore()
|
|
})
|
|
})
|