75 lines
2.3 KiB
TypeScript
75 lines
2.3 KiB
TypeScript
// tests/main/services/audio-capture-redteam-r1-3.test.ts
|
|
// SoX 가 장치를 못 열고 끝났을 때 'error' 리스너가 없어 ERR_UNHANDLED_ERROR 가 나고
|
|
// 뒤이은 'stopped' 가 영영 나가지 않던 버그의 회귀 테스트.
|
|
|
|
import { describe, it, expect, beforeEach, vi } from 'vitest'
|
|
import { EventEmitter } from 'events'
|
|
|
|
vi.mock('../../../src/main/services/LoggerService', () => ({
|
|
getLogger: () => ({ info: vi.fn(), warn: vi.fn(), error: vi.fn(), debug: vi.fn() }),
|
|
}))
|
|
|
|
vi.mock('../../../src/main/services/ConfigService', () => ({
|
|
configGet: vi.fn(() => 'usb-headset-gone'),
|
|
}))
|
|
|
|
vi.mock('../../../src/main/utils/paths', () => ({
|
|
getSoxPath: () => 'sox',
|
|
}))
|
|
|
|
class FakeProcess extends EventEmitter {
|
|
stdout = new EventEmitter()
|
|
stderr = new EventEmitter()
|
|
kill = vi.fn()
|
|
}
|
|
|
|
const spawned = vi.hoisted(() => ({ list: [] as unknown[] }))
|
|
|
|
vi.mock('child_process', async (importOriginal) => {
|
|
const actual = await importOriginal<typeof import('child_process')>()
|
|
return {
|
|
...actual,
|
|
spawn: vi.fn(() => {
|
|
const proc = new FakeProcess()
|
|
spawned.list.push(proc)
|
|
return proc
|
|
}),
|
|
}
|
|
})
|
|
|
|
type Module = typeof import('../../../src/main/services/AudioCaptureService')
|
|
let mod: Module
|
|
|
|
beforeEach(async () => {
|
|
vi.resetModules()
|
|
spawned.list = []
|
|
mod = await import('../../../src/main/services/AudioCaptureService')
|
|
mod.resetAudioCaptureServiceForTests()
|
|
})
|
|
|
|
describe('AudioCaptureService — 캡처 프로세스 종료', () => {
|
|
it("SoX 가 녹음 중 끝나도 예외 없이 'stopped'(device-lost) 를 알린다", async () => {
|
|
const audio = mod.getAudioCaptureService()
|
|
const stopped: string[] = []
|
|
audio.on('stopped', ({ reason }) => stopped.push(reason))
|
|
|
|
await audio.start()
|
|
expect(audio.state).toBe('capturing')
|
|
|
|
const proc = spawned.list[0] as FakeProcess
|
|
expect(() => proc.emit('close', 1)).not.toThrow()
|
|
|
|
expect(stopped).toEqual(['device-lost'])
|
|
expect(audio.state).toBe('error')
|
|
})
|
|
|
|
it('실패 뒤에도 다시 시작할 수 있다', async () => {
|
|
const audio = mod.getAudioCaptureService()
|
|
await audio.start()
|
|
;(spawned.list[0] as FakeProcess).emit('close', 1)
|
|
|
|
await audio.start()
|
|
expect(audio.state).toBe('capturing')
|
|
expect(spawned.list).toHaveLength(2)
|
|
})
|
|
})
|