feat: complete release preparation, 10+ ad mediation, CI/CD, and docker deployment
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
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
This commit is contained in:
parent
5cd1de6859
commit
708e20f747
406 changed files with 42464 additions and 6199 deletions
138
apps/desktop/tests/red/voice-command.usecase.test.ts
Normal file
138
apps/desktop/tests/red/voice-command.usecase.test.ts
Normal file
|
|
@ -0,0 +1,138 @@
|
|||
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)
|
||||
})
|
||||
})
|
||||
Loading…
Add table
Add a link
Reference in a new issue