Files
The-Ouroboros/tests/test_validate_docs_sync.py
agentson 6656adc2b7
All checks were successful
Gitea CI / test (push) Successful in 33s
Gitea CI / test (pull_request) Successful in 35s
ci/docs: wire docs sync validator into workflows and tighten tests
2026-03-01 23:09:20 +09:00

124 lines
3.9 KiB
Python

from __future__ import annotations
import importlib.util
from pathlib import Path
def _load_module():
script_path = Path(__file__).resolve().parents[1] / "scripts" / "validate_docs_sync.py"
spec = importlib.util.spec_from_file_location("validate_docs_sync", script_path)
assert spec is not None
assert spec.loader is not None
module = importlib.util.module_from_spec(spec)
spec.loader.exec_module(module)
return module
def test_collect_command_endpoints_parses_markdown_table_rows() -> None:
module = _load_module()
text = "\n".join(
[
"| Endpoint | Description |",
"|----------|-------------|",
"| `GET /api/status` | status |",
"| `POST /api/run` | run |",
"| not-a-row | ignored |",
]
)
endpoints = module.collect_command_endpoints(text)
assert endpoints == ["GET /api/status", "POST /api/run"]
def test_validate_links_resolve_detects_absolute_and_broken_links(tmp_path) -> None:
module = _load_module()
doc = tmp_path / "doc.md"
existing = tmp_path / "ok.md"
existing.write_text("# ok\n", encoding="utf-8")
doc.write_text(
"\n".join(
[
"[ok](./ok.md)",
"[abs](/tmp/nowhere.md)",
"[broken](./missing.md)",
]
),
encoding="utf-8",
)
errors: list[str] = []
module.validate_links_resolve(doc, doc.read_text(encoding="utf-8"), errors)
assert any("absolute link is forbidden" in err for err in errors)
assert any("broken link" in err for err in errors)
def test_validate_summary_docs_reference_core_docs(monkeypatch) -> None:
module = _load_module()
errors: list[str] = []
fake_docs = {
str(module.REQUIRED_FILES["README.md"]): (
"docs/workflow.md docs/commands.md docs/testing.md"
),
str(module.REQUIRED_FILES["CLAUDE.md"]): "docs/workflow.md docs/commands.md",
}
def fake_read(path: Path) -> str:
return fake_docs[str(path)]
monkeypatch.setattr(module, "_read", fake_read)
module.validate_summary_docs_reference_core_docs(errors)
assert errors == []
def test_validate_summary_docs_reference_core_docs_reports_missing_links(
monkeypatch,
) -> None:
module = _load_module()
errors: list[str] = []
fake_docs = {
str(module.REQUIRED_FILES["README.md"]): "docs/workflow.md",
str(module.REQUIRED_FILES["CLAUDE.md"]): "docs/workflow.md",
}
def fake_read(path: Path) -> str:
return fake_docs[str(path)]
monkeypatch.setattr(module, "_read", fake_read)
module.validate_summary_docs_reference_core_docs(errors)
assert any("README.md" in err and "docs/commands.md" in err for err in errors)
assert any("README.md" in err and "docs/testing.md" in err for err in errors)
assert any("CLAUDE.md" in err and "docs/commands.md" in err for err in errors)
def test_validate_commands_endpoint_duplicates_reports_duplicates(monkeypatch) -> None:
module = _load_module()
errors: list[str] = []
text = "\n".join(
[
"| `GET /api/status` | status |",
"| `GET /api/status` | duplicate |",
]
)
def fake_read(path: Path) -> str:
assert path == module.REQUIRED_FILES["commands"]
return text
monkeypatch.setattr(module, "_read", fake_read)
module.validate_commands_endpoint_duplicates(errors)
assert errors
assert "duplicated API endpoint row -> GET /api/status" in errors[0]
def test_validate_testing_doc_has_dynamic_count_guidance(monkeypatch) -> None:
module = _load_module()
errors: list[str] = []
def fake_read(path: Path) -> str:
assert path == module.REQUIRED_FILES["testing"]
return "Use pytest --collect-only -q for dynamic counts."
monkeypatch.setattr(module, "_read", fake_read)
module.validate_testing_doc_has_dynamic_count_guidance(errors)
assert errors == []