docs validator: add validate_docs_sync with unit tests (#363)
This commit is contained in:
102
tests/test_validate_docs_sync.py
Normal file
102
tests/test_validate_docs_sync.py
Normal file
@@ -0,0 +1,102 @@
|
||||
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_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 == []
|
||||
Reference in New Issue
Block a user