import type { TagNode, TextNode } from '../../types/ast'; import { describe, it, expect } from 'vitest'; import { parse } from '../llm'; describe('LLM Parser', () => { it('should parse code blocks', () => { const input = `
\`\`\`js const x = 1; \`\`\`
`; const { ast } = parse(input); expect(ast).toHaveLength(1); const section = ast[0] as TagNode; const codeBlock = section.children?.find(n => (n as TextNode).textType === 'code'); expect(codeBlock).toBeDefined(); expect((codeBlock as TextNode).language).toBe('js'); }); it('should preserve whitespace around code blocks', () => { const input = `
Text before \`\`\`js const x = 1; \`\`\` Text after
`; const { ast } = parse(input); expect(ast).toHaveLength(1); const section = ast[0] as TagNode; const children = section.children || []; expect(children.some(n => (n as TextNode).textType === 'code')).toBe(true); expect(children.some(n => !(n as TextNode).textType && (n as TextNode).value.includes('Text before'))).toBe(true); expect(children.some(n => !(n as TextNode).textType && (n as TextNode).value.includes('Text after'))).toBe(true); }); it('requires capital letter for tag names', () => { const input = '
'; const { errors } = parse(input); expect(errors).toHaveLength(1); expect(errors[0].message).toBe('Tag names must start with a capital letter'); }); it('should parse tag attributes', () => { const input = '
Content
'; const { ast } = parse(input); const section = ast[0] as TagNode; expect(section.attributes).toMatchObject({ title: 'Test', hlevel: '2' }); }); it('should use tag name as title if not specified', () => { const input = '
Content
'; const { ast } = parse(input); const section = ast[0] as TagNode; expect(section.attributes).toMatchObject({ title: 'Section', hlevel: '2' }); }); describe('error handling', () => { it('detects mismatched tags', () => { const input = '
Content'; const { errors } = parse(input); expect(errors).toHaveLength(1); expect(errors[0].message).toContain('Mismatched tags'); }); it('handles unclosed tags', () => { const input = '
Content'; const { errors } = parse(input); expect(errors).toHaveLength(1); expect(errors[0].message).toContain('Mismatched tags'); }); it('provides location information', () => { const input = `
`; const { errors } = parse(input); expect(errors).toHaveLength(1); expect(errors[0].location).toBeDefined(); expect(errors[0].location.start.line).toBe(2); }); it('handles malformed code blocks', () => { const input = `
\`\`\`js const x = 1;
`; const { errors } = parse(input); expect(errors).toHaveLength(1); expect(errors[0].message).toBe('Unclosed code block'); }); }); });