import { describe, it, expect, beforeEach } from 'vitest'; import { FrontmatterValidator } from '../../../../src/domain/text/validators/FrontmatterValidator.js'; import { MarkdownParser } from '../../../../src/core/parser.js'; import type { ValidationContext, DocumentMetadata } from '../../../../src/core/types.js'; describe('FrontmatterValidator', () => { let validator: FrontmatterValidator; let parser: MarkdownParser; beforeEach(() => { validator = new FrontmatterValidator(); parser = new MarkdownParser(); }); function createContext(content: string): ValidationContext { const tree = parser.parse(content); const frontmatter = parser.extractFrontmatter(content); const metadata: DocumentMetadata = { filePath: '/test/file.md', title: typeof frontmatter.title === 'string' ? frontmatter.title : undefined, frontmatter, }; return { tree, content, metadata }; } describe('Validatorインターフェース', () => { it('正しいIDを持つ', () => { expect(validator.id).toBe('text/frontmatter'); }); it('正しい名前を持つ', () => { expect(validator.name).toBe('Frontmatter検証'); }); }); describe('frontmatter存在チェック', () => { it('frontmatterがない場合、エラーを返す', () => { const content = '# タイトル\n\n本文です。'; const context = createContext(content); const results = validator.validate(context); expect(results.length).toBeGreaterThan(0); const missingError = results.find(r => r.ruleId === 'text/frontmatter/missing'); expect(missingError).toBeDefined(); expect(missingError?.severity).toBe('error'); }); it('frontmatterがある場合、missing エラーを返さない', () => { const content = `--- title: テストタイトル draft: false --- # タイトル`; const context = createContext(content); const results = validator.validate(context); const missingError = results.find(r => r.ruleId === 'text/frontmatter/missing'); expect(missingError).toBeUndefined(); }); }); describe('titleフィールドチェック', () => { it('titleがない場合、エラーを返す', () => { const content = `--- draft: false --- # タイトル`; const context = createContext(content); const results = validator.validate(context); const titleError = results.find(r => r.ruleId === 'text/frontmatter/missing-title'); expect(titleError).toBeDefined(); expect(titleError?.severity).toBe('error'); expect(titleError?.message).toContain('title'); }); it('titleがある場合、titleエラーを返さない', () => { const content = `--- title: テストタイトル draft: false --- # タイトル`; const context = createContext(content); const results = validator.validate(context); const titleError = results.find(r => r.ruleId === 'text/frontmatter/missing-title'); expect(titleError).toBeUndefined(); }); }); describe('draftフィールドチェック', () => { it('draftがない場合、エラーを返す', () => { const content = `--- title: テストタイトル --- # タイトル`; const context = createContext(content); const results = validator.validate(context); const draftError = results.find(r => r.ruleId === 'text/frontmatter/missing-draft'); expect(draftError).toBeDefined(); expect(draftError?.severity).toBe('error'); }); it('draftがtrueでもfalseでもエラーを返さない', () => { const contentTrue = `--- title: テストタイトル draft: true --- # タイトル`; const contentFalse = `--- title: テストタイトル draft: false --- # タイトル`; const resultsTrue = validator.validate(createContext(contentTrue)); const resultsFalse = validator.validate(createContext(contentFalse)); expect(resultsTrue.find(r => r.ruleId === 'text/frontmatter/missing-draft')).toBeUndefined(); expect(resultsFalse.find(r => r.ruleId === 'text/frontmatter/missing-draft')).toBeUndefined(); }); }); describe('正常ケース', () => { it('正しいfrontmatterの場合、エラーを返さない', () => { const content = `--- title: 正しいテキスト教材 draft: false --- # 正しいタイトル 本文です。`; const context = createContext(content); const results = validator.validate(context); expect(results.length).toBe(0); }); }); describe('エラーメッセージの品質', () => { it('修正方法(suggestion)を含む', () => { const content = '# タイトル'; const context = createContext(content); const results = validator.validate(context); const missingError = results.find(r => r.ruleId === 'text/frontmatter/missing'); expect(missingError?.suggestion).toBeDefined(); expect(missingError?.suggestion).toContain('---'); }); it('詳細説明(detail)を含む', () => { const content = '# タイトル'; const context = createContext(content); const results = validator.validate(context); const missingError = results.find(r => r.ruleId === 'text/frontmatter/missing'); expect(missingError?.detail).toBeDefined(); }); }); });