from pathlib import Path import pytest from personal_mcp.prompts.content import load_prompt_definition from personal_mcp.prompts.content import render_prompt pytestmark = pytest.mark.unit class TestPromptContentRenderer: def test_renders_arguments_without_frontmatter(self) -> None: rendered = render_prompt( "jsfiddle-page-layout", {"domain": "public library", "layout_brief": None}, ) assert not rendered.startswith("---") assert "`domain`: public library" in rendered assert "`layout_brief`: Not provided" in rendered def test_rejects_placeholder_drift(self) -> None: with pytest.raises(ValueError, match="placeholders do not match arguments"): render_prompt("jsfiddle-page-layout", {"domain": "public library"}) def test_rejects_invalid_prompt_id(self) -> None: with pytest.raises(ValueError, match="lowercase kebab-case"): render_prompt("../outside", {}) def test_rejects_missing_prompt_metadata(self, tmp_path: Path) -> None: document = tmp_path / "PROMPT.md" document.write_text("---\nicon: lucide/messages-square\n---\n\n# Body\n", encoding="utf-8") with pytest.raises(ValueError, match="missing the 'prompt' block"): load_prompt_definition("demo", document) def test_rejects_unknown_prompt_metadata(self, tmp_path: Path) -> None: document = tmp_path / "PROMPT.md" document.write_text( "---\nprompt: {version: '1', description: Demo, tags: [demo], arguments: {}, unknown: true}\n" "---\n\n# Body\n", encoding="utf-8", ) with pytest.raises(ValueError, match="Extra inputs are not permitted"): load_prompt_definition("demo", document) def test_rejects_declared_placeholder_drift(self, tmp_path: Path) -> None: document = tmp_path / "PROMPT.md" document.write_text( "---\nprompt: {version: '1', description: Demo, tags: [demo], arguments: " "{topic: {description: Topic, required: true}}}\n---\n\n# Body\n", encoding="utf-8", ) with pytest.raises(ValueError, match="placeholders do not match arguments"): load_prompt_definition("demo", document)