Spaces:
Sleeping
Sleeping
| 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 | |