Spaces:
Running
Running
File size: 5,869 Bytes
f02a571 429a15d f02a571 429a15d f02a571 429a15d f02a571 429a15d f02a571 429a15d f02a571 429a15d f02a571 429a15d f02a571 429a15d f02a571 5ae85c9 853ce51 5ae85c9 f02a571 853ce51 429a15d f02a571 429a15d f02a571 429a15d f02a571 429a15d f02a571 429a15d f02a571 429a15d f02a571 429a15d f02a571 429a15d f02a571 429a15d f02a571 429a15d f02a571 429a15d f02a571 429a15d 70877b7 f02a571 70877b7 f02a571 70877b7 429a15d f02a571 | 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 | from __future__ import annotations
from pathlib import Path
REPO_ROOT = Path(__file__).resolve().parents[1]
APP = REPO_ROOT / "presidio_streamlit.py"
SERIAL_PANEL = REPO_ROOT / "serial_review_panel_ui.py"
RENDERER = REPO_ROOT / "replacement_decision_panel_ui.py"
HELPER = REPO_ROOT / "replacement_decision.py"
PLAN = REPO_ROOT / "REPLACE_LOGIC_UI_PLAN.md"
CONTRACT_TEST = REPO_ROOT / "tests" / "test_replace_logic_ui_contract.py"
STARTUP_PATCH = REPO_ROOT / "fix_streamlit_nested_expanders.py"
def _normal_flow_text() -> str:
return APP.read_text(encoding="utf-8") + "\n" + SERIAL_PANEL.read_text(encoding="utf-8")
def _renderer_text() -> str:
return RENDERER.read_text(encoding="utf-8")
def test_replacement_helper_and_contract_assets_are_preserved_for_redesign():
assert HELPER.exists()
assert PLAN.exists()
assert CONTRACT_TEST.exists()
assert RENDERER.exists()
helper_text = HELPER.read_text(encoding="utf-8")
plan_text = PLAN.read_text(encoding="utf-8")
contract_text = CONTRACT_TEST.read_text(encoding="utf-8")
assert "build_replacement_decision" in helper_text
assert "build_replacement_audit" in helper_text
assert "matching_occurrence_ids" in helper_text
assert "staged decision preview only" in plan_text
assert "existing review table remains source of truth and fallback" in plan_text
assert "test_staged_vs_applied_state_contract_is_explicit_and_non_mutating" in contract_text
def test_replacement_helper_panel_is_not_rendered_in_normal_scrub_flow():
app_text = APP.read_text(encoding="utf-8")
serial_text = SERIAL_PANEL.read_text(encoding="utf-8")
normal_flow = _normal_flow_text()
assert "render_serial_review_panel(" in app_text
assert "from replacement_decision_panel_ui import" not in app_text
assert "from replacement_decision_panel_ui import" not in serial_text
assert "render_replacement_decision_panel(" not in normal_flow
assert "Replacement decision helper" not in normal_flow
assert "replacement_decision_preview" not in normal_flow
def test_serial_review_panel_remains_available_and_table_first():
normal_flow = _normal_flow_text()
serial_text = SERIAL_PANEL.read_text(encoding="utf-8")
assert "Stap voor stap controleren" in serial_text
assert "expanded=False" in serial_text
assert "Loop de gevonden gegevens één voor één na" in serial_text
assert "de vervangtabel blijft leidend voor export" in serial_text
assert "Filter voor stap-voor-stap controle" in serial_text
assert "Serial review — experimentele reviewhulp" not in serial_text
assert "table-first baseline" not in serial_text
assert "no Scrub Key mutation" not in serial_text
assert "no export blocking" not in serial_text
assert "no reinsert behavior change" not in serial_text
assert "render_serial_review_panel(" in normal_flow
assert "include_side_by_side=False" in normal_flow
assert "render_side_by_side_review_panel(" in normal_flow
assert "replacement_editor" in normal_flow
def test_parked_replacement_panel_still_documents_non_mutating_boundaries():
renderer_text = _renderer_text()
for phrase in [
"staged decision preview only",
"staged decision state is not applied state",
"existing review table remains source of truth and fallback",
"does not mutate review rows",
"does not write edited_replacements_df",
"does not apply replacements",
"does not write Scrub Key mappings",
"does not block export",
"does not call export/download",
"does not change reinsert behavior",
"does not use fuzzy matching",
"does not use real data",
]:
assert phrase in renderer_text
def test_normal_flow_does_not_call_export_download_scrub_key_or_reinsert_from_replacement_panel():
normal_flow = _normal_flow_text().lower()
forbidden_calls = [
"render_replacement_decision_panel(",
"replacement_decision_panel_ui",
"scrub_key_to_json(",
"build_scrub_key(",
"validate_scrub_key(",
"reinsert_from_scrub_key(",
"reinsert_docx_bytes(",
"reinsert_txt_bytes(",
"replacement_decision_preview",
]
for marker in forbidden_calls:
assert marker.lower() not in normal_flow
def test_no_automatic_replacement_or_editor_marking_features_were_added():
normal_flow = _normal_flow_text().lower()
renderer_text = _renderer_text().lower()
forbidden_normal_flow_markers = [
"automatic_replacement = true",
"review_table_mutation = true",
"st.session_state[\"replacement_editor",
"click-to-mark",
"advanced editor",
"full-document marking",
"unsafe_allow_html",
]
for marker in forbidden_normal_flow_markers:
assert marker not in normal_flow
assert "automatic_replacement" in renderer_text
assert "scrub_key_writes" in renderer_text
assert "export_blocking" in renderer_text
assert "reinsert_behavior_change" in renderer_text
def test_no_startup_source_mutation_or_cloud_real_data_fixture_added():
rendered = _normal_flow_text() + "\n" + _renderer_text()
startup_text = STARTUP_PATCH.read_text(encoding="utf-8")
app_file_write_marker = "APP_FILE" + ".write_text"
replace_once_marker = "replace" + "_once("
assert "replacement_decision_panel_ui" not in startup_text
assert app_file_write_marker not in rendered
assert replace_once_marker not in rendered
assert "cloud services" in rendered.lower()
assert "real data" in rendered.lower()
forbidden_real_data_examples = [
"Jan " + "Jansen",
"Piet " + "de " + "Vries",
"123" + "456" + "782",
]
for forbidden in forbidden_real_data_examples:
assert forbidden not in rendered
|