Player.jsx Component - Comprehensive Architecture Improvement, fix vitest

This commit is contained in:
Xavier Araque 2025-11-07 15:48:08 +01:00
parent e3534fa56b
commit d3c2beabd8
4 changed files with 48 additions and 51 deletions

View File

@ -1,22 +1,21 @@
/* eslint-env jest */
import { renderHook } from '@testing-library/react-hooks'
import { usePlayerState } from './usePlayerState'
import { useDispatch, useSelector } from 'react-redux'
import { describe, it, beforeEach, vi, expect } from 'vitest'
// Mock react-redux
jest.mock('react-redux', () => ({
useDispatch: jest.fn(),
useSelector: jest.fn(),
vi.mock('react-redux', () => ({
useDispatch: vi.fn(),
useSelector: vi.fn(),
}))
// Mock actions
jest.mock('../../actions', () => ({
clearQueue: jest.fn(() => ({ type: 'CLEAR_QUEUE' })),
currentPlaying: jest.fn(() => ({ type: 'CURRENT_PLAYING' })),
setPlayMode: jest.fn(() => ({ type: 'SET_PLAY_MODE' })),
setVolume: jest.fn(() => ({ type: 'SET_VOLUME' })),
syncQueue: jest.fn(() => ({ type: 'SYNC_QUEUE' })),
vi.mock('../../actions', () => ({
clearQueue: vi.fn(() => ({ type: 'CLEAR_QUEUE' })),
currentPlaying: vi.fn(() => ({ type: 'CURRENT_PLAYING' })),
setPlayMode: vi.fn(() => ({ type: 'SET_PLAY_MODE' })),
setVolume: vi.fn(() => ({ type: 'SET_VOLUME' })),
syncQueue: vi.fn(() => ({ type: 'SYNC_QUEUE' })),
}))
// Import the mocked actions
@ -30,10 +29,10 @@ describe('usePlayerState', () => {
volume: 0.8,
}
const mockDispatch = jest.fn()
const mockDispatch = vi.fn()
beforeEach(() => {
jest.clearAllMocks()
vi.clearAllMocks()
useDispatch.mockReturnValue(mockDispatch)
useSelector.mockReturnValue(mockPlayerState)
})

View File

@ -1,7 +1,6 @@
/* eslint-env jest */
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 = {
@ -13,11 +12,11 @@ describe('usePreloading', () => {
}
beforeEach(() => {
jest.clearAllMocks()
vi.clearAllMocks()
// Mock Audio constructor
global.Audio = jest.fn().mockImplementation(() => ({
global.Audio = vi.fn().mockImplementation(() => ({
src: '',
addEventListener: jest.fn(),
addEventListener: vi.fn(),
}))
})
@ -96,9 +95,9 @@ describe('usePreloading', () => {
})
it('should handle Audio constructor errors gracefully', () => {
const consoleSpy = jest.spyOn(console, 'error').mockImplementation(() => {})
const consoleSpy = vi.spyOn(console, 'error').mockImplementation(() => {})
global.Audio = jest.fn().mockImplementation(() => {
global.Audio = vi.fn().mockImplementation(() => {
throw new Error('Audio creation failed')
})
@ -118,18 +117,18 @@ describe('usePreloading', () => {
})
it('should handle audio load errors gracefully', () => {
const consoleSpy = jest.spyOn(console, 'error').mockImplementation(() => {})
const consoleSpy = vi.spyOn(console, 'error').mockImplementation(() => {})
const mockAudioInstance = {
src: '',
addEventListener: jest.fn((event, callback) => {
addEventListener: vi.fn((event, callback) => {
if (event === 'error') {
callback(new Event('error'))
}
}),
}
global.Audio = jest.fn().mockImplementation(() => mockAudioInstance)
global.Audio = vi.fn().mockImplementation(() => mockAudioInstance)
const { result } = renderHook(() => usePreloading(mockPlayerState))

View File

@ -1,11 +1,10 @@
/* eslint-env jest */
import { renderHook, act } from '@testing-library/react-hooks'
import { useReplayGain } from './useReplayGain'
import { describe, it, beforeEach, afterEach, vi, expect } from 'vitest'
// Mock calculateGain utility
jest.mock('../../utils/calculateReplayGain', () => ({
calculateGain: jest.fn(),
vi.mock('../../utils/calculateReplayGain', () => ({
calculateGain: vi.fn(),
}))
// Import the mocked module
@ -15,17 +14,17 @@ describe('useReplayGain', () => {
const mockCalculateGain = calculateReplayGain.calculateGain
beforeEach(() => {
jest.clearAllMocks()
vi.clearAllMocks()
// Mock Web Audio API
global.AudioContext = jest.fn().mockImplementation(() => ({
createMediaElementSource: jest.fn(() => ({
connect: jest.fn(),
global.AudioContext = vi.fn().mockImplementation(() => ({
createMediaElementSource: vi.fn(() => ({
connect: vi.fn(),
})),
createGain: jest.fn(() => ({
createGain: vi.fn(() => ({
gain: {
setValueAtTime: jest.fn(),
setValueAtTime: vi.fn(),
},
connect: jest.fn(),
connect: vi.fn(),
})),
currentTime: 0,
}))
@ -83,10 +82,10 @@ describe('useReplayGain', () => {
})
it('should handle Web Audio API errors gracefully', () => {
const consoleSpy = jest.spyOn(console, 'error').mockImplementation(() => {})
const consoleSpy = vi.spyOn(console, 'error').mockImplementation(() => {})
// Mock AudioContext to throw error
global.AudioContext = jest.fn().mockImplementation(() => {
global.AudioContext = vi.fn().mockImplementation(() => {
throw new Error('Web Audio API not supported')
})
@ -108,7 +107,7 @@ describe('useReplayGain', () => {
})
it('should handle gain application errors gracefully', () => {
const consoleSpy = jest.spyOn(console, 'error').mockImplementation(() => {})
const consoleSpy = vi.spyOn(console, 'error').mockImplementation(() => {})
const mockAudioInstance = { crossOrigin: '' }
const mockPlayerState = {
@ -119,17 +118,17 @@ describe('useReplayGain', () => {
// Mock gain.setValueAtTime to throw error
const mockGainNode = {
gain: {
setValueAtTime: jest.fn(() => {
setValueAtTime: vi.fn(() => {
throw new Error('Gain application failed')
}),
},
}
global.AudioContext = jest.fn().mockImplementation(() => ({
createMediaElementSource: jest.fn(() => ({
connect: jest.fn(),
global.AudioContext = vi.fn().mockImplementation(() => ({
createMediaElementSource: vi.fn(() => ({
connect: vi.fn(),
})),
createGain: jest.fn(() => mockGainNode),
createGain: vi.fn(() => mockGainNode),
currentTime: 0,
}))

View File

@ -1,12 +1,12 @@
/* eslint-env jest */
import { renderHook, act } from '@testing-library/react-hooks'
import { useScrobbling } from './useScrobbling'
import { describe, it, beforeEach, vi, expect } from 'vitest'
// Mock subsonic module
jest.mock('../../subsonic', () => ({
scrobble: jest.fn(),
nowPlaying: jest.fn(),
vi.mock('../../subsonic', () => ({
default: {},
scrobble: vi.fn(),
nowPlaying: vi.fn(),
}))
// Import the mocked module
@ -14,7 +14,7 @@ import * as subsonic from '../../subsonic'
// Mock dataProvider
const mockDataProvider = {
getOne: jest.fn(),
getOne: vi.fn(),
}
describe('useScrobbling', () => {
@ -26,10 +26,10 @@ describe('useScrobbling', () => {
current: { uuid: '1', trackId: 'track1' },
}
const mockDispatch = jest.fn()
const mockDispatch = vi.fn()
beforeEach(() => {
jest.clearAllMocks()
vi.clearAllMocks()
mockDataProvider.getOne.mockResolvedValue({ data: {} })
})
@ -131,7 +131,7 @@ describe('useScrobbling', () => {
})
it('should handle scrobbling errors gracefully', () => {
const consoleSpy = jest.spyOn(console, 'error').mockImplementation(() => {})
const consoleSpy = vi.spyOn(console, 'error').mockImplementation(() => {})
// const mockSubsonic = subsonic
subsonic.scrobble.mockImplementation(() => {
throw new Error('Scrobbling failed')