from pathlib import Path import pytest import scripts.decisions_lib as dl FIX = Path(__file__).parent / "fixtures" / "sample_decisions.md" def test_parses_migrated_record(): recs = dl.parse_file(FIX) migrated = [r for r in recs if r.key == "ci.runner-placement"] assert len(migrated) == 1 r = migrated[0] assert r.status == "active" assert r.since == "2026-07-17" assert r.supersedes == "none" assert r.superseded_by == "none" assert r.rule == "Every CI services container gets an explicit cap." assert r.signals is not None assert "issues: #390 #406" in r.signals assert r.mechanics is not None assert r.mechanics.startswith("docs/ci-cd.md") def test_legacy_record_is_unmigrated(): recs = dl.parse_file(FIX) legacy = [r for r in recs if r.heading.endswith("(#231)")] assert len(legacy) == 1 assert legacy[0].key is None assert legacy[0].status == "legacy-unmigrated" def test_index_section_parses_as_heading(): recs = dl.parse_file(FIX) assert any(r.heading == "Index" for r in recs) def test_parses_optional_stale_after_and_sources(): recs = dl.parse_file(FIX) r = next(r for r in recs if r.key == "ci.peak-anon-measurement") assert r.stale_after == "2027-01-15" assert r.sources is not None assert "gitea run 4471" in r.sources def test_optional_fields_default_to_none_when_absent(): recs = dl.parse_file(FIX) r = next(r for r in recs if r.key == "ci.runner-placement") assert r.stale_after is None assert r.sources is None def test_empty_stale_after_parses_as_empty_string_not_none(): """Absent vs present-but-empty must stay distinguishable for the validator.""" text = ( "## H\n" "`key: a.b` · `status: active` · `since: 2026-01-01` · `stale-after:` " "· `supersedes: none` · `superseded-by: none`\n" "**Rule:** r\n" ) r = dl.parse_text(text, Path("fake.md"))[0] assert r.stale_after == "" def test_frontmatter_reader_matches_pyyaml_on_every_real_record(): """The dependency-free reader must agree with PyYAML on the whole real corpus. The read path cannot import PyYAML — it runs in CI's `decisions lifecycle` job, the Husky pre-commit hook, and on every contributor's machine, none of which install it. (Requiring it made the validator crash with ModuleNotFoundError once the corpus was migrated.) A hand parser is only safe if it provably matches the library that WROTE the files, so this compares the two across every record rather than on a sample. """ yaml = pytest.importorskip("yaml") files = [p for p in dl.RECORDS_DIR.rglob("*.md")] + [p for p in dl.ARCHIVE_DIR.rglob("*.md")] files = [f for f in files if dl.has_frontmatter(f.read_text(encoding="utf-8"))] assert len(files) > 100, f"only {len(files)} frontmatter files found — test would be near-vacuous" diffs = [] for f in files: lines = f.read_text(encoding="utf-8").splitlines() end = next(i for i, ln in enumerate(lines[1:], start=1) if ln.rstrip() == "---") block = "\n".join(lines[1:end]) mine = dl._read_frontmatter(block) theirs = yaml.safe_load(block) or {} theirs = {k: ("" if v is None else str(v)) for k, v in theirs.items()} if mine != theirs: for k in set(mine or {}) | set(theirs): if (mine or {}).get(k) != theirs.get(k): diffs.append(f"{f.name}:{k}\n mine ={(mine or {}).get(k)!r}\n pyyaml={theirs.get(k)!r}") assert not diffs, f"{len(diffs)} field(s) differ from PyYAML:\n" + "\n".join(diffs[:5])