File size: 4,096 Bytes
aad7814
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
"""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