File size: 2,238 Bytes
36db998 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 | import { describe, it, expect, vi, beforeEach, afterEach } from 'vitest'
import { renderHook, act, waitFor } from '@testing-library/react'
import { useRecorder } from './useRecorder'
function setupAudio() {
const tracks = [{ stop: vi.fn() }]
const stream = { getTracks: () => tracks } as unknown as MediaStream
Object.defineProperty(navigator, 'mediaDevices', {
configurable: true, value: { getUserMedia: vi.fn().mockResolvedValue(stream) },
})
const node = { connect: vi.fn(), disconnect: vi.fn(), onaudioprocess: null as ((e: unknown) => void) | null }
const source = { connect: vi.fn(), disconnect: vi.fn() }
class FakeAC {
sampleRate = 16000
destination = {}
createMediaStreamSource = () => source
createScriptProcessor = () => node
close = vi.fn()
}
const w = window as unknown as Record<string, unknown>
w.AudioContext = FakeAC
return { tracks, node }
}
describe('useRecorder (WAV)', () => {
beforeEach(() => setupAudio())
afterEach(() => vi.restoreAllMocks())
it('records PCM and produces a WAV data URI, stopping mic tracks', async () => {
const { tracks, node } = setupAudio()
const { result } = renderHook(() => useRecorder())
await act(async () => { await result.current.start() })
await waitFor(() => expect(result.current.status).toBe('recording'))
// feed one audio buffer, then stop
act(() => node.onaudioprocess?.({ inputBuffer: { getChannelData: () => new Float32Array([0.1, -0.2, 0.3]) } }))
act(() => result.current.stop())
await waitFor(() => expect(result.current.status).toBe('recorded'))
await waitFor(() => expect(result.current.dataUri).toMatch(/^data:audio\/wav/))
expect(tracks[0].stop).toHaveBeenCalled() // mic released
})
it('reports unsupported when WebAudio is unavailable', async () => {
Object.defineProperty(navigator, 'mediaDevices', { configurable: true, value: { getUserMedia: vi.fn() } })
const w = window as unknown as Record<string, unknown>
w.AudioContext = undefined
w.webkitAudioContext = undefined
const { result } = renderHook(() => useRecorder())
await act(async () => { await result.current.start() })
expect(result.current.status).toBe('unsupported')
})
})
|