"""Bootstrap relationship and provision parsing tests.""" import pandas as pd from telen.bootstrap import ( canonicalize_relationship, canonicalize_relationship_frame, contains_document_number, extract_articles, extract_event_mentions, html_to_legal_text, normalize_document_number, ) from telen.domain import RelationType def test_active_and_passive_labels_have_same_canonical_orientation() -> None: active = canonicalize_relationship("new", "old", "Thay thế") passive = canonicalize_relationship("old", "new", "Văn bản quy định hết hiệu lực") assert active is not None assert passive is not None assert active.event_doc_id == passive.event_doc_id == "new" assert active.affected_doc_id == passive.affected_doc_id == "old" assert active.relation is RelationType.REPLACES assert passive.relation is RelationType.TERMINATES_VERSION def test_specific_termination_supersedes_generic_mirror() -> None: raw = pd.DataFrame( [ {"doc_id": "new", "other_doc_id": "old", "relationship": "Thay thế"}, { "doc_id": "old", "other_doc_id": "new", "relationship": "Văn bản quy định hết hiệu lực", }, ] ) canonical = canonicalize_relationship_frame(raw) assert len(canonical) == 1 assert canonical.iloc[0]["event_doc_id"] == "new" assert canonical.iloc[0]["affected_doc_id"] == "old" assert canonical.iloc[0]["relation"] == "REPLACES" assert canonical.iloc[0]["evidence_count"] == 2 assert "Văn bản quy định hết hiệu lực" in canonical.iloc[0]["raw_labels"] def test_mirrored_amendment_evidence_collapses_but_retains_labels() -> None: raw = pd.DataFrame( [ { "doc_id": "new", "other_doc_id": "old", "relationship": "Sửa đổi, bổ sung", }, { "doc_id": "old", "other_doc_id": "new", "relationship": "Văn bản sửa đổi", }, ] ) canonical = canonicalize_relationship_frame(raw) assert len(canonical) == 1 row = canonical.iloc[0] assert row["relation"] == "AMENDS" assert row["evidence_count"] == 2 assert "Sửa đổi, bổ sung" in row["raw_labels"] assert "Văn bản sửa đổi" in row["raw_labels"] def test_unknown_relation_is_not_silently_promoted_to_graph_fact() -> None: assert canonicalize_relationship("a", "b", "Văn bản liên quan khác") is None def test_html_parser_removes_scripts_and_preserves_article_lines() -> None: html = """

Điều 1. Phạm vi điều chỉnh

Luật này quy định về thuế.

Điều 2: Đối tượng áp dụng

Tổ chức và cá nhân.

""" text = html_to_legal_text(html) articles = extract_articles(html) assert "color:red" not in text assert "alert" not in text assert len(articles) == 2 assert articles[0].article_number == "1" assert articles[0].heading == "Phạm vi điều chỉnh" assert "Luật này quy định về thuế" in articles[0].text assert articles[1].article_number == "2" def test_document_number_matching_is_separator_tolerant_but_not_fuzzy() -> None: assert normalize_document_number(" 03 / 2024 / TT-BKHCN ") == "03/2024/ttbkhcn".replace("/", "") assert contains_document_number( "Thông tư số 03 / 2024 / TT-BKHCN ngày 15 tháng 4", "03/2024/TT-BKHCN", ) assert not contains_document_number( "Thông tư số 13/2024/TT-BKHCN", "03/2024/TT-BKHCN" ) def test_extract_event_mentions_links_amending_clause_to_target_articles() -> None: html = """

THÔNG TƯ

Sửa đổi một số điều của Thông tư số 03/2024/TT-BKHCN

Điều 1. Sửa đổi, bổ sung khoản 1 Điều 4 như sau:

“Điều 4. Nội dung mới”

Điều 2. Bãi bỏ Điều 7 và Điều 8.

Điều 3. Hiệu lực thi hành

""" mentions = extract_event_mentions(html, "03/2024/TT-BKHCN") assert len(mentions) == 2 assert mentions[0].source_article_number == "1" assert mentions[0].target_article_numbers == ("4",) assert mentions[0].target_document_explicit is False assert mentions[1].action == "bãi bỏ" assert mentions[1].target_article_numbers == ("7", "8") def test_extract_event_mentions_requires_explicit_target_document() -> None: html = """

Điều 1. Sửa đổi Điều 4 như sau:

“Điều 4. Nội dung mới”

""" assert extract_event_mentions(html, "03/2024/TT-BKHCN") == () def test_preamble_fallback_is_disabled_for_ambiguous_multiple_targets() -> None: html = """

Số: 80/2026/NĐ-CP

Sửa đổi Nghị định số 142/2017/NĐ-CP và Nghị định số 139/2021/NĐ-CP

Căn cứ Luật số 01/2020/QH14

Điều 1. Sửa đổi Điều 4 như sau:

Điều 2. Sửa đổi Điều 8 của Nghị định số 139/2021/NĐ-CP.

""" mentions = extract_event_mentions(html, "139/2021/NĐ-CP") assert len(mentions) == 1 assert mentions[0].source_article_number == "2" assert mentions[0].target_document_explicit is True