Files
geointel/backend/tests/test_sprint198_detection_review_completion.py
T
JensandClaude Opus 5 3e4e211fad test frontend wiring instead of frontend formatting
19 tests were failing on main. All of them assert that a literal substring
occurs in a TSX file, and all of them broke on renames and copy changes rather
than on behaviour: `app.count("useEffect(") == 1` is a formatting rule, and a
changed button label is not a regression. 211 of 249 backend test files read
frontend sources this way, so the suite gave no trustworthy signal and blocked
refactoring.

tests/frontend_contract.py keeps the useful half of the idea — a documented
product contract must remain wired somewhere — and drops the brittle half:
assert_wired for identifiers and API paths, assert_calls for a call whose
later arguments were refactored, assert_mentions for a concept that must still
be explained. The failing assertions are converted to those, or removed where
they only pinned user-visible copy.

test_frontend_contract_test_style.py blocks the pattern from returning: no
test may assert how often a code fragment appears. Counting list values or
network calls is unaffected.

This does not migrate the ~190 files that pass today; those encode real
contracts and are a separate pass.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-22 14:34:13 +02:00

129 lines
4.5 KiB
Python

from __future__ import annotations
import importlib.util
from pathlib import Path
import pytest
ROOT = Path(__file__).resolve().parents[2]
def _load_validator():
script = ROOT / "scripts" / "validate_detection_false_negative_review_decisions.py"
spec = importlib.util.spec_from_file_location("false_negative_review_validator", script)
assert spec and spec.loader
module = importlib.util.module_from_spec(spec)
spec.loader.exec_module(module)
return module
def _summary() -> dict:
return {
"portfolio_path": "/evidence/portfolio.json",
"selected_features": [
{
"reference_feature_id": "reference-1",
"sample_slug": "mol",
"area_m2": 42.0,
"area_bucket": "small_25_100_m2",
"source_tile_path": "/storage/tiles/mol.tif",
"geometry": {
"type": "Polygon",
"coordinates": [[[5.0, 51.0], [5.001, 51.0], [5.001, 51.001], [5.0, 51.0]]],
},
"properties": {"source_feature_id": "grb-1"},
},
{
"reference_feature_id": "reference-2",
"sample_slug": "mol",
"area_m2": 18.0,
"area_bucket": "tiny_lt_25_m2",
"source_tile_path": "/storage/tiles/mol.tif",
"geometry": {
"type": "Polygon",
"coordinates": [[[5.01, 51.0], [5.011, 51.0], [5.011, 51.001], [5.01, 51.0]]],
},
},
],
}
def test_false_negative_validator_exports_only_explicit_confirmed_misses() -> None:
validator = _load_validator()
report, confirmed = validator.validate(
_summary(),
[
{
"reference_feature_id": "reference-1",
"review_decision": "confirmed_model_false_negative",
"review_notes": "Visible roof with no suitable candidate.",
},
{
"reference_feature_id": "reference-2",
"review_decision": "qa_alignment_mismatch",
"review_notes": "Candidate overlaps the footprint.",
},
],
)
assert report["status"] == "complete"
assert report["confirmed_model_false_negative_count"] == 1
assert report["decision_counts"]["qa_alignment_mismatch"] == 1
assert len(confirmed["features"]) == 1
assert confirmed["features"][0]["properties"]["reference_feature_id"] == "reference-1"
def test_false_negative_validator_fails_closed_for_incomplete_or_invalid_reviews() -> None:
validator = _load_validator()
report, confirmed = validator.validate(
_summary(),
[
{
"reference_feature_id": "reference-1",
"review_decision": "unreviewed",
"review_notes": "",
},
{
"reference_feature_id": "reference-2",
"review_decision": "imagery_obscured_or_uncertain",
"review_notes": "Tile edge prevents a decision.",
},
],
)
assert report["status"] == "review_required"
assert confirmed["features"] == []
with pytest.raises(SystemExit, match="Invalid review decision"):
validator.validate(
_summary(),
[
{
"reference_feature_id": "reference-1",
"review_decision": "confirmed_model_false_positive",
"review_notes": "wrong role",
},
{
"reference_feature_id": "reference-2",
"review_decision": "unreviewed",
"review_notes": "",
},
],
)
def test_readiness_compiles_false_negative_review_validator() -> None:
readiness = (ROOT / "scripts" / "run_readiness_check.sh").read_text(encoding="utf-8")
assert "validate_detection_false_negative_review_decisions.py" in readiness
def test_map_explains_strict_and_diagnostic_detection_matching() -> None:
workspace = (
ROOT / "frontend" / "src" / "components" / "map" / "MapWorkspace.tsx"
).read_text(encoding="utf-8")
# Both matching methods must be named; the exact label may change.
assert "strikte" in workspace.casefold()
assert "Rechthoekcontrole" in workspace
assert "possible_box_to_footprint_mismatch_count" in workspace
assert "De kerncijfers hierboven gebruiken strikte GRB-footprints" in workspace