"""Unit tests for scripts/approve_proposal.py.""" from __future__ import annotations import sys from pathlib import Path try: import pytest except ImportError: # standalone fallback so the file runs without pytest installed import contextlib import types pytest = types.SimpleNamespace() @contextlib.contextmanager def _raises(exc, match=None): try: yield except exc as err: if match is not None and match not in str(err): raise AssertionError(f"expected {match!r} in {err!r}") from err return raise AssertionError(f"expected {exc.__name__} to be raised") pytest.raises = _raises REPO_ROOT = Path(__file__).resolve().parents[1] sys.path.insert(0, str(REPO_ROOT / "scripts")) import approve_proposal as approve # noqa: E402 def _strict_pending(): return { "id": "00957f6c-9883-4015-95a4-6b09367efb0e", "proposal_type": "add_edge", "status": "pending_review", "payload": { "apply_payload": { "from_claim": "11111111-1111-1111-1111-111111111111", "to_claim": "22222222-2222-2222-2222-222222222222", "edge_type": "supports", } }, } def test_assert_approvable_allows_strict_pending_payload(): approve.assert_approvable(_strict_pending(), "m3ta", "approved from Telegram") def test_assert_approvable_rejects_missing_review_note(): with pytest.raises(SystemExit): approve.assert_approvable(_strict_pending(), "m3ta", "") def test_assert_approvable_rejects_empty_reviewer(): with pytest.raises(SystemExit): approve.assert_approvable(_strict_pending(), " ", "approved") def test_assert_approvable_rejects_already_approved(): proposal = _strict_pending() proposal["status"] = "approved" with pytest.raises(SystemExit): approve.assert_approvable(proposal, "m3ta", "approved") def test_assert_approvable_rejects_non_applyable_type(): proposal = _strict_pending() proposal["proposal_type"] = "rewrite_claim" with pytest.raises(SystemExit): approve.assert_approvable(proposal, "m3ta", "approved") def test_assert_approvable_rejects_freeform_without_apply_payload(): proposal = _strict_pending() proposal["payload"] = {"rationale": "looks approved in chat"} with pytest.raises(SystemExit): approve.assert_approvable(proposal, "m3ta", "approved") def test_build_approve_sql_has_required_guards(): sql = approve.build_approve_sql("00957f6c-9883-4015-95a4-6b09367efb0e", "m3ta", "O'Brien approves") assert "status = 'approved'" in sql assert "where id = '00957f6c-9883-4015-95a4-6b09367efb0e'::uuid" in sql assert "and status = 'pending_review'" in sql assert "and payload ? 'apply_payload'" in sql assert "'O''Brien approves'" in sql assert "'add_edge'" in sql assert "'attach_evidence'" in sql assert "'revise_strategy'" in sql def test_parse_reviewed_rows_requires_exactly_one_row(): rows = approve.parse_reviewed_rows( '[{"id":"00957f6c-9883-4015-95a4-6b09367efb0e","status":"approved"}]', "00957f6c-9883-4015-95a4-6b09367efb0e", ) assert rows[0]["status"] == "approved" with pytest.raises(SystemExit): approve.parse_reviewed_rows("[]", "00957f6c-9883-4015-95a4-6b09367efb0e") if __name__ == "__main__": import traceback failures = 0 for name, fn in sorted(globals().items()): if name.startswith("test_") and callable(fn): try: fn() print(f"PASS {name}") except Exception: failures += 1 print(f"FAIL {name}") traceback.print_exc() sys.exit(1 if failures else 0)