131 lines
4.3 KiB
TypeScript
131 lines
4.3 KiB
TypeScript
import { describe, it, expect } from 'vitest';
|
|
import { parseAiResponse } from '@main/ai/schema.js';
|
|
|
|
describe('parseAiResponse', () => {
|
|
it('accepts valid Korean title, 3-line summary, kebab tags', () => {
|
|
const r = parseAiResponse({
|
|
title: '회의 요약',
|
|
summary: '첫 줄\n둘째 줄\n셋째 줄',
|
|
tags: ['api-timeout', 'meeting']
|
|
});
|
|
expect(r.title).toBe('회의 요약');
|
|
expect(r.summary.split('\n')).toHaveLength(3);
|
|
expect(r.tags).toEqual(['api-timeout', 'meeting']);
|
|
});
|
|
|
|
it('영어 title → (첨부 메모) placeholder fallback (vision graceful 처리)', () => {
|
|
const r = parseAiResponse({ title: 'English only', summary: 'a\nb\nc', tags: [] });
|
|
expect(r.title).toBe('(첨부 메모)');
|
|
});
|
|
|
|
it('null title/summary → placeholder coerce (vision 본문 빈 케이스)', () => {
|
|
const r = parseAiResponse({ title: null, summary: null, tags: [], due_date: null });
|
|
expect(r.title).toBe('(첨부 메모)');
|
|
expect(r.summary.startsWith('내용을 자동으로 정리하지 못했습니다')).toBe(true);
|
|
});
|
|
|
|
it('empty string title/summary → placeholder coerce', () => {
|
|
const r = parseAiResponse({ title: '', summary: '', tags: [] });
|
|
expect(r.title).toBe('(첨부 메모)');
|
|
expect(r.summary.length).toBeGreaterThan(0);
|
|
});
|
|
|
|
it('pads short summary to 3 lines', () => {
|
|
const r = parseAiResponse({ title: '제목', summary: '한 줄', tags: [] });
|
|
expect(r.summary.split('\n')).toHaveLength(3);
|
|
});
|
|
|
|
it('compresses long summary to 3 lines', () => {
|
|
const r = parseAiResponse({
|
|
title: '제목', summary: 'a\nb\nc\nd\ne', tags: []
|
|
});
|
|
const lines = r.summary.split('\n');
|
|
expect(lines).toHaveLength(3);
|
|
expect(lines[2]).toBe('c d e');
|
|
});
|
|
|
|
it('filters invalid tags', () => {
|
|
const r = parseAiResponse({
|
|
title: '제목', summary: 'a\nb\nc',
|
|
tags: ['good-tag', 'BadCase', 'has space', 'ok2', '']
|
|
});
|
|
expect(r.tags).toEqual(['good-tag', 'ok2']);
|
|
});
|
|
|
|
it('caps tags to 3', () => {
|
|
const r = parseAiResponse({
|
|
title: '제목', summary: 'a\nb\nc',
|
|
tags: ['a', 'b', 'c', 'd', 'e']
|
|
});
|
|
expect(r.tags).toHaveLength(3);
|
|
});
|
|
|
|
it('rejects non-object input', () => {
|
|
expect(() => parseAiResponse('nope')).toThrow();
|
|
});
|
|
|
|
it('parses note with valid due_date', () => {
|
|
const r = parseAiResponse({
|
|
title: '내일 회의',
|
|
summary: 'a\nb\nc',
|
|
tags: [],
|
|
due_date: '2026-04-27'
|
|
});
|
|
expect(r.dueDate).toBe('2026-04-27');
|
|
});
|
|
|
|
it('null due_date passes through', () => {
|
|
const r = parseAiResponse({
|
|
title: '내일 회의',
|
|
summary: 'a\nb\nc',
|
|
tags: []
|
|
});
|
|
expect(r.dueDate).toBeNull();
|
|
});
|
|
|
|
it('explicit null due_date passes through', () => {
|
|
const r = parseAiResponse({
|
|
title: '내일 회의',
|
|
summary: 'a\nb\nc',
|
|
tags: [],
|
|
due_date: null
|
|
});
|
|
expect(r.dueDate).toBeNull();
|
|
});
|
|
|
|
it('malformed due_date string → null coerce (vision graceful 처리)', () => {
|
|
const r = parseAiResponse({ title: '내일', summary: 'a\nb\nc', tags: [], due_date: 'tomorrow' });
|
|
expect(r.dueDate).toBeNull();
|
|
});
|
|
|
|
it('empty string due_date → null coerce', () => {
|
|
const r = parseAiResponse({ title: '내일', summary: 'a\nb\nc', tags: [], due_date: '' });
|
|
expect(r.dueDate).toBeNull();
|
|
});
|
|
|
|
it('coerces invalid date that passes regex (e.g. 2026-13-99) to null', () => {
|
|
const r = parseAiResponse({
|
|
title: '내일 회의',
|
|
summary: 'a\nb\nc',
|
|
tags: [],
|
|
due_date: '2026-13-99'
|
|
});
|
|
expect(r.dueDate).toBeNull();
|
|
});
|
|
|
|
it('parseAiResponse — notebook_match valid string', () => {
|
|
const r = parseAiResponse({ title: '제목입니다', summary: '한\n두\n셋', tags: [], due_date: null, notebook_match: '회사' });
|
|
expect(r.notebookMatch).toBe('회사');
|
|
});
|
|
|
|
it('parseAiResponse — notebook_match null', () => {
|
|
const r = parseAiResponse({ title: '제목입니다', summary: '한\n두\n셋', tags: [], due_date: null, notebook_match: null });
|
|
expect(r.notebookMatch).toBeNull();
|
|
});
|
|
|
|
it('parseAiResponse — notebook_match 누락 시 null', () => {
|
|
const r = parseAiResponse({ title: '제목입니다', summary: '한\n두\n셋', tags: [], due_date: null });
|
|
expect(r.notebookMatch).toBeNull();
|
|
});
|
|
});
|