mirror of
https://github.com/basicmachines-co/basic-memory
synced 2026-06-21 13:47:35 +00:00
128 lines
3.3 KiB
Python
128 lines
3.3 KiB
Python
"""Tests for base markdown parser."""
|
|
|
|
from dataclasses import dataclass
|
|
from pathlib import Path
|
|
from typing import Dict, Any, Optional
|
|
|
|
import pytest
|
|
|
|
from basic_memory.markdown.base_parser import MarkdownParser, ParseError, FileError
|
|
|
|
|
|
@dataclass
|
|
class TestDoc:
|
|
"""Simple document for testing."""
|
|
|
|
title: str
|
|
content: str
|
|
frontmatter: Dict[str, Any]
|
|
|
|
|
|
class TestParser(MarkdownParser[TestDoc]):
|
|
"""Concrete parser implementation for testing."""
|
|
|
|
async def parse_frontmatter(self, frontmatter: Dict[str, Any]) -> Dict[str, Any]:
|
|
"""Extract title from frontmatter."""
|
|
if "title" not in frontmatter:
|
|
raise ParseError("Missing required title")
|
|
return frontmatter
|
|
|
|
async def parse_content(self, title: str, sections: Dict[str, str]) -> str:
|
|
"""Process sections into content string."""
|
|
if "content" in sections:
|
|
return sections["content"]
|
|
# Join all section content if no direct content section
|
|
return "\n".join(sections.values())
|
|
|
|
async def parse_metadata(self, metadata: Optional[Dict[str, Any]]) -> Optional[Dict[str, Any]]: # pyright: ignore [reportIncompatibleMethodOverride]
|
|
"""Pass through metadata."""
|
|
return metadata
|
|
|
|
async def create_document(
|
|
self, frontmatter: Dict[str, Any], content: str, metadata: Optional[Dict[str, Any]]
|
|
) -> TestDoc:
|
|
"""Create test document."""
|
|
return TestDoc(title=frontmatter["title"], content=content, frontmatter=frontmatter)
|
|
|
|
|
|
@pytest.mark.asyncio
|
|
async def test_parse_valid_file(tmp_path: Path):
|
|
"""Test parsing valid file."""
|
|
# Create test file
|
|
test_file = tmp_path / "test.md"
|
|
content = """
|
|
---
|
|
title: Test Doc
|
|
metadata:
|
|
key: value
|
|
---
|
|
|
|
# Title
|
|
Test content
|
|
"""
|
|
test_file.write_text(content)
|
|
|
|
# Parse file
|
|
parser = TestParser()
|
|
doc = await parser.parse_file(test_file)
|
|
|
|
assert doc.title == "Test Doc"
|
|
assert doc.content == "Test content"
|
|
assert doc.frontmatter["metadata"] == {"key": "value"}
|
|
|
|
|
|
@pytest.mark.asyncio
|
|
async def test_parse_missing_file():
|
|
"""Test error on missing file."""
|
|
parser = TestParser()
|
|
with pytest.raises(FileError):
|
|
await parser.parse_file(Path("nonexistent.md"))
|
|
|
|
|
|
@pytest.mark.asyncio
|
|
async def test_parse_invalid_frontmatter(tmp_path: Path):
|
|
"""Test error on invalid frontmatter."""
|
|
test_file = tmp_path / "test.md"
|
|
content = """---
|
|
not_title: Test Doc
|
|
---
|
|
|
|
# Title
|
|
content"""
|
|
test_file.write_text(content)
|
|
|
|
parser = TestParser()
|
|
with pytest.raises(ParseError):
|
|
await parser.parse_file(test_file)
|
|
|
|
|
|
@pytest.mark.asyncio
|
|
async def test_parse_no_frontmatter(tmp_path: Path):
|
|
"""Test file with no frontmatter."""
|
|
test_file = tmp_path / "test.md"
|
|
content = """# Title
|
|
Just content"""
|
|
test_file.write_text(content)
|
|
|
|
parser = TestParser()
|
|
with pytest.raises(ParseError):
|
|
await parser.parse_file(test_file)
|
|
|
|
|
|
@pytest.mark.asyncio
|
|
async def test_parse_content_str():
|
|
"""Test parsing content string directly."""
|
|
content = """---
|
|
title: Test Doc
|
|
---
|
|
|
|
# Title
|
|
Test content"""
|
|
|
|
parser = TestParser()
|
|
doc = await parser.parse_content_str(content)
|
|
|
|
assert doc.title == "Test Doc"
|
|
assert doc.content == "Test content"
|
|
assert doc.frontmatter["title"] == "Test Doc"
|