Files
grm/tests/unit/test_doc_coverage.py
T
emil 5b05db4e6d GRM-36: feat: implement documentation-as-code with wiki sync and doc-coverage
Add /docs/ directory with user and technical documentation extracted from README, AGENTS.md, and source code. Add scripts/sync_wiki.py to sync docs to Gitea wiki via API. Add scripts/doc_coverage.py to check CLI commands, modules, and CI scripts are documented. Add sync-wiki.yml workflow for auto-sync on merge and release. Slim down README.md to lean entry point. 28 new unit tests, 100% coverage maintained.

Closes GRM-36
2026-06-21 19:45:34 +00:00

110 lines
4.3 KiB
Python

"""Unit tests for scripts/doc_coverage.py."""
from pathlib import Path
from click.testing import CliRunner
from scripts.doc_coverage import (
check_command_documented,
check_module_documented,
extract_cli_commands,
main,
)
class TestExtractCliCommands:
def test_extracts_commands(self) -> None:
commands = extract_cli_commands()
# Should find all 9 CLI commands
assert "install" in commands
assert "update" in commands
assert "start" in commands
assert "stop" in commands
assert "enable" in commands
assert "disable" in commands
assert "status" in commands
assert "remove" in commands
assert "list" in commands
def test_returns_list(self) -> None:
commands = extract_cli_commands()
assert isinstance(commands, list)
assert len(commands) == 9
class TestCheckCommandDocumented:
def test_finds_command_in_heading(self) -> None:
content = "## install\n\nInstall a runner."
assert check_command_documented("install", content) is True
def test_finds_command_in_code_block(self) -> None:
content = "```bash\ngrm install 192.168.1.10\n```"
assert check_command_documented("install", content) is True
def test_finds_command_with_grm_prefix(self) -> None:
content = "Use `grm start prod-runner` to start."
assert check_command_documented("start", content) is True
def test_missing_command(self) -> None:
content = "## Other stuff\n\nNo commands here."
assert check_command_documented("install", content) is False
class TestCheckModuleDocumented:
def test_finds_module(self) -> None:
content = "The cli.py module handles..."
assert check_module_documented("cli.py", content) is True
def test_missing_module(self) -> None:
content = "No modules mentioned."
assert check_module_documented("cli.py", content) is False
class TestMain:
def test_all_present(self, tmp_path: Path) -> None:
"""When all docs exist and cover all commands/modules, exit 0."""
docs = tmp_path / "docs"
(docs / "user").mkdir(parents=True)
(docs / "tech").mkdir(parents=True)
# Write cli-commands.md with all commands
(docs / "user" / "cli-commands.md").write_text(
"## install\n## update\n## start\n## stop\n## enable\n## disable\n## status\n## remove\n## list\n"
)
# Write architecture.md with all modules
(docs / "tech" / "architecture.md").write_text(
"cli.py runner_manager.py executor.py registry.py i18n.py exceptions.py api_clients.py config.py"
)
# Write ci-cd-workflow.md with all scripts
(docs / "tech" / "ci-cd-workflow.md").write_text(
"auto_merge.py release.py publish.py review_pr.py notify_failure.py post_merge.py"
)
runner = CliRunner()
result = runner.invoke(main, ["--docs-dir", str(docs)])
assert result.exit_code == 0
assert "100%" in result.output
def test_missing_docs_fail(self, tmp_path: Path) -> None:
"""When docs are missing and --fail-on-missing is set, exit 1."""
docs = tmp_path / "docs"
(docs / "user").mkdir(parents=True)
(docs / "tech").mkdir(parents=True)
(docs / "user" / "cli-commands.md").write_text("No commands here.")
(docs / "tech" / "architecture.md").write_text("No modules here.")
(docs / "tech" / "ci-cd-workflow.md").write_text("No scripts here.")
runner = CliRunner()
result = runner.invoke(main, ["--docs-dir", str(docs), "--fail-on-missing"])
assert result.exit_code == 1
def test_missing_docs_warn_only(self, tmp_path: Path) -> None:
"""Without --fail-on-missing, missing docs only warn (exit 0)."""
docs = tmp_path / "docs"
(docs / "user").mkdir(parents=True)
(docs / "tech").mkdir(parents=True)
(docs / "user" / "cli-commands.md").write_text("No commands here.")
(docs / "tech" / "architecture.md").write_text("No modules here.")
(docs / "tech" / "ci-cd-workflow.md").write_text("No scripts here.")
runner = CliRunner()
result = runner.invoke(main, ["--docs-dir", str(docs)])
assert result.exit_code == 0
assert "MISSING" in result.output