import { describe, it, expect, vi } from 'vitest'; import { classifyStatus } from '../../src/main/ai/classifyStatus'; import type { InferenceProvider } from '../../src/main/ai/InferenceProvider'; function makeProvider(generateRaw?: (p: string) => Promise): InferenceProvider { return { name: 'mock', generate: vi.fn(async () => { throw new Error('not used'); }), healthCheck: vi.fn(async () => ({ ok: true })), ...(generateRaw !== undefined ? { generateRaw } : {}) } as InferenceProvider; } describe('classifyStatus', () => { it('parses recommended status and rationale from valid AI response', async () => { const provider = makeProvider( vi.fn(async () => '{"recommended":"completed","rationale":"처리됨"}') ); const r = await classifyStatus({ provider, rawText: 't', summary: '', reason: '결재 끝' }); expect(r.recommended).toBe('completed'); expect(r.rationale).toBe('처리됨'); }); it('falls back to archived on parse failure (invalid JSON)', async () => { const provider = makeProvider(vi.fn(async () => 'not json')); const r = await classifyStatus({ provider, rawText: 't', summary: '', reason: 'r' }); expect(r.recommended).toBe('archived'); expect(r.rationale).toMatch(/판단 실패|보관/); }); it('falls back to archived on invalid status value', async () => { const provider = makeProvider( vi.fn(async () => '{"recommended":"unknown","rationale":"x"}') ); const r = await classifyStatus({ provider, rawText: 't', summary: '', reason: 'r' }); expect(r.recommended).toBe('archived'); }); it('handles provider throw', async () => { const provider = makeProvider( vi.fn(async () => { throw new Error('network'); }) ); const r = await classifyStatus({ provider, rawText: 't', summary: '', reason: 'r' }); expect(r.recommended).toBe('archived'); expect(r.rationale).toMatch(/판단 실패|보관/); }); it('falls back when provider lacks generateRaw method', async () => { const provider = makeProvider(); const r = await classifyStatus({ provider, rawText: 't', summary: '', reason: 'r' }); expect(r.recommended).toBe('archived'); expect(r.rationale).toMatch(/판단 실패|보관/); }); it('substitutes empty inputs with placeholder text in prompt', async () => { const generateRaw = vi.fn( async (_p: string) => '{"recommended":"archived","rationale":"ok"}' ); const provider = makeProvider(generateRaw); await classifyStatus({ provider, rawText: '', summary: '', reason: '' }); const prompt = generateRaw.mock.calls[0]?.[0] ?? ''; expect(prompt).toContain('(빈 메모)'); expect(prompt).toContain('(요약 없음)'); expect(prompt).toContain('(사유 없음)'); }); it('rationale defaults to empty string when missing/non-string', async () => { const provider = makeProvider( vi.fn(async () => '{"recommended":"completed"}') ); const r = await classifyStatus({ provider, rawText: 't', summary: '', reason: 'r' }); expect(r.recommended).toBe('completed'); expect(r.rationale).toBe(''); }); });