import { describe, it, expect, vi, beforeEach } from 'vitest'; import { LintUseCase, LintUseCaseInput, LintUseCaseOutput } from '../../src/usecases/LintUseCase.js'; import { DocumentType, ValidationContext, LintResult, Validator } from '../../src/core/types.js'; import { MarkdownParser } from '../../src/core/parser.js'; import { FileReader } from '../../src/infrastructure/FileReader.js'; // モックバリデーター class MockValidator implements Validator { readonly id = 'mock-validator'; readonly name = 'Mock Validator'; private results: LintResult[]; constructor(results: LintResult[] = []) { this.results = results; } validate(_context: ValidationContext): LintResult[] { return this.results; } } // モックドキュメントタイプ class MockDocumentType implements DocumentType { readonly id: string; readonly name: string; readonly validators: Validator[]; constructor(id: string, name: string, validators: Validator[] = []) { this.id = id; this.name = name; this.validators = validators; } } describe('LintUseCase', () => { let parser: MarkdownParser; let fileReader: FileReader; let useCase: LintUseCase; beforeEach(() => { parser = new MarkdownParser(); fileReader = new FileReader(); }); describe('execute', () => { it('バリデーターがない場合、空の結果を返す', async () => { const documentType = new MockDocumentType('test', 'Test Document'); useCase = new LintUseCase(parser, fileReader, documentType); const input: LintUseCaseInput = { content: '# テスト\n\nこれはテストです。', filePath: '/test/file.md', }; const output = await useCase.execute(input); expect(output.results).toEqual([]); expect(output.metadata.filePath).toBe('/test/file.md'); }); it('バリデーターからの結果を収集する', async () => { const mockResult: LintResult = { ruleId: 'test-001', ruleName: 'テストルール', severity: 'error', message: 'テストエラー', }; const validator = new MockValidator([mockResult]); const documentType = new MockDocumentType('test', 'Test Document', [validator]); useCase = new LintUseCase(parser, fileReader, documentType); const input: LintUseCaseInput = { content: '# テスト', filePath: '/test/file.md', }; const output = await useCase.execute(input); expect(output.results).toHaveLength(1); expect(output.results[0].ruleId).toBe('test-001'); }); it('複数のバリデーターからの結果を統合する', async () => { const result1: LintResult = { ruleId: 'test-001', ruleName: 'テストルール1', severity: 'error', message: 'エラー1', }; const result2: LintResult = { ruleId: 'test-002', ruleName: 'テストルール2', severity: 'warning', message: '警告1', }; const validator1 = new MockValidator([result1]); const validator2 = new MockValidator([result2]); const documentType = new MockDocumentType('test', 'Test Document', [validator1, validator2]); useCase = new LintUseCase(parser, fileReader, documentType); const input: LintUseCaseInput = { content: '# テスト', filePath: '/test/file.md', }; const output = await useCase.execute(input); expect(output.results).toHaveLength(2); expect(output.results.map(r => r.ruleId)).toContain('test-001'); expect(output.results.map(r => r.ruleId)).toContain('test-002'); }); it('frontmatterを抽出してメタデータに含める', async () => { const documentType = new MockDocumentType('test', 'Test Document'); useCase = new LintUseCase(parser, fileReader, documentType); const content = `--- title: テストタイトル author: テスト著者 --- # 本文`; const input: LintUseCaseInput = { content, filePath: '/test/file.md', }; const output = await useCase.execute(input); expect(output.metadata.frontmatter.title).toBe('テストタイトル'); expect(output.metadata.frontmatter.author).toBe('テスト著者'); }); it('ファイルパスからコンテンツを読み込む(filePathOnlyモード)', async () => { const documentType = new MockDocumentType('test', 'Test Document'); useCase = new LintUseCase(parser, fileReader, documentType); // ファイルが存在しない場合のテスト const input: LintUseCaseInput = { filePath: '/nonexistent/file.md', }; await expect(useCase.execute(input)).rejects.toThrow(); }); }); describe('executeFromFile', () => { it('ファイルパスからドキュメントをリントする', async () => { const mockResult: LintResult = { ruleId: 'test-001', ruleName: 'テストルール', severity: 'error', message: 'テストエラー', }; const validator = new MockValidator([mockResult]); const documentType = new MockDocumentType('test', 'Test Document', [validator]); useCase = new LintUseCase(parser, fileReader, documentType); // 存在しないファイルでエラーになることを確認 await expect(useCase.executeFromFile('/nonexistent/path.md')).rejects.toThrow(); }); }); });