File size: 7,212 Bytes
a1b3d21
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
fa11e0b
 
 
a1b3d21
 
 
 
 
 
fa11e0b
 
a1b3d21
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
5884807
8c65924
5884807
 
 
 
 
 
 
 
 
 
 
 
 
 
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
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
from __future__ import annotations

import ast
from pathlib import Path


REPO_ROOT = Path(__file__).resolve().parents[1]
APP_PATH = REPO_ROOT / "presidio_streamlit.py"
PLAN_PATH = REPO_ROOT / "DUPLICATE_INPUT_SURFACE_SIMPLIFICATION_PLAN.md"
DOCKERFILE_PATH = REPO_ROOT / "Dockerfile"
NESTED_PATCH_PATH = REPO_ROOT / "fix_streamlit_nested_expanders.py"
PDF_PATCH_PATH = REPO_ROOT / "fix_streamlit_pdf_text_reinsert.py"
THIS_TEST_PATH = REPO_ROOT / "tests" / "test_duplicate_input_surface_simplification_contracts.py"


def read(path: Path) -> str:
    return path.read_text(encoding="utf-8")


def compact(text: str) -> str:
    return " ".join(text.split())


def assert_contains(text: str, marker: str) -> None:
    assert marker in text, f"Expected marker missing: {marker!r}"


def assert_ordered(text: str, markers: list[str]) -> None:
    positions = []
    for marker in markers:
        index = text.find(marker)
        assert index >= 0, marker
        positions.append(index)
    assert positions == sorted(positions), markers


def test_plan_exists_and_locks_single_input_surface_target() -> None:
    assert PLAN_PATH.exists(), "Duplicate input surface simplification plan must exist"
    plan_text = read(PLAN_PATH)

    for marker in [
        "single coherent input area",
        "1. Voeg document of tekst toe",
        "2. Controleer resultaat",
        "3. Exporteer resultaat",
        "SCRUB-WP_DUPLICATE_INPUT_SURFACE_SIMPLIFICATION_CONTRACT_TESTS",
        "SCRUB-WP_DUPLICATE_INPUT_SURFACE_SIMPLIFICATION_IMPLEMENTATION",
    ]:
        assert_contains(plan_text, marker)


def test_app_has_one_direct_input_step_heading() -> None:
    app_text = read(APP_PATH)

    assert app_text.count('st.subheader("1. Voeg document of tekst toe")') == 1


def test_step_order_remains_input_review_export() -> None:
    app_text = read(APP_PATH)

    assert_ordered(
        app_text,
        [
            'st.subheader("1. Voeg document of tekst toe")',
            'st.subheader("2. Controleer resultaat")',
            'st.subheader("3. Exporteer resultaat")',
        ],
    )


def test_existing_upload_support_remains_available() -> None:
    app_text = read(APP_PATH)
    app_compact = compact(app_text)

    for marker in [
        "st.file_uploader(",
        "Upload een .txt-, .docx- of tekstgebaseerd .pdf-bestand",
        'type=["txt", "docx", "pdf"]',
        "uploaded_file_to_text(uploaded_file)",
        "uploaded_file_type",
    ]:
        assert_contains(app_text, marker)

    assert_contains(
        app_compact,
        'uploaded_file = st.file_uploader( "Upload een .txt-, .docx- of tekstgebaseerd .pdf-bestand", type=["txt", "docx", "pdf"],',
    )


def test_synthetic_legal_example_support_remains_present() -> None:
    app_text = read(APP_PATH)

    for marker in [
        "Gebruik een synthetisch juridisch testvoorbeeld",
        "get_example_names()",
        "get_example_text(sample_name)",
        "Geen testvoorbeeld laden",
        "EMBEDDED_LEGAL_TEST_CASES",
    ]:
        assert_contains(app_text, marker)


def test_pasted_or_extracted_text_area_remains_present() -> None:
    app_text = read(APP_PATH)

    for marker in [
        "st_text = st.text_area(",
        "Plak tekst of controleer de uit het document gehaalde tekst",
        'key="text_input"',
        "height=240",
    ]:
        assert_contains(app_text, marker)


