Spaces:
Runtime error
Runtime error
| """Verification for the report post-processing pipeline (pure transform).""" | |
| from __future__ import annotations | |
| import re | |
| import pytest | |
| from backend.utils.report_postprocessor import ( | |
| _jaccard_similarity, | |
| polish_report, | |
| ) | |
| _RAW = ( | |
| "[REDACTED_NAME_1] repairs tend to be expensive due to the associated " | |
| "scaffolding costs. SEE THE LIMITATIONS OF OUR INSPECTION ABOVE. MAIN ROOF:\n" | |
| "The main roof structure is of hipped pitch and [[REDACTED_NAME_2]] " | |
| "construction, partially extended to form\ndormers. The pitched roof covering " | |
| "appears to be of plain concrete tiles. However, some areas were concealed " | |
| "from view due to the loft\n2\nRICS Home Survey - Level 3\n26\nconversion. " | |
| "Condition Rating 2. Condition Rating 2." | |
| ) | |
| def test_raises_on_empty(): | |
| with pytest.raises(ValueError): | |
| polish_report("") | |
| with pytest.raises(ValueError): | |
| polish_report(" \n ") | |
| def test_pure_function_idempotent_on_clean_input(): | |
| out1 = polish_report(_RAW) | |
| # Same input -> same output. | |
| assert polish_report(_RAW) == out1 | |
| def test_orphan_page_numbers_removed_globally(): | |
| out = polish_report(_RAW) | |
| assert not re.search(r"(?m)^\s*\d{1,3}\s*$", out) | |
| assert "loft conversion" in out # sentence rejoined across the page break | |
| def test_repeated_doc_header_suppressed(): | |
| out = polish_report(_RAW) | |
| assert "RICS Home Survey" not in out | |
| def test_sentence_initial_placeholder_grammar(): | |
| out = polish_report(_RAW) | |
| assert out.startswith("Repairs tend to be expensive") | |
| assert "REDACTED" not in out | |
| def test_mid_sentence_placeholder_becomes_neutral(): | |
| out = polish_report(_RAW) | |
| # Never the bare word "specified" — must be a visible, honest placeholder. | |
| assert "specified" not in out.lower() | |
| assert "[SURVEYOR TO CONFIRM] construction" in out | |
| assert "REDACTED" not in out | |
| def test_all_caps_directive_scrubbed(): | |
| out = polish_report(_RAW) | |
| assert "SEE THE LIMITATIONS" not in out.upper() | |
| def test_consecutive_duplicate_short_sentence_collapsed(): | |
| out = polish_report(_RAW) | |
| assert out.count("Condition Rating 2.") == 1 | |
| def test_non_adjacent_short_repeats_preserved(): | |
| raw = ( | |
| "The flashing is defective. Condition Rating 2. " | |
| "The gutter is blocked and overflowing at the rear. Condition Rating 2." | |
| ) | |
| out = polish_report(raw) | |
| assert out.count("Condition Rating 2.") == 2 | |
| def test_near_duplicate_paragraph_collapsed(): | |
| para = ( | |
| "The mortar bedding and pointing to the ridge and hip tiles is " | |
| "deteriorating and repointing is required to prevent wind uplift damage." | |
| ) | |
| raw = f"{para}\n\n{para}\n\nA distinct closing observation about the gutters." | |
| out = polish_report(raw) | |
| assert out.count("mortar bedding and pointing") == 1 | |
| assert "closing observation about the gutters" in out | |
| def test_caps_word_in_normal_sentence_not_stripped(): | |
| raw = "Please see the limitations of our inspection in the relevant section." | |
| out = polish_report(raw) | |
| assert "limitations of our inspection" in out | |
| def test_standalone_placeholder_line_removed(): | |
| raw = "Roof inspected from ground level.\n[REDACTED_ADDRESS_1]\nNo defects noted." | |
| out = polish_report(raw) | |
| assert "REDACTED" not in out | |
| assert "Roof inspected from ground level." in out | |
| assert "No defects noted." in out | |
| def test_extra_header_patterns_are_firm_agnostic(): | |
| raw = "Roof comments here.\nACME SURVEYS LLP CONFIDENTIAL\nMore roof comments." | |
| out = polish_report( | |
| raw, | |
| extra_header_patterns=[re.compile(r"ACME SURVEYS LLP CONFIDENTIAL")], | |
| ) | |
| assert "ACME SURVEYS" not in out | |
| def test_unicode_normalisation(): | |
| raw = "The roof\u2019s covering \u2013 slate \u2014 is sound\u00a0and intact." | |
| out = polish_report(raw) | |
| assert "\u2019" not in out and "\u2013" not in out and "\u2014" not in out | |
| assert "\u00a0" not in out | |
| def test_jaccard_bounds(): | |
| assert _jaccard_similarity("abcdef", "abcdef") == 1.0 | |
| assert _jaccard_similarity("abcdef", "xyzuvw") == 0.0 | |