from __future__ import annotations from collections.abc import Callable from pathlib import Path import pytest from personal_mcp.registry.ingest.document import MarkdownDocument from personal_mcp.registry.ingest.prompt import PromptFilesBundle from personal_mcp.registry.ingest.prompt import group_prompt_paths pytestmark = pytest.mark.unit MakeDoc = Callable[[str], MarkdownDocument] class TestPromptFilesBundle: """Covers PromptFilesBundle construction and path-based categorization.""" class TestFromRoot: """Covers bundle creation from resource roots.""" def test_builds_bundles(self, tmp_path: Path) -> None: """Ensures from_root builds bundles from discovered markdown docs.""" alpha = tmp_path / "prompts" / "alpha" beta = tmp_path / "prompts" / "beta" alpha.mkdir(parents=True) beta.mkdir(parents=True) (alpha / "PROMPT.md").write_text("# alpha\n", encoding="utf-8") (alpha / "notes.md").write_text("notes\n", encoding="utf-8") (beta / "PROMPT.md").write_text("# beta\n", encoding="utf-8") bundles = PromptFilesBundle.from_root(tmp_path) assert {bundle.slug for bundle in bundles} == {"alpha", "beta"} def test_delegates_to_from_docs( self, tmp_path: Path, ) -> None: """Ensures from_root delegates bundle assembly to from_docs.""" alpha = tmp_path / "prompts" / "alpha" beta = tmp_path / "prompts" / "beta" alpha.mkdir(parents=True) beta.mkdir(parents=True) (alpha / "PROMPT.md").write_text("# alpha\n", encoding="utf-8") (alpha / "notes.md").write_text("notes\n", encoding="utf-8") (beta / "PROMPT.md").write_text("# beta\n", encoding="utf-8") from_root = PromptFilesBundle.from_root(tmp_path) from_docs = PromptFilesBundle.from_docs(MarkdownDocument.from_root(tmp_path).values()) assert tuple(from_root) == from_docs class TestFromDocs: """Covers bundle creation from preloaded markdown documents.""" def test_groups_by_slug(self, make_doc: MakeDoc) -> None: """Ensures from_docs groups documents by prompt slug.""" docs = [ make_doc("prompts/alpha/PROMPT.md"), make_doc("prompts/alpha/notes.md"), make_doc("prompts/beta/PROMPT.md"), ] bundles = PromptFilesBundle.from_docs(docs) assert {bundle.slug for bundle in bundles} == {"alpha", "beta"} def test_one_bundle_per_slug(self, make_doc: MakeDoc) -> None: """Ensures from_docs produces one PromptFilesBundle per slug.""" docs = [ make_doc("prompts/alpha/PROMPT.md"), make_doc("prompts/alpha/notes.md"), make_doc("prompts/alpha/changelog.md"), ] bundles = PromptFilesBundle.from_docs(docs) assert len(bundles) == 1 assert bundles[0].slug == "alpha" class TestFromPaths: """Covers classification of prompt and other documents.""" def test_selects_prompt_md(self, make_doc: MakeDoc) -> None: """Ensures from_paths selects PROMPT.md as the primary document.""" docs = { make_doc("prompts/alpha/PROMPT.md"), make_doc("prompts/alpha/notes.md"), } bundle = PromptFilesBundle.from_paths("alpha", docs) assert bundle.prompt.relpath.name == "PROMPT.md" def test_collects_other_docs(self, make_doc: MakeDoc) -> None: """Ensures from_paths classifies non-prompt docs as other docs.""" docs = { make_doc("prompts/alpha/PROMPT.md"), make_doc("prompts/alpha/notes.md"), make_doc("prompts/alpha/changelog.md"), } bundle = PromptFilesBundle.from_paths("alpha", docs) assert {doc.relpath.as_posix() for doc in bundle.other} == { "prompts/alpha/changelog.md", "prompts/alpha/notes.md", } class TestGroupPromptPaths: """Covers grouping markdown documents by derived prompt slug.""" def test_groups_slugged_docs(self, make_doc: MakeDoc) -> None: """Ensures group_prompt_paths groups only documents with a slug.""" docs = [ make_doc("prompts/alpha/PROMPT.md"), make_doc("prompts/alpha/notes.md"), make_doc("prompts/beta/PROMPT.md"), ] grouped = group_prompt_paths(docs) assert set(grouped) == {"alpha", "beta"} def test_excludes_unslugged_docs(self, make_doc: MakeDoc) -> None: """Ensures group_prompt_paths excludes documents without prompt slugs.""" docs = [ make_doc("docs/index.md"), make_doc("prompts/legacy.md"), ] assert group_prompt_paths(docs) == {} def test_returns_sets(self, make_doc: MakeDoc) -> None: """Ensures group_prompt_paths returns sets of docs per slug.""" grouped = group_prompt_paths([make_doc("prompts/alpha/PROMPT.md")]) assert isinstance(grouped["alpha"], set) def test_stable_grouping(self, make_doc: MakeDoc) -> None: """Ensures group_prompt_paths behaves consistently after internal sorting.""" docs = [ make_doc("prompts/beta/PROMPT.md"), make_doc("prompts/alpha/notes.md"), make_doc("prompts/alpha/PROMPT.md"), ] grouped_forward = group_prompt_paths(docs) grouped_reverse = group_prompt_paths(list(reversed(docs))) assert grouped_forward == grouped_reverse