opencode-config/tests/test_check_adr_refs.py
Sergey 6005c88203
feat: migrate src/ second-brain + tests + python tooling (#17)
* feat(src): migrate second-brain RAG CLI + tests

* fix(embedder): strip hardcoded ai.slaid098.dev endpoint

* refactor: rename slaid098/opencode to opencode-config

* docs(handoff): add pr-5 handoff + ADR-001

* fix(docs): rebase handoff/ADR naming to PR number + drop dangling ADR-009 refs

* fix(tests): update script paths + assertions for opencode-config migration

* fix(pyproject): update cov + ruff paths config/scripts -> .opencode/scripts

* docs: update project map + handoff + ADR

---------

Co-authored-by: opencode-agent <agent@slaid098.dev>
2026-07-23 23:17:18 +03:00

157 lines
5.9 KiB
Python

"""Tests for .opencode/scripts/check-adr-refs.py — dangling ADR reference guard.
Covers the deterministic ADR-ref guard: clean repo passes, a dangling
``ADR-999`` in a temp handoff is detected, self-reference inside an
``NNN-*.md`` file is excluded, a valid cross-ref (``ADR-002``) passes,
a file with no ADR refs passes, and ``node_modules/`` is excluded.
Strategy mirrors ``tests/test_check_permissions.py``:
- ``test_clean_repo_passes`` runs the script as a subprocess on the
real (clean) repo — black-box, returncode 0, OK message in stdout.
- The remaining tests load the script in-process via importlib and
monkeypatch ``REPO_ROOT`` / ``ADR_DIR`` to point at a tmp_path tree,
then call ``main()`` and assert on captured stdout / SystemExit code.
"""
import importlib.util
import subprocess
import sys
from pathlib import Path
import pytest
REPO_ROOT = Path(__file__).resolve().parent.parent
SCRIPT_PATH = REPO_ROOT / ".opencode" / "scripts" / "check-adr-refs.py"
def _load_script():
spec = importlib.util.spec_from_file_location("check_adr_refs", SCRIPT_PATH)
module = importlib.util.module_from_spec(spec)
sys.modules["check_adr_refs"] = module
spec.loader.exec_module(module)
return module
car = _load_script()
# ── clean repo (subprocess black-box) ───────────────────────────────────────
def test_clean_repo_passes():
"""On the current (clean) repo the script exits 0 with the OK message."""
result = subprocess.run(
["python3", str(SCRIPT_PATH)],
capture_output=True,
text=True,
check=False,
)
assert result.returncode == 0, result.stderr
assert "OK: No dangling ADR references." in result.stdout
# ── helpers for in-process tests ────────────────────────────────────────────
def _setup_tmp_repo(tmp_path: Path, monkeypatch) -> tuple[Path, Path]:
"""Point the script's REPO_ROOT and ADR_DIR at a tmp_path tree.
Creates the ``docs/decisions/`` dir and returns (repo_root, adr_dir).
"""
repo = tmp_path / "repo"
adr_dir = repo / "docs" / "decisions"
adr_dir.mkdir(parents=True)
handoff_dir = repo / "docs" / "handoff"
handoff_dir.mkdir(parents=True)
monkeypatch.setattr(car, "REPO_ROOT", repo)
monkeypatch.setattr(car, "ADR_DIR", adr_dir)
return repo, adr_dir
# ── dangling reference detected ─────────────────────────────────────────────
def test_dangling_ref_detected(tmp_path, monkeypatch, capsys):
"""A handoff referencing ADR-999 (no 999-*.md) → exit 1 + ADR-999 in output."""
repo, _adr_dir = _setup_tmp_repo(tmp_path, monkeypatch)
(repo / "docs" / "handoff" / "pr-1-test.md").write_text("See ADR-999 for context.\n")
with pytest.raises(SystemExit) as exc_info:
car.main()
assert exc_info.value.code == 1
captured = capsys.readouterr()
assert "ADR-999" in captured.out
assert "FAIL" in captured.out
# ── self-reference excluded ─────────────────────────────────────────────────
def test_self_reference_excluded(tmp_path, monkeypatch, capsys):
"""An ADR file ``019-pr-94-test.md`` mentioning ADR-019 → passes (self-ref)."""
_repo, adr_dir = _setup_tmp_repo(tmp_path, monkeypatch)
(adr_dir / "019-pr-94-test.md").write_text("# ADR-019: self-reference is OK.\n")
with pytest.raises(SystemExit) as exc_info:
car.main()
assert exc_info.value.code == 0
captured = capsys.readouterr()
assert "OK: No dangling ADR references." in captured.out
# ── valid cross-reference passes ────────────────────────────────────────────
def test_valid_cross_ref_passes(tmp_path, monkeypatch, capsys):
"""A handoff referencing ADR-002 when 002-*.md exists → passes."""
repo, adr_dir = _setup_tmp_repo(tmp_path, monkeypatch)
(adr_dir / "002-pr-56-pipeline-mandatory-adr.md").write_text("# ADR-002\n")
(repo / "docs" / "handoff" / "pr-3-test.md").write_text("Per ADR-002, ADR is mandatory.\n")
with pytest.raises(SystemExit) as exc_info:
car.main()
assert exc_info.value.code == 0
captured = capsys.readouterr()
assert "OK: No dangling ADR references." in captured.out
# ── no ADR refs in a file passes ────────────────────────────────────────────
def test_no_adr_refs_passes(tmp_path, monkeypatch, capsys):
"""A handoff with no ADR-NNN references → passes."""
repo, _adr_dir = _setup_tmp_repo(tmp_path, monkeypatch)
(repo / "docs" / "handoff" / "pr-4-test.md").write_text("No ADR references here.\n")
with pytest.raises(SystemExit) as exc_info:
car.main()
assert exc_info.value.code == 0
captured = capsys.readouterr()
assert "OK: No dangling ADR references." in captured.out
# ── node_modules excluded ───────────────────────────────────────────────────
def test_exclude_node_modules(tmp_path, monkeypatch, capsys):
"""A ``.md`` file under ``node_modules/`` with ADR-999 is NOT scanned."""
repo, _adr_dir = _setup_tmp_repo(tmp_path, monkeypatch)
nm = repo / "node_modules" / "some-pkg"
nm.mkdir(parents=True)
(nm / "README.md").write_text("Dangling ADR-999 should be ignored.\n")
with pytest.raises(SystemExit) as exc_info:
car.main()
assert exc_info.value.code == 0
captured = capsys.readouterr()
assert "OK: No dangling ADR references." in captured.out
assert "ADR-999" not in captured.out
if __name__ == "__main__":
pytest.main([__file__, "-v"])