198 lines
7.9 KiB
Python
198 lines
7.9 KiB
Python
from __future__ import annotations
|
|
|
|
from pathlib import Path
|
|
from pathlib import PurePosixPath
|
|
|
|
import pytest
|
|
|
|
from personal_mcp.registry.ingest.document import MarkdownDocument
|
|
from personal_mcp.registry.ingest.document import get_frontmatter_delim_idx
|
|
from personal_mcp.registry.ingest.document import get_raw_frontmatter
|
|
from personal_mcp.registry.ingest.document import walk_resources
|
|
|
|
pytestmark = pytest.mark.unit
|
|
|
|
|
|
class TestMarkdownDocument:
|
|
"""Covers MarkdownDocument construction and derived properties."""
|
|
|
|
class TestFromRoot:
|
|
"""Covers loading markdown documents from a resource root."""
|
|
|
|
def test_keys_by_relpath(self, tmp_path: Path) -> None:
|
|
"""Ensures from_root returns a mapping keyed by relative path."""
|
|
skills_dir = tmp_path / "skills" / "demo"
|
|
skills_dir.mkdir(parents=True)
|
|
(skills_dir / "SKILL.md").write_text("# demo\n", encoding="utf-8")
|
|
|
|
docs = MarkdownDocument.from_root(tmp_path)
|
|
|
|
assert set(docs) == {PurePosixPath("skills/demo/SKILL.md")}
|
|
|
|
def test_loads_markdown_only(self, tmp_path: Path) -> None:
|
|
"""Ensures from_root includes only markdown resources."""
|
|
(tmp_path / "a.md").write_text("a\n", encoding="utf-8")
|
|
(tmp_path / "b.MD").write_text("b\n", encoding="utf-8")
|
|
(tmp_path / "c.txt").write_text("c\n", encoding="utf-8")
|
|
|
|
docs = MarkdownDocument.from_root(tmp_path)
|
|
|
|
assert set(docs) == {PurePosixPath("a.md"), PurePosixPath("b.MD")}
|
|
|
|
def test_preserves_relpaths(self, tmp_path: Path) -> None:
|
|
"""Ensures from_root preserves PurePosixPath-style relative paths."""
|
|
nested = tmp_path / "skills" / "slug"
|
|
nested.mkdir(parents=True)
|
|
(nested / "SKILL.md").write_text("# slug\n", encoding="utf-8")
|
|
|
|
docs = MarkdownDocument.from_root(tmp_path)
|
|
[relpath] = docs.keys()
|
|
|
|
assert isinstance(relpath, PurePosixPath)
|
|
assert relpath == PurePosixPath("skills/slug/SKILL.md")
|
|
|
|
class TestFromResource:
|
|
"""Covers loading a single markdown document from a resource."""
|
|
|
|
def test_reads_utf8(self, tmp_path: Path) -> None:
|
|
"""Ensures from_resource reads text using UTF-8."""
|
|
resource = tmp_path / "index.md"
|
|
resource.write_text("caf\u00e9\n", encoding="utf-8")
|
|
|
|
doc = MarkdownDocument.from_resource(PurePosixPath("index.md"), resource)
|
|
|
|
assert doc.content == "caf\u00e9\n"
|
|
|
|
def test_sets_frontmatter(self, tmp_path: Path) -> None:
|
|
"""Ensures from_resource stores frontmatter when delimiters exist."""
|
|
resource = tmp_path / "index.md"
|
|
resource.write_text("---\nname: demo\n---\n# body\n", encoding="utf-8")
|
|
|
|
doc = MarkdownDocument.from_resource(PurePosixPath("index.md"), resource)
|
|
|
|
assert doc.frontmatter == "name: demo"
|
|
|
|
def test_none_frontmatter(self, tmp_path: Path) -> None:
|
|
"""Ensures from_resource sets frontmatter to None when absent."""
|
|
resource = tmp_path / "index.md"
|
|
resource.write_text("# no frontmatter\n", encoding="utf-8")
|
|
|
|
doc = MarkdownDocument.from_resource(PurePosixPath("index.md"), resource)
|
|
|
|
assert doc.frontmatter is None
|
|
|
|
class TestSkillSlugProperty:
|
|
"""Covers skill_slug derivation from document relative paths."""
|
|
|
|
def test_returns_slug(self) -> None:
|
|
"""Ensures skill_slug returns the slug for valid skills paths."""
|
|
doc = MarkdownDocument(relpath=PurePosixPath("skills/demo/SKILL.md"), content="#")
|
|
|
|
assert doc.skill_slug == "demo"
|
|
|
|
def test_none_for_non_skill(self) -> None:
|
|
"""Ensures skill_slug is None for non-skills paths."""
|
|
doc = MarkdownDocument(relpath=PurePosixPath("docs/index.md"), content="#")
|
|
|
|
assert doc.skill_slug is None
|
|
|
|
def test_none_for_incomplete_skill(self) -> None:
|
|
"""Ensures skill_slug is None for incomplete skills paths."""
|
|
doc = MarkdownDocument(relpath=PurePosixPath("skills/demo"), content="#")
|
|
|
|
assert doc.skill_slug is None
|
|
|
|
class TestPromptSlugProperty:
|
|
"""Covers prompt_slug derivation from document relative paths."""
|
|
|
|
def test_returns_slug(self) -> None:
|
|
"""Ensures prompt_slug returns the slug for valid prompt paths."""
|
|
doc = MarkdownDocument(relpath=PurePosixPath("prompts/demo/PROMPT.md"), content="#")
|
|
|
|
assert doc.prompt_slug == "demo"
|
|
|
|
def test_none_for_non_prompt(self) -> None:
|
|
"""Ensures prompt_slug is None for non-prompt paths."""
|
|
doc = MarkdownDocument(relpath=PurePosixPath("docs/index.md"), content="#")
|
|
|
|
assert doc.prompt_slug is None
|
|
|
|
def test_none_for_incomplete_prompt(self) -> None:
|
|
"""Ensures prompt_slug is None for incomplete prompt paths."""
|
|
doc = MarkdownDocument(relpath=PurePosixPath("prompts/demo"), content="#")
|
|
|
|
assert doc.prompt_slug is None
|
|
|
|
|
|
class TestWalkResources:
|
|
"""Covers recursive resource walking and markdown filtering behavior."""
|
|
|
|
def test_yields_markdown(self, tmp_path: Path) -> None:
|
|
"""Ensures walk_resources yields markdown files from nested directories."""
|
|
nested = tmp_path / "skills" / "alpha"
|
|
nested.mkdir(parents=True)
|
|
(nested / "SKILL.md").write_text("# alpha\n", encoding="utf-8")
|
|
(tmp_path / "index.md").write_text("# index\n", encoding="utf-8")
|
|
|
|
relpaths = [path for path, _ in walk_resources(tmp_path)]
|
|
|
|
assert relpaths == [
|
|
PurePosixPath("index.md"),
|
|
PurePosixPath("skills/alpha/SKILL.md"),
|
|
]
|
|
|
|
def test_ignores_other_suffixes(self, tmp_path: Path) -> None:
|
|
"""Ensures walk_resources excludes files with non-matching suffixes."""
|
|
(tmp_path / "a.md").write_text("a\n", encoding="utf-8")
|
|
(tmp_path / "b.txt").write_text("b\n", encoding="utf-8")
|
|
(tmp_path / "c.json").write_text("c\n", encoding="utf-8")
|
|
|
|
relpaths = [path for path, _ in walk_resources(tmp_path)]
|
|
|
|
assert relpaths == [PurePosixPath("a.md")]
|
|
|
|
def test_sorted_output(self, tmp_path: Path) -> None:
|
|
"""Ensures walk_resources yields entries in sorted child-name order."""
|
|
(tmp_path / "b.md").write_text("b\n", encoding="utf-8")
|
|
(tmp_path / "a.md").write_text("a\n", encoding="utf-8")
|
|
(tmp_path / "skills").mkdir()
|
|
(tmp_path / "skills" / "z.md").write_text("z\n", encoding="utf-8")
|
|
|
|
relpaths = [path for path, _ in walk_resources(tmp_path)]
|
|
|
|
assert relpaths == [
|
|
PurePosixPath("a.md"),
|
|
PurePosixPath("b.md"),
|
|
PurePosixPath("skills/z.md"),
|
|
]
|
|
|
|
def test_applies_prefix(self, tmp_path: Path) -> None:
|
|
"""Ensures walk_resources prepends the provided prefix to relpaths."""
|
|
(tmp_path / "index.md").write_text("# index\n", encoding="utf-8")
|
|
|
|
relpaths = [path for path, _ in walk_resources(tmp_path, prefix=PurePosixPath("docs"))]
|
|
|
|
assert relpaths == [PurePosixPath("docs/index.md")]
|
|
|
|
|
|
class TestFrontmatterParsing:
|
|
"""Covers frontmatter delimiter discovery and raw block extraction."""
|
|
|
|
def test_extracts_between_delimiters(self) -> None:
|
|
"""Ensures get_raw_frontmatter returns lines between first delimiters."""
|
|
raw = "---\nname: demo\ntags:\n - test\n---\n# body\n"
|
|
|
|
assert get_raw_frontmatter(raw) == "name: demo\ntags:\n - test"
|
|
|
|
def test_none_without_two_delimiters(self) -> None:
|
|
"""Ensures get_raw_frontmatter returns None without two delimiters."""
|
|
raw = "---\nname: demo\n# body\n"
|
|
|
|
assert get_raw_frontmatter(raw) is None
|
|
|
|
def test_allows_leading_whitespace(self) -> None:
|
|
"""Ensures delimiter detection accepts lines with leading whitespace."""
|
|
raw = " ---\nname: demo\n ---\n# body\n"
|
|
|
|
assert list(get_frontmatter_delim_idx(raw)) == [0, 2]
|