import json import re from pathlib import Path ROOT = Path(__file__).resolve().parents[1] DOMAIN = ROOT / "docs" / "domain" GOLDEN = ROOT / "test" / "fixtures" / "golden" / "accident-scenarios.json" def load_json(path): return json.loads(path.read_text(encoding="utf-8")) def test_stage_registry_and_transition_matrix_are_closed(): stage_registry = load_json(DOMAIN / "stage-codes.json") transitions = load_json(DOMAIN / "stage-transitions.json") codes = {entry["code"] for entry in stage_registry["codes"]} assert len(codes) == len(stage_registry["codes"]) assert {"0000", "0004", "0005", "1001", "1002", "3001", "3002"} <= codes assert set(transitions["allowed"]) == codes for source, targets in transitions["allowed"].items(): assert set(targets) <= codes, source for terminal in {"0000", "0001", "0002", "0003", "0004", "0005"}: assert transitions["allowed"][terminal] == [] def test_photo_sequences_cannot_skip_steps(): transitions = load_json(DOMAIN / "stage-transitions.json") for sequence in transitions["photo_sequences"].values(): for current, following in zip(sequence, sequence[1:]): assert following in transitions["allowed"][current] later_steps = set(sequence[sequence.index(following) + 1 :]) assert later_steps.isdisjoint(transitions["allowed"][current]) def test_field_registry_groups_are_complete_and_unique(): registry = load_json(DOMAIN / "field-registry.json") fields = registry["fields"] keys = [field["key"] for field in fields] assert len(keys) == len(set(keys)) assert set(keys) == { key for group_keys in registry["groups"].values() for key in group_keys } assert {"sfzmhm1", "sjhm1", "hphm1", "sfzmhm2", "sjhm2", "hphm2"} <= { field["key"] for field in fields if field["sensitive"] } assert {"sfzmwh1", "sjwh1", "sfzmwh2", "sjwh2"} <= { field["key"] for field in fields if not field["external_write"] } def test_golden_scenarios_are_unique_and_use_known_stages(): stages = { entry["code"] for entry in load_json(DOMAIN / "stage-codes.json")["codes"] } scenarios = load_json(GOLDEN)["scenarios"] case_ids = [case["case_id"] for case in scenarios] assert len(scenarios) >= 12 assert len(case_ids) == len(set(case_ids)) for case in scenarios: assert case["initial_stage"] in stages if "expected_stage" in case: assert case["expected_stage"] in stages for turn in case.get("turns", []): if "expected_stage" in turn: assert turn["expected_stage"] in stages def test_golden_turn_sequences_follow_the_transition_matrix(): allowed = load_json(DOMAIN / "stage-transitions.json")["allowed"] scenarios = load_json(GOLDEN)["scenarios"] for case in scenarios: current = case["initial_stage"] for turn in case.get("turns", []): expected = turn.get("expected_stage") if expected is None: continue if "expected_error" not in turn: assert expected in allowed[current], ( case["case_id"], current, expected, ) current = expected def test_golden_fixture_contains_no_realistic_phone_or_national_id(): raw = GOLDEN.read_text(encoding="utf-8") assert not re.search(r"(?