- npm workspaces 루트 (apps/*, packages/*) 세팅 - V1 전체를 apps/desktop/으로 git mv (src, resources, tests, sidecar, scripts, electron.vite.config.ts, electron-builder.yml, vitest.config.ts, tsconfig.node.json, tsconfig.web.json) - apps/desktop/package.json 신규 (name=@d3ro/desktop) - productName: 'd3ro-voice' 명시 — app.getName()을 고정하여 userData 경로 %APPDATA%\d3ro-voice\ 그대로 유지 (기존 DB/설정 연속성 보장) - 루트 package.json을 workspace 루트로 재구성, 공통 devDep만 유지 (typescript, eslint, prettier) - turbo.json, tsconfig.base.json 추가 (Turborepo 자체 설치는 별도 sub-phase) - memory/project_status.md 생성 (규칙 13) 검증: - npm run typecheck 통과 - npm run build 통과 (electron-vite main+preload+renderer) - npm run dev 실제 실행 → DB/핫키/Ollama 자동 실행 모두 정상
75 lines
2.4 KiB
TypeScript
75 lines
2.4 KiB
TypeScript
// tests/shared/errors.test.ts
|
|
// D3ROError + IPCResult 헬퍼 테스트
|
|
|
|
import { describe, it, expect } from 'vitest'
|
|
import { D3ROError, ErrorCode, ipcSuccess, ipcError } from '../../src/shared/errors'
|
|
|
|
describe('D3ROError', () => {
|
|
it('code, message, details를 올바르게 설정한다', () => {
|
|
const err = new D3ROError(ErrorCode.STTModelNotFound, 'Model not found', { modelId: 'large' })
|
|
|
|
expect(err.code).toBe(ErrorCode.STTModelNotFound)
|
|
expect(err.message).toBe('Model not found')
|
|
expect(err.details).toEqual({ modelId: 'large' })
|
|
expect(err.name).toBe('D3ROError')
|
|
expect(err instanceof Error).toBe(true)
|
|
})
|
|
|
|
it('toJSON으로 직렬화할 수 있다', () => {
|
|
const err = new D3ROError(ErrorCode.LLMServerUnreachable, 'Server down')
|
|
const json = err.toJSON()
|
|
|
|
expect(json.code).toBe(300)
|
|
expect(json.message).toBe('Server down')
|
|
expect(json.details).toBeUndefined()
|
|
})
|
|
|
|
it('fromJSON으로 역직렬화할 수 있다', () => {
|
|
const json = { code: ErrorCode.AudioDeviceNotFound, message: 'No mic' }
|
|
const err = D3ROError.fromJSON(json)
|
|
|
|
expect(err).toBeInstanceOf(D3ROError)
|
|
expect(err.code).toBe(ErrorCode.AudioDeviceNotFound)
|
|
expect(err.message).toBe('No mic')
|
|
})
|
|
})
|
|
|
|
describe('IPCResult helpers', () => {
|
|
it('ipcSuccess는 success: true + data를 반환한다', () => {
|
|
const result = ipcSuccess({ value: 42 })
|
|
|
|
expect(result.success).toBe(true)
|
|
if (result.success) {
|
|
expect(result.data).toEqual({ value: 42 })
|
|
}
|
|
})
|
|
|
|
it('ipcError는 success: false + error를 반환한다', () => {
|
|
const result = ipcError(ErrorCode.DBQueryFailed, 'Query failed', { table: 'history' })
|
|
|
|
expect(result.success).toBe(false)
|
|
if (!result.success) {
|
|
expect(result.error.code).toBe(ErrorCode.DBQueryFailed)
|
|
expect(result.error.message).toBe('Query failed')
|
|
expect(result.error.details).toEqual({ table: 'history' })
|
|
}
|
|
})
|
|
})
|
|
|
|
describe('ErrorCode', () => {
|
|
it('에러 코드 범위가 올바르다', () => {
|
|
// STT: 100-199
|
|
expect(ErrorCode.STTEngineNotInstalled).toBe(100)
|
|
expect(ErrorCode.STTGPUNotAvailable).toBe(140)
|
|
|
|
// LLM: 300-399
|
|
expect(ErrorCode.LLMServerUnreachable).toBe(300)
|
|
expect(ErrorCode.LLMPromptTooLong).toBe(331)
|
|
|
|
// Audio: 400-499
|
|
expect(ErrorCode.AudioDeviceNotFound).toBe(400)
|
|
|
|
// System: 900-999
|
|
expect(ErrorCode.UnknownError).toBe(999)
|
|
})
|
|
})
|