"""Schema validation of the REAL curated datasets. test_commentary.py deliberately exercises the renderer on a minimal in-memory dataset; nothing previously validated the actual shipped JSON, so a hand-edit typo in the 51-jurisdiction survey surfaced only at runtime in production. """ import json import unittest from pathlib import Path CURATED = Path(__file__).resolve().parent.parent / "data" / "curated" VERDICTS = {"yes", "likely-yes", "likely-no", "no", "fact-specific", "depends"} STATUSES = {"settled", "judicially-considered", "guidance-only", "no-authority"} US_STATES = { "Alabama", "Alaska", "Arizona", "Arkansas", "California", "Colorado", "Connecticut", "Delaware", "District of Columbia", "Florida", "Georgia", "Hawaii", "Idaho", "Illinois", "Indiana", "Iowa", "Kansas", "Kentucky", "Louisiana", "Maine", "Maryland", "Massachusetts", "Michigan", "Minnesota", "Mississippi", "Missouri", "Montana", "Nebraska", "Nevada", "New Hampshire", "New Jersey", "New Mexico", "New York", "North Carolina", "North Dakota", "Ohio", "Oklahoma", "Oregon", "Pennsylvania", "Rhode Island", "South Carolina", "South Dakota", "Tennessee", "Texas", "Utah", "Vermont", "Virginia", "Washington", "West Virginia", "Wisconsin", "Wyoming", "general", } class DispositionsSchemaTests(unittest.TestCase): @classmethod def setUpClass(cls): cls.data = json.loads( (CURATED / "us_dispositions.json").read_text(encoding="utf-8")) def test_reviewed_date_present(self): self.assertRegex(self.data.get("reviewed", ""), r"^\d{4}-\d{2}-\d{2}$") def test_entries_have_required_keys(self): for e in self.data["dispositions"]: for key in ("id", "names", "is_conviction", "status", "analysis"): self.assertIn(key, e, f"{e.get('id', '?')} missing {key}") self.assertTrue(e["names"], f"{e['id']}: empty names") def test_verdicts_are_legal_values(self): for e in self.data["dispositions"]: self.assertIn(e["is_conviction"], VERDICTS, e["id"]) self.assertIn(e["status"], STATUSES, e["id"]) for v in e.get("state_variations", []): if v.get("is_conviction"): self.assertIn(v["is_conviction"], VERDICTS, f"{e['id']}/{v.get('state')}") def test_state_names_valid(self): for e in self.data["dispositions"]: for v in e.get("state_variations", []): self.assertIn(v["state"], US_STATES, f"{e['id']}: unknown state {v['state']!r}") def test_authorities_carry_citations(self): for e in self.data["dispositions"]: for a in e.get("authorities", []): self.assertTrue(a.get("cite"), f"{e['id']}: authority no cite") def test_renderer_accepts_every_entry(self): from canlex.commentary import _entry_text for e in self.data["dispositions"]: text = _entry_text(e) self.assertGreater(len(text), 100, e["id"]) class EquivalencySchemaTests(unittest.TestCase): @classmethod def setUpClass(cls): cls.data = json.loads( (CURATED / "us_equivalency.json").read_text(encoding="utf-8")) def test_pairings_have_required_keys(self): for p in self.data["pairings"]: for key in ("id", "us_terms", "canadian_offence", "penalty", "branch", "status", "analysis"): self.assertIn(key, p, f"{p.get('id', '?')} missing {key}") self.assertTrue(p["us_terms"], f"{p['id']}: empty us_terms") def test_methodology_framework_present(self): ids = {m["id"] for m in self.data.get("methodology", [])} self.assertIn("equivalency-framework", ids) if __name__ == "__main__": unittest.main()