d3ro-voice/apps/desktop/tests/red/voice-command.usecase.test.ts
Yun Chan 708e20f747
Some checks failed
CI Pipeline / Code Quality & Typecheck (push) Waiting to run
CI Pipeline / Test Suite (macos-latest) (push) Blocked by required conditions
CI Pipeline / Test Suite (ubuntu-latest) (push) Blocked by required conditions
CI Pipeline / Test Suite (windows-latest) (push) Blocked by required conditions
CI Pipeline / Build Validation (admin) (push) Blocked by required conditions
CI Pipeline / Build Validation (desktop) (push) Blocked by required conditions
Deploy Landing Page / deploy (push) Blocked by required conditions
Deploy Landing Page / build (push) Waiting to run
Release & Packaging Pipeline / Build & Publish Admin Docker Image (push) Failing after 8s
Release & Code Signing CA Pipeline / build-and-sign-windows (push) Failing after 1m51s
Build macOS / Build & Package (macOS) (push) Failing after 4s
Build macOS / Build & Package (macOS)-1 (push) Failing after 5s
Release & Code Signing CA Pipeline / build-and-sign-macos (push) Failing after 3s
Release & Packaging Pipeline / Package macOS Desktop App (push) Failing after 4s
Release & Packaging Pipeline / Package Windows Desktop App (push) Failing after 2m28s
Release & Packaging Pipeline / Publish Official GitHub Release (push) Has been skipped
feat: complete release preparation, 10+ ad mediation, CI/CD, and docker deployment
2026-08-20 11:12:05 +09:00

138 lines
4.7 KiB
TypeScript

import { describe, it, expect } from 'vitest'
import { IPC_CHANNELS } from '@d3ro/core/ipc-channels'
import { getVoiceCommandService } from '../../src/main/services/VoiceCommandService'
import { registerVoiceCommandHandlers } from '../../src/main/ipc/voice-command-handlers'
import { invokeIpc, useRedHarness } from './harness'
useRedHarness()
describe('유스케이스: 음성 단축키 매칭 / 토글 / 키워드 CRUD', () => {
it('초기에는 비활성이다', () => {
const svc = getVoiceCommandService()
svc.initialize()
expect(svc.isEnabled()).toBe(false)
})
it('비활성 상태에서는 키워드가 있어도 매칭하지 않는다', () => {
const svc = getVoiceCommandService()
svc.initialize()
svc.initDefaultKeywords()
const match = svc.match('번역해줘 이 문장')
expect(match.matched).toBe(false)
expect(match.cleanedText).toBe('번역해줘 이 문장')
})
it('활성 + 기본 키워드면 prefix 매칭한다', () => {
const svc = getVoiceCommandService()
svc.initialize()
svc.initDefaultKeywords()
svc.setEnabled(true)
const match = svc.match('번역해줘 이 문장')
expect(match.matched).toBe(true)
expect(match.instructionId).toBe('builtin-translate')
expect(match.cleanedText).toBe('이 문장')
expect(match.matchedKeyword).toBe('번역해줘')
})
it('요약 키워드도 매칭한다', () => {
const svc = getVoiceCommandService()
svc.initialize()
svc.initDefaultKeywords()
svc.setEnabled(true)
expect(svc.match('요약해줘 긴 글').instructionId).toBe('builtin-summarize')
})
it('매칭 실패 시 cleanedText 는 원문이다', () => {
const svc = getVoiceCommandService()
svc.initialize()
svc.initDefaultKeywords()
svc.setEnabled(true)
const match = svc.match('그냥 받아쓰기')
expect(match.matched).toBe(false)
expect(match.cleanedText).toBe('그냥 받아쓰기')
})
it('빈 텍스트는 매칭하지 않는다', () => {
const svc = getVoiceCommandService()
svc.initialize()
svc.initDefaultKeywords()
svc.setEnabled(true)
expect(svc.match(' ').matched).toBe(false)
})
it('사용자 키워드를 추가하면 contains 로 잡힌다', () => {
const svc = getVoiceCommandService()
svc.initialize()
svc.setEnabled(true)
svc.setKeywordsForInstruction('builtin-formal', [
{ keyword: '정중하게', matchMode: 'contains' },
])
const match = svc.match('이 메일 정중하게 써줘')
expect(match.matched).toBe(true)
expect(match.instructionId).toBe('builtin-formal')
})
it('같은 instruction 키워드를 덮어쓴다', () => {
const svc = getVoiceCommandService()
svc.initialize()
svc.setEnabled(true)
svc.setKeywordsForInstruction('builtin-formal', [
{ keyword: 'oldkw', matchMode: 'prefix' },
])
svc.setKeywordsForInstruction('builtin-formal', [
{ keyword: 'newkw', matchMode: 'prefix' },
])
expect(svc.match('oldkw x').matched).toBe(false)
expect(svc.match('newkw x').matched).toBe(true)
})
it('initDefaultKeywords 두 번은 규칙을 복제하지 않는다', () => {
const svc = getVoiceCommandService()
svc.initialize()
svc.initDefaultKeywords()
const n = svc.getAllRules().length
svc.initDefaultKeywords()
expect(svc.getAllRules().length).toBe(n)
})
it('비활성화하면 다시 매칭하지 않는다', () => {
const svc = getVoiceCommandService()
svc.initialize()
svc.initDefaultKeywords()
svc.setEnabled(true)
svc.setEnabled(false)
expect(svc.match('번역해줘 x').matched).toBe(false)
})
it('IPC setEnabled / isEnabled 왕복', async () => {
getVoiceCommandService().initialize()
registerVoiceCommandHandlers()
await invokeIpc(IPC_CHANNELS.VOICE_COMMAND.SET_ENABLED, { enabled: true })
const res = await invokeIpc(IPC_CHANNELS.VOICE_COMMAND.IS_ENABLED)
expect(res.success).toBe(true)
if (res.success) expect(res.data).toBe(true)
})
it('IPC getAll 은 배열이다', async () => {
const svc = getVoiceCommandService()
svc.initialize()
svc.initDefaultKeywords()
registerVoiceCommandHandlers()
const res = await invokeIpc(IPC_CHANNELS.VOICE_COMMAND.GET_ALL)
expect(res.success).toBe(true)
if (res.success) expect(Array.isArray(res.data)).toBe(true)
})
it('IPC setKeywords 후 매칭된다', async () => {
const svc = getVoiceCommandService()
svc.initialize()
svc.setEnabled(true)
registerVoiceCommandHandlers()
const set = await invokeIpc(IPC_CHANNELS.VOICE_COMMAND.SET_KEYWORDS, {
instructionId: 'builtin-translate',
keywords: [{ keyword: '영작', matchMode: 'prefix' }],
})
expect(set.success).toBe(true)
expect(svc.match('영작 hello').matched).toBe(true)
})
})