"""Unit tests for the X13 court-citation classifier.""" from __future__ import annotations from legal_mcp.services.court_citation import ( case_number_from_citation, classify, normalize_case_number, ) def test_admin_filed_format_the_example(): """The plan's example: עת"מ 46111-12-22 → admin, parsed into (46111,12,22).""" c = classify('עת"מ 46111-12-22 יכין-אפק בע"מ נ\' הוועדה המחוזית') assert c.tier == "admin" assert c.court_prefix in ('עת"מ', "עת״מ") assert c.case_number_raw == "46111-12-22" assert c.case_number_norm == "46111-12-22" assert (c.file_number, c.month, c.year) == ("46111", "12", "22") assert c.fetchable is True def test_bare_filed_number_defaults_admin(): c = classify("46111-12-22") assert c.tier == "admin" assert (c.file_number, c.month, c.year) == ("46111", "12", "22") def test_supreme_prefixes(): for cit, pref in [ ('עע"מ 1234/22', "supreme"), ('בג"ץ 5678/21', "supreme"), ('ע"א 999/20', "supreme"), ('רע"א 4/19', "supreme"), ('בר"מ 8126/24', "supreme"), ]: c = classify(cit) assert c.tier == pref, f"{cit} -> {c.tier}" assert c.fetchable is True def test_appeals_committee_is_skip(): """ערר / בל"מ must never be auto-fetched (needs Nevo) — INV-CF6.""" for cit in ['ערר 1110/20', 'בל"מ 8048/24', "ערר 1015-01-24 ירושלים שקופה"]: c = classify(cit) assert c.tier == "skip", f"{cit} -> {c.tier}" assert c.fetchable is False def test_skip_wins_over_court_match(): """An 'ערר' citation that also contains court-like digits stays skip.""" c = classify("ראה החלטתי בערר 1041/24 ובהמשך") assert c.tier == "skip" def test_admin_amn_prefix(): c = classify('עמ"נ 12345-06-23') assert c.tier == "admin" assert (c.file_number, c.month, c.year) == ("12345", "06", "23") def test_two_group_serial_has_no_filed_triple(): """Supreme serial 1234/22 normalizes but yields no (file,month,year).""" c = classify('עע"מ 1234/22') assert c.case_number_norm == "1234-22" assert c.file_number is None def test_implausible_month_not_parsed_as_filed(): # 1234-22-05 has month=22 → not a valid filed triple. assert classify("1234-22-05").tier in ("unknown", "admin") c = classify("1234-22-05") if c.tier == "admin": assert c.month is None def test_empty_and_garbage(): assert classify("").tier == "unknown" assert classify("שלום עולם בלי ציטוט").tier == "unknown" def test_normalize_case_number(): assert normalize_case_number('עת"מ 46111/12/22') == "46111-12-22" assert normalize_case_number("1110/20") == "1110-20" def test_case_number_from_citation_strips_party_names(): """#137 — a full ועדת-ערר citation yields ONLY the number, never the display string with party names (INV-ID2). This is the exact precedent 1bf0bae0 that planted ``85074-04-25) רפאל לוי …`` into case_number.""" cit = 'ערר (ת"א 85074-04-25) רפאל לוי ואח\' נ\' הוועדה המקומית - חולון' assert case_number_from_citation(cit) == "85074-04-25" def test_case_number_from_citation_various_forms(): assert case_number_from_citation('ערר (ת"א 1198-12-25) זאטוס') == "1198-12-25" assert case_number_from_citation("85074-04-25") == "85074-04-25" assert case_number_from_citation('בל"מ 85074-09-24') == "85074-09-24" assert case_number_from_citation("ערר 8137/24") == "8137-24" def test_case_number_from_citation_empty_when_unparseable(): """No number → '' so the caller demands a manual number, never the raw citation (the #137 fallback that caused the bug).""" assert case_number_from_citation("") == "" assert case_number_from_citation("פסק דין בלי מספר") == "" def test_supreme_with_net_format_triple(): """A Supreme prefix carrying a נט-format number exposes the triple so the orchestrator can route it to Tier-1 (נט המשפט serves Supreme too).""" c = classify('בר"מ 72182-06-25 הימנותא נ\' הוועדה המקומית') assert c.tier == "supreme" assert (c.file_number, c.month, c.year) == ("72182", "06", "25") # serial-format Supreme has no triple → stays Tier-0-only s = classify('עע"מ 5886/24') assert s.tier == "supreme" and s.file_number is None