kaizen-agentic/tests/test_agent_docs.py

98 lines
3.5 KiB
Python
Raw Normal View History

"""Tests for idempotent agent-docs generation (WP-0007 T01/T02)."""
from __future__ import annotations
from pathlib import Path
import pytest
from click.testing import CliRunner
from kaizen_agentic.agent_docs import (
SECTION_FOOTER,
SECTION_HEADING,
render_installed_agents_section,
upsert_installed_agents_section,
)
from kaizen_agentic.cli import cli
from kaizen_agentic.registry import AgentRegistry
AGENTS_DIR = Path(__file__).parent.parent / "agents"
@pytest.fixture
def runner() -> CliRunner:
return CliRunner()
def _section() -> str:
agents = AgentRegistry(AGENTS_DIR).list_agents()[:4]
return render_installed_agents_section(agents)
class TestUpsertIdempotency:
def test_upsert_is_idempotent(self):
section = _section()
base = f"# Project\n\nintro\n\n{section}\n## Keep Me\nbody\n"
once = upsert_installed_agents_section(base, section)
twice = upsert_installed_agents_section(once, section)
assert once == twice
assert once.count(SECTION_HEADING) == 1
assert once.count(SECTION_FOOTER) == 1
# A following top-level section must survive the replace
assert once.count("## Keep Me") == 1
def test_subheadings_do_not_truncate_section(self):
section = _section()
# The block contains '### Category' subheadings; the replace must not
# stop at the first one (the original regex bug).
merged = upsert_installed_agents_section("# P\n\n", section)
assert merged.count(SECTION_FOOTER) == 1
assert "### " in merged # categories rendered
def test_append_when_absent(self):
section = _section()
merged = upsert_installed_agents_section("# Project\n\nbody\n", section)
assert SECTION_HEADING in merged
assert merged.count(SECTION_FOOTER) == 1
class TestDocsGenerateCli:
def test_generate_then_check_clean(self, runner: CliRunner, tmp_path: Path):
# A project with two installed agents
proj = tmp_path / "proj"
(proj / "agents").mkdir(parents=True)
for name, cat in (("alpha", "testing"), ("beta", "code-quality")):
(proj / "agents" / f"agent-{name}.md").write_text(
f"---\nname: {name}\ndescription: d{name}\ncategory: {cat}\n---\nx\n"
)
gen = runner.invoke(cli, ["docs", "generate", "--target", str(proj)])
assert gen.exit_code == 0
claude = (proj / "CLAUDE.md").read_text()
assert claude.count(SECTION_HEADING) == 1
assert "**alpha**" in claude and "**beta**" in claude
# Second generate is a no-op
again = runner.invoke(cli, ["docs", "generate", "--target", str(proj)])
assert "already up to date" in again.output
# --check passes on a synced repo
check = runner.invoke(
cli, ["docs", "generate", "--check", "--target", str(proj)]
)
assert check.exit_code == 0
assert "up to date" in check.output
def test_check_fails_when_stale(self, runner: CliRunner, tmp_path: Path):
proj = tmp_path / "proj"
(proj / "agents").mkdir(parents=True)
(proj / "agents" / "agent-alpha.md").write_text(
"---\nname: alpha\ndescription: d\ncategory: testing\n---\nx\n"
)
(proj / "CLAUDE.md").write_text("# Proj\n\nno agents section yet\n")
check = runner.invoke(
cli, ["docs", "generate", "--check", "--target", str(proj)]
)
assert check.exit_code == 1
assert "out of date" in check.output