def test_input_precedence_markers_remain_present() -> None:
    app_text = read(APP_PATH)

    for marker in [
        'input_text = stored_source_text(st.session_state, "".join(demo_text))',
        'cached_uploaded_file = st.session_state.get("_premium_cached_uploaded_file")',
        'uploaded_file = new_uploaded_file if new_uploaded_file is not None else cached_uploaded_file',
        'if sample_name != "Geen testvoorbeeld laden" and uploaded_file is None:',
        "if uploaded_file is not None:",
        "input_text, uploaded_file_type = uploaded_file_to_text(uploaded_file)",
    ]:
        assert_contains(app_text, marker)

    assert 'if is_premium_standard\n            else "".join(demo_text)' not in app_text


def test_review_export_and_scrub_key_surface_remains_present() -> None:
    app_text = read(APP_PATH)

    for marker in [
        "render_side_by_side_review_panel",
        "Basiscontrole",
        "Expertcontrole",
        "Gemiste waarde toevoegen",
        "Details aanpassen — vervangtabel",
        "Document downloaden",
        "Scrub Key downloaden",
        "Audit en technische bestanden",
        "render_docx_hygiene_audit_panel",
    ]:
        assert_contains(app_text, marker)


def test_no_duplicate_input_startup_or_runtime_patch_is_introduced() -> None:
    startup_text = "\n".join(
        [
            read(DOCKERFILE_PATH),
            read(NESTED_PATCH_PATH),
            read(PDF_PATCH_PATH),
        ]
    )
    startup_lower = startup_text.lower()

    for marker in [
        "duplicate_input_surface",
        "single_input_surface_patch",
        "fix_streamlit_duplicate_input",
        "runtime source mutation for duplicate input",
    ]:
        assert marker not in startup_lower

    assert startup_text.count('st.subheader("1. Voeg document of tekst toe")') == 0
    assert startup_text.count("1. Voeg document of tekst toe") == 0


def test_no_prohibited_scope_is_added_to_direct_runtime_surface() -> None:
    direct_runtime_text = "\n".join(
        [
            read(APP_PATH),
            read(DOCKERFILE_PATH),
            read(NESTED_PATCH_PATH),
        ]
    ).lower()

    prohibited_markers = [
        "new ocr",
        "pdf-to-docx reconstruction",
        "cloud processing",
        "ai document processing",
        "new upload backend",
        "new recognizers",
        "new export gates",
        "click-to-mark",
        "advanced editor",
        "full-document marking",
    ]
    for marker in prohibited_markers:
        assert marker not in direct_runtime_text, marker


def test_contract_tests_remain_source_level_only() -> None:
    tree = ast.parse(read(THIS_TEST_PATH))
    imported_roots = set()
    for node in ast.walk(tree):
        if isinstance(node, ast.Import):
            imported_roots.update(alias.name.split(".")[0] for alias in node.names)
        elif isinstance(node, ast.ImportFrom) and node.module:
            imported_roots.add(node.module.split(".")[0])

    assert "streamlit" not in imported_roots
    assert "presidio_streamlit" not in imported_roots


def test_input_controls_are_grouped_under_single_input_surface() -> None:
    app_text = read(APP_PATH)

    input_start = app_text.index('st.subheader("1. Voeg document of tekst toe")')
    review_start = app_text.index('st.subheader("2. Controleer resultaat")')
    input_section = app_text[input_start:review_start]

    assert "with st.container(border=True):" in input_section
    assert input_section.count("st.file_uploader(") == 1
    assert input_section.count("st.text_area(") == 1
    assert "Gebruik een synthetisch juridisch testvoorbeeld" in input_section
    assert "uploaded_file_to_text(uploaded_file)" in input_section
    assert 'type=["txt", "docx", "pdf"]' in input_section
    assert 'key="text_input"' in input_section