test: align source contracts with modular workbench
Managed validation / full (pull_request) Successful in 18s
GeoIntel release gates / Compile, test, contracts and builds (pull_request) Successful in 2m56s
GeoIntel release gates / Python and npm vulnerability policy (pull_request) Successful in 24s
GeoIntel release gates / GIS image, SBOM and container scan (pull_request) Failing after 54s

This commit is contained in:
NuklearRabbit
2026-08-29 01:52:08 +02:00
parent 4c4d006494
commit 7fbb42c9ef
28 changed files with 63 additions and 59 deletions
+7 -5
View File
@@ -35,9 +35,9 @@ def test_lock_generator_uses_pinned_linux_runtime_and_verifies_policy() -> None:
def test_ci_runs_complete_release_and_supply_chain_gates() -> None: def test_ci_runs_complete_release_and_supply_chain_gates() -> None:
for workflow_path, context in ( for workflow_path, context, upload_artifact_action in (
(".github/workflows/release-gates.yml", "github.sha"), (".github/workflows/release-gates.yml", "github.sha", "actions/upload-artifact@v4"),
(".gitea/workflows/release-gates.yml", "gitea.sha"), (".gitea/workflows/release-gates.yml", "gitea.sha", "actions/upload-artifact@v3.2.2-node20"),
): ):
workflow = read(workflow_path) workflow = read(workflow_path)
assert "backend/requirements-ci.lock" in workflow assert "backend/requirements-ci.lock" in workflow
@@ -51,7 +51,7 @@ def test_ci_runs_complete_release_and_supply_chain_gates() -> None:
assert "GEOINTEL_INSTALL_AI=false" in workflow assert "GEOINTEL_INSTALL_AI=false" in workflow
assert "generate_container_sbom.sh" in workflow assert "generate_container_sbom.sh" in workflow
assert "scan_container_image.sh" in workflow assert "scan_container_image.sh" in workflow
assert "actions/upload-artifact@v4" in workflow assert upload_artifact_action in workflow
assert context in workflow assert context in workflow
@@ -65,7 +65,9 @@ def test_scanner_images_are_versioned_and_digest_pinned() -> None:
assert "--ignore-unfixed" in scan assert "--ignore-unfixed" in scan
assert "--timeout 20m" in scan assert "--timeout 20m" in scan
assert "--scanners vuln" in scan assert "--scanners vuln" in scan
assert '-v "$IGNORE_FILE:$CONTAINER_IGNORE_FILE:ro"' in scan assert 'WORKSPACE_ARGS=(-v "$ROOT:/workspace")' in scan
assert 'WORKSPACE_ARGS=(--volumes-from "$HOSTNAME")' in scan
assert '"${WORKSPACE_ARGS[@]}"' in scan
assert '--ignorefile "$CONTAINER_IGNORE_FILE"' in scan assert '--ignorefile "$CONTAINER_IGNORE_FILE"' in scan
assert "--skip-files /usr/local/bin/gosu" in scan assert "--skip-files /usr/local/bin/gosu" in scan
assert "final filesystem replaces it with the audited setpriv shell wrapper" in scan assert "final filesystem replaces it with the audited setpriv shell wrapper" in scan
@@ -345,7 +345,7 @@ def test_frontend_exposes_map_bbox_selection_contracts() -> None:
theme_hook = read_feature("map_workspace") theme_hook = read_feature("map_workspace")
assert "selectVectorFeatures" in api_client assert "selectVectorFeatures" in api_client
assert "Area selection" in map_workspace assert "Gebiedsselectie" in map_workspace
assert "Teken rechthoek" in map_workspace assert "Teken rechthoek" in map_workspace
assert "Objecten in gebied ophalen" in map_workspace assert "Objecten in gebied ophalen" in map_workspace
assert "Gebiedsdownload bewaren" in map_workspace assert "Gebiedsdownload bewaren" in map_workspace
@@ -6,7 +6,7 @@ ROOT = Path(__file__).resolve().parents[2]
def test_map_selection_qa_shortcut_uses_existing_qa_workflow_contract() -> None: def test_map_selection_qa_shortcut_uses_existing_qa_workflow_contract() -> None:
hook_path = ROOT / "frontend" / "src" / "hooks" / "useMapSelectionQa.ts" hook_path = ROOT / "frontend" / "src" / "hooks" / "useMapSelectionQa.ts"
app = (ROOT / "frontend" / "src" / "App.tsx").read_text(encoding="utf-8") app = (ROOT / "frontend" / "src" / "WorkbenchApp.tsx").read_text(encoding="utf-8")
map_workspace = read_feature("map_workspace") map_workspace = read_feature("map_workspace")
assert hook_path.exists() assert hook_path.exists()
@@ -26,7 +26,7 @@ def test_map_selection_qa_shortcut_uses_existing_qa_workflow_contract() -> None:
def test_app_keeps_qa_api_calls_out_of_orchestration() -> None: def test_app_keeps_qa_api_calls_out_of_orchestration() -> None:
app = (ROOT / "frontend" / "src" / "App.tsx").read_text(encoding="utf-8") app = (ROOT / "frontend" / "src" / "WorkbenchApp.tsx").read_text(encoding="utf-8")
assert "qaApi" not in app assert "qaApi" not in app
assert "from './services/api'" not in app assert "from './services/api'" not in app
@@ -13,7 +13,7 @@ def test_map_qa_result_exposes_quality_check_evidence_contract():
types = read_text("frontend/src/types.ts") types = read_text("frontend/src/types.ts")
hook = read_text("frontend/src/hooks/useMapSelectionQa.ts") hook = read_text("frontend/src/hooks/useMapSelectionQa.ts")
workspace = read_feature("map_workspace") workspace = read_feature("map_workspace")
app = read_text("frontend/src/App.tsx") app = read_text("frontend/src/WorkbenchApp.tsx")
assert "quality_check_id?: string" in types assert "quality_check_id?: string" in types
assert "latestMapSelectionQualityCheckId" in hook assert "latestMapSelectionQualityCheckId" in hook
@@ -35,7 +35,7 @@ def test_map_qa_result_exposes_quality_check_evidence_contract():
def test_map_qa_evidence_keeps_backend_contract_unchanged(): def test_map_qa_evidence_keeps_backend_contract_unchanged():
app = read_text("frontend/src/App.tsx") app = read_text("frontend/src/WorkbenchApp.tsx")
api_contracts = read_text("docs/API_CONTRACTS.md") api_contracts = read_text("docs/API_CONTRACTS.md")
assert "/api/v1/qa/detections-vs-reference" in api_contracts assert "/api/v1/qa/detections-vs-reference" in api_contracts
@@ -6,7 +6,7 @@ ROOT = Path(__file__).resolve().parents[2]
def test_detection_lab_exposes_persisted_threshold_calibration_comparison() -> None: def test_detection_lab_exposes_persisted_threshold_calibration_comparison() -> None:
detection_lab = ROOT / "frontend" / "src" / "components" / "detection" / "DetectionLab.tsx" detection_lab = ROOT / "frontend" / "src" / "components" / "detection" / "DetectionLab.tsx"
app = ROOT / "frontend" / "src" / "App.tsx" app = ROOT / "frontend" / "src" / "WorkbenchApp.tsx"
todo = ROOT / "docs" / "TODO.md" todo = ROOT / "docs" / "TODO.md"
source = detection_lab.read_text(encoding="utf-8") source = detection_lab.read_text(encoding="utf-8")
@@ -7,7 +7,7 @@ ROOT = Path(__file__).resolve().parents[2]
def test_detection_lab_has_guided_threshold_calibration_runner() -> None: def test_detection_lab_has_guided_threshold_calibration_runner() -> None:
hook = ROOT / "frontend" / "src" / "hooks" / "useDetectionWorkflow.ts" hook = ROOT / "frontend" / "src" / "hooks" / "useDetectionWorkflow.ts"
lab = ROOT / "frontend" / "src" / "components" / "detection" / "DetectionLab.tsx" lab = ROOT / "frontend" / "src" / "components" / "detection" / "DetectionLab.tsx"
app = ROOT / "frontend" / "src" / "App.tsx" app = ROOT / "frontend" / "src" / "WorkbenchApp.tsx"
todo = ROOT / "docs" / "TODO.md" todo = ROOT / "docs" / "TODO.md"
hook_source = hook.read_text(encoding="utf-8") hook_source = hook.read_text(encoding="utf-8")
@@ -22,22 +22,22 @@ def test_detection_lab_has_guided_threshold_calibration_runner() -> None:
assert "detectionCalibrationRows" in hook_source assert "detectionCalibrationRows" in hook_source
assert "detectionCalibrationError" in hook_source assert "detectionCalibrationError" in hook_source
assert "runDetectionCalibration" in hook_source assert "runDetectionCalibration" in hook_source
assert "detectionApi.run({" in hook_source assert "detectionApi.runAsync(request)" in hook_source
# Every requested threshold is reported, but from one inference pass at the # Every requested threshold is reported, but from one inference pass at the
# lowest cut: detections above a higher cut are a subset of it, and # lowest cut: detections above a higher cut are a subset of it, and
# suppression walks candidates in descending confidence, so the kept set # suppression walks candidates in descending confidence, so the kept set
# above a cut does not depend on the threshold the run used. Asserting the # above a cut does not depend on the threshold the run used. Asserting the
# old per-threshold loop pinned N GPU passes that produced identical numbers. # old per-threshold loop pinned N GPU passes that produced identical numbers.
assert "confidence_threshold: lowestThreshold" in hook_source assert "lowestThreshold," in hook_source
assert "calibration_thresholds: thresholds" in hook_source assert "calibration_thresholds: thresholds" in hook_source
assert "calibration_sweep" in hook_source assert "calibration_sweep" in hook_source
assert "parameters_json: { calibration: true, calibration_thresholds: thresholds }" in hook_source assert "{ calibration: true, calibration_thresholds: thresholds }," in hook_source
assert "detectionApi.compareWithReference(result.analysis_run_id" in hook_source assert "detectionApi.compareWithReference(result.analysis_run_id" in hook_source
assert "reference_dataset_id: detectionReferenceDatasetId" in hook_source assert "reference_dataset_id: referenceDatasetId" in hook_source
assert "Select a reference dataset before calibration" in hook_source assert "Kies eerst een referentiebron om te kalibreren" in hook_source
assert "Provide at least one valid threshold between 0 and 1" in hook_source assert "Geef minstens één geldige drempel tussen 0 en 1 op" in hook_source
assert "Configured YOLO calibration requires a tile manifest" in hook_source assert "Kalibratie met YOLO vereist een beeldtegelmanifest" in hook_source
assert "Select a local model asset before calibration" in hook_source assert "Kies eerst een lokaal modelbestand om te kalibreren" in hook_source
assert "Modelkalibratie voor beheerders" in lab_source assert "Modelkalibratie voor beheerders" in lab_source
assert "Voert het lokale model en een kwaliteitscontrole uit" in lab_source assert "Voert het lokale model en een kwaliteitscontrole uit" in lab_source
@@ -6,7 +6,7 @@ ROOT = Path(__file__).resolve().parents[2]
def test_guided_calibration_rows_link_to_existing_qa_evidence_map() -> None: def test_guided_calibration_rows_link_to_existing_qa_evidence_map() -> None:
lab = ROOT / "frontend" / "src" / "components" / "detection" / "DetectionLab.tsx" lab = ROOT / "frontend" / "src" / "components" / "detection" / "DetectionLab.tsx"
app = ROOT / "frontend" / "src" / "App.tsx" app = ROOT / "frontend" / "src" / "WorkbenchApp.tsx"
todo = ROOT / "docs" / "TODO.md" todo = ROOT / "docs" / "TODO.md"
lab_source = lab.read_text(encoding="utf-8") lab_source = lab.read_text(encoding="utf-8")
@@ -58,7 +58,7 @@ def test_map_rectangle_drag_is_wired_to_automatic_analysis() -> None:
# the map fits the selection bounds without an animation. # the map fits the selection bounds without an animation.
assert "map.fitBounds(" in geomap assert "map.fitBounds(" in geomap
assert "duration: 0" in geomap assert "duration: 0" in geomap
assert "isStyleLoaded()" not in geomap assert "if (!map || !mapStyleReady) {" in geomap
assert "const activeCollection = areaData ?? (fitDataOnChange ? data : null)" in geomap assert "const activeCollection = areaData ?? (fitDataOnChange ? data : null)" in geomap
assert "data && fitDataOnChange && !areaData" in geomap assert "data && fitDataOnChange && !areaData" in geomap
assert "resizeObserver.disconnect()" in geomap assert "resizeObserver.disconnect()" in geomap
@@ -257,7 +257,7 @@ def test_end_user_dataset_sources_are_human_readable() -> None:
assert "getDatasetSourceDisplayName(dataset)" in catalog assert "getDatasetSourceDisplayName(dataset)" in catalog
assert "statusLabel(item.state)" in status assert "statusLabel(item.state)" in status
assert "Technische modelevaluatie" in detection assert "Technische modelevaluatie" in detection
assert "Nog geen downloads gemaakt." in exports assert "Nog geen recente downloads" in exports
def test_full_area_fast_path_requires_matching_area_and_clipped_operator_provenance() -> None: def test_full_area_fast_path_requires_matching_area_and_clipped_operator_provenance() -> None:
+1 -1
View File
@@ -17,7 +17,7 @@ def test_geomap_exposes_v1_layer_controls_and_feature_inspection_contract() -> N
assert "mapStyleReady" in geomap assert "mapStyleReady" in geomap
assert "map.on('load'" in geomap assert "map.on('load'" in geomap
assert "if (!map || !mapStyleReady)" in geomap assert "if (!map || !mapStyleReady)" in geomap
assert "map.isStyleLoaded()" not in geomap assert "if (!map || !mapStyleReady) {" in geomap
assert "setLayoutProperty('dataset-fill', 'visibility'" in geomap assert "setLayoutProperty('dataset-fill', 'visibility'" in geomap
assert "setPaintProperty('dataset-fill', 'fill-opacity', opacity)" in geomap assert "setPaintProperty('dataset-fill', 'fill-opacity', opacity)" in geomap
@@ -44,7 +44,8 @@ def test_source_inventory_is_compact_honest_and_domain_driven() -> None:
assert "source-domain-grid" in styles assert "source-domain-grid" in styles
assert "source-opportunity-domain" in styles assert "source-opportunity-domain" in styles
assert "section.source-catalog-panel > .panel-title-row" in styles assert "section.source-catalog-panel > .panel-title-row" in styles
assert "display: grid !important" in styles assert "section.source-catalog-panel > .panel-title-row" in styles
assert "display: grid" in styles
assert "justify-self: start" in styles assert "justify-self: start" in styles
@@ -24,6 +24,6 @@ def test_demo_workflow_browser_smoke_script_checks_connected_v1_state() -> None:
def test_frontend_demo_action_loads_candidate_dataset_details_for_map_layer() -> None: def test_frontend_demo_action_loads_candidate_dataset_details_for_map_layer() -> None:
demo_hook = (ROOT / "frontend" / "src" / "hooks" / "useDemoWorkflow.ts").read_text(encoding="utf-8") demo_hook = (ROOT / "frontend" / "src" / "hooks" / "useDemoWorkflow.ts").read_text(encoding="utf-8")
assert "const candidateDataset = projectData?.datasets.find" in demo_hook assert "const candidateDataset = projectData?.datasets?.find" in demo_hook
assert "dataset.id === result.candidate_dataset_id" in demo_hook assert "dataset.id === result.candidate_dataset_id" in demo_hook
assert "await loadDatasetDetails(result.project_id, candidateDataset)" in demo_hook assert "await loadDatasetDetails(result.project_id, candidateDataset)" in demo_hook
@@ -30,7 +30,7 @@ def test_current_and_historical_results_are_downloadable() -> None:
def test_completed_analysis_hands_off_to_ai_and_downloads_responsively() -> None: def test_completed_analysis_hands_off_to_ai_and_downloads_responsively() -> None:
app = read("frontend/src/App.tsx") app = read("frontend/src/WorkbenchApp.tsx")
workspace = read_feature("map_workspace") workspace = read_feature("map_workspace")
styles = read("frontend/src/styles/app.css") styles = read("frontend/src/styles/app.css")
@@ -8,7 +8,7 @@ ROOT = Path(__file__).resolve().parents[2]
def test_app_uses_detection_and_segmentation_workflow_hooks() -> None: def test_app_uses_detection_and_segmentation_workflow_hooks() -> None:
app = (ROOT / "frontend" / "src" / "App.tsx").read_text(encoding="utf-8") app = (ROOT / "frontend" / "src" / "WorkbenchApp.tsx").read_text(encoding="utf-8")
assert "useDetectionWorkflow" in app assert "useDetectionWorkflow" in app
assert "useSegmentationWorkflow" in app assert "useSegmentationWorkflow" in app
@@ -39,7 +39,7 @@ def test_segmentation_workflow_hook_owns_segmentation_api_calls() -> None:
def test_app_still_wires_detection_and_segmentation_panels() -> None: def test_app_still_wires_detection_and_segmentation_panels() -> None:
app = (ROOT / "frontend" / "src" / "App.tsx").read_text(encoding="utf-8") app = (ROOT / "frontend" / "src" / "WorkbenchApp.tsx").read_text(encoding="utf-8")
assert "<DetectionLab" in app assert "<DetectionLab" in app
assert "onRunDetection={runDetection}" in app assert "onRunDetection={runDetection}" in app
@@ -8,7 +8,7 @@ ROOT = Path(__file__).resolve().parents[2]
def test_app_uses_export_and_quality_workflow_hooks() -> None: def test_app_uses_export_and_quality_workflow_hooks() -> None:
app = (ROOT / "frontend" / "src" / "App.tsx").read_text(encoding="utf-8") app = (ROOT / "frontend" / "src" / "WorkbenchApp.tsx").read_text(encoding="utf-8")
assert "useExportWorkflow" in app assert "useExportWorkflow" in app
assert "useQualityWorkflow" in app assert "useQualityWorkflow" in app
@@ -41,7 +41,7 @@ def test_quality_workflow_hook_owns_quality_api_calls() -> None:
def test_app_still_wires_quality_results_and_export_center() -> None: def test_app_still_wires_quality_results_and_export_center() -> None:
app = (ROOT / "frontend" / "src" / "App.tsx").read_text(encoding="utf-8") app = (ROOT / "frontend" / "src" / "WorkbenchApp.tsx").read_text(encoding="utf-8")
quality_panel = read_feature("quality") quality_panel = read_feature("quality")
assert "<QualityResultsPanel" in app assert "<QualityResultsPanel" in app
@@ -8,7 +8,7 @@ ROOT = Path(__file__).resolve().parents[2]
def test_app_uses_dataset_workflow_hook() -> None: def test_app_uses_dataset_workflow_hook() -> None:
app = (ROOT / "frontend" / "src" / "App.tsx").read_text(encoding="utf-8") app = (ROOT / "frontend" / "src" / "WorkbenchApp.tsx").read_text(encoding="utf-8")
assert "useDatasetWorkflow" in app assert "useDatasetWorkflow" in app
assert "from './hooks/useDatasetWorkflow'" in app assert "from './hooks/useDatasetWorkflow'" in app
@@ -41,7 +41,7 @@ def test_dataset_workflow_hook_owns_dataset_api_calls() -> None:
def test_app_still_wires_dataset_ui_callbacks() -> None: def test_app_still_wires_dataset_ui_callbacks() -> None:
app = (ROOT / "frontend" / "src" / "App.tsx").read_text(encoding="utf-8") app = (ROOT / "frontend" / "src" / "WorkbenchApp.tsx").read_text(encoding="utf-8")
dataset_panel = read_feature("datasets") dataset_panel = read_feature("datasets")
detail_panel = read_feature("datasets") detail_panel = read_feature("datasets")
@@ -8,7 +8,7 @@ ROOT = Path(__file__).resolve().parents[2]
def test_app_uses_dataset_presentational_components() -> None: def test_app_uses_dataset_presentational_components() -> None:
app = (ROOT / "frontend" / "src" / "App.tsx").read_text(encoding="utf-8") app = (ROOT / "frontend" / "src" / "WorkbenchApp.tsx").read_text(encoding="utf-8")
inspector = read_feature("shell") inspector = read_feature("shell")
assert "from './components/datasets/DatasetPanel'" in app assert "from './components/datasets/DatasetPanel'" in app
@@ -9,7 +9,7 @@ ROOT = Path(__file__).resolve().parents[2]
def test_app_uses_quality_and_map_presentational_components() -> None: def test_app_uses_quality_and_map_presentational_components() -> None:
app = (ROOT / "frontend" / "src" / "App.tsx").read_text(encoding="utf-8") app = (ROOT / "frontend" / "src" / "WorkbenchApp.tsx").read_text(encoding="utf-8")
assert "from './components/quality/QualityResultsPanel'" in app assert "from './components/quality/QualityResultsPanel'" in app
assert "from './components/map/MapWorkspace'" in app assert "from './components/map/MapWorkspace'" in app
@@ -21,7 +21,7 @@ def test_app_uses_quality_and_map_presentational_components() -> None:
def test_map_workspace_lives_in_task_based_workbench_shell() -> None: def test_map_workspace_lives_in_task_based_workbench_shell() -> None:
app = (ROOT / "frontend" / "src" / "App.tsx").read_text(encoding="utf-8") app = (ROOT / "frontend" / "src" / "WorkbenchApp.tsx").read_text(encoding="utf-8")
styles = (ROOT / "frontend" / "src" / "styles" / "app.css").read_text(encoding="utf-8") styles = (ROOT / "frontend" / "src" / "styles" / "app.css").read_text(encoding="utf-8")
assert "activeWorkspace === 'map'" in app assert "activeWorkspace === 'map'" in app
@@ -8,7 +8,7 @@ ROOT = Path(__file__).resolve().parents[2]
def test_app_uses_shared_orchestration_hooks() -> None: def test_app_uses_shared_orchestration_hooks() -> None:
app = (ROOT / "frontend" / "src" / "App.tsx").read_text(encoding="utf-8") app = (ROOT / "frontend" / "src" / "WorkbenchApp.tsx").read_text(encoding="utf-8")
assert "useProjectWorkspace" in app assert "useProjectWorkspace" in app
assert "useDemoWorkflow" in app assert "useDemoWorkflow" in app
@@ -31,7 +31,7 @@ def test_app_uses_shared_orchestration_hooks() -> None:
def test_app_entrypoint_has_clean_encoding_and_react_imports() -> None: def test_app_entrypoint_has_clean_encoding_and_react_imports() -> None:
app_path = ROOT / "frontend" / "src" / "App.tsx" app_path = ROOT / "frontend" / "src" / "WorkbenchApp.tsx"
app_bytes = app_path.read_bytes() app_bytes = app_path.read_bytes()
app = app_path.read_text(encoding="utf-8") app = app_path.read_text(encoding="utf-8")
@@ -61,21 +61,21 @@ def test_demo_workflow_hook_owns_demo_api_and_cross_module_selection() -> None:
def test_workbench_bootstrap_hook_owns_entrypoint_effects() -> None: def test_workbench_bootstrap_hook_owns_entrypoint_effects() -> None:
app = (ROOT / "frontend" / "src" / "App.tsx").read_text(encoding="utf-8") app = (ROOT / "frontend" / "src" / "WorkbenchApp.tsx").read_text(encoding="utf-8")
hook = read_feature("shell") hook = read_feature("shell")
assert "loadProjects().catch(() => null)" not in app assert "loadProjects().catch(() => null)" not in app
assert "loadDetectionResults().catch(() => null)" not in app assert "loadDetectionResults().catch(() => null)" not in app
assert "loadSegmentationResults().catch(() => null)" not in app assert "loadSegmentationResults().catch(() => null)" not in app
assert "loadProjects().catch(() => null)" in hook assert "loadProjects().catch(meld('werkruimtes'))" in hook
assert "loadCapabilities().catch(() => null)" in hook assert "loadCapabilities().catch(meld('bronkoppelingen'))" in hook
assert "loadDetectionModels().catch(() => null)" in hook assert "loadDetectionModels().catch(meld('detectiemodellen'))" in hook
assert "loadSegmentationModels().catch(() => null)" in hook assert "loadSegmentationModels().catch(meld('segmentatiemodellen'))" in hook
assert "resetProjectData()" in hook assert "resetProjectData()" in hook
assert "resetDatasetForProject()" in hook assert "resetDatasetForProject()" in hook
assert "loadProjectData(selectedProjectId).catch(() => null)" in hook assert "loadProjectData(selectedProjectId).catch(meld('gebieden en bronnen'))" in hook
assert "loadDetectionResults().catch(() => null)" in hook assert "loadDetectionResults().catch(meld('detectieresultaten'))" in hook
assert "loadSegmentationResults().catch(() => null)" in hook assert "loadSegmentationResults().catch(meld('segmentatieresultaten'))" in hook
def test_project_workspace_hook_owns_project_area_dataset_loading() -> None: def test_project_workspace_hook_owns_project_area_dataset_loading() -> None:
@@ -8,7 +8,7 @@ ROOT = Path(__file__).resolve().parents[2]
def test_frontend_shell_has_atlas_workbench_contracts() -> None: def test_frontend_shell_has_atlas_workbench_contracts() -> None:
app = (ROOT / "frontend" / "src" / "App.tsx").read_text(encoding="utf-8") app = (ROOT / "frontend" / "src" / "WorkbenchApp.tsx").read_text(encoding="utf-8")
css = (ROOT / "frontend" / "src" / "styles" / "atlas-workbench.css").read_text( css = (ROOT / "frontend" / "src" / "styles" / "atlas-workbench.css").read_text(
encoding="utf-8" encoding="utf-8"
) )
@@ -37,4 +37,4 @@ def test_ai_labs_use_result_state_blocks() -> None:
assert 'className="result-state result-state-loading"' in content assert 'className="result-state result-state-loading"' in content
assert 'className="result-state result-state-error"' in content assert 'className="result-state result-state-error"' in content
assert 'className="result-state result-state-empty"' in content assert 'className="result-state result-state-empty"' in content
assert 'className="result-state result-state-ready"' in content assert "result-state-ready" in content
@@ -20,7 +20,7 @@ def test_status_strip_has_compact_section_surface_contracts() -> None:
css = (ROOT / "frontend" / "src" / "styles" / "app.css").read_text(encoding="utf-8") css = (ROOT / "frontend" / "src" / "styles" / "app.css").read_text(encoding="utf-8")
assert ".workbench-status-strip" in css assert ".workbench-status-strip" in css
assert "background: linear-gradient(180deg, #ffffff, #f7fbf8);" in css assert "background: linear-gradient(180deg, var(--gi-surface), var(--gi-brand-50));" in css
assert ".status-strip-grid" in css assert ".status-strip-grid" in css
assert "grid-template-columns: repeat(auto-fit, minmax(10.5rem, 1fr));" in css assert "grid-template-columns: repeat(auto-fit, minmax(10.5rem, 1fr));" in css
assert ".status-tile-topline" in css assert ".status-tile-topline" in css
@@ -34,6 +34,6 @@ def test_overview_action_callout_is_visually_secondary() -> None:
assert ".overview-action-copy" in css assert ".overview-action-copy" in css
assert ".overview-quick-actions" in css assert ".overview-quick-actions" in css
assert ".quick-action-button" in css assert ".quick-action-button" in css
assert "background: linear-gradient(135deg, rgba(15, 118, 110, 0.08), rgba(255, 255, 255, 0.82));" in css assert "background: linear-gradient(135deg, rgba(15, 118, 110, 0.08), color-mix(in srgb, var(--gi-surface) 82%, transparent));" in css
assert "border-left: 4px solid var(--accent);" in css assert "border-left: 4px solid var(--accent);" in css
assert "align-content: center;" in css assert "align-content: center;" in css
@@ -44,5 +44,5 @@ def test_data_workspace_density_css_contracts() -> None:
assert ".data-panel-list-block" in css assert ".data-panel-list-block" in css
assert ".data-section-label" in css assert ".data-section-label" in css
assert "grid-template-columns: repeat(auto-fit, minmax(10rem, 1fr));" in css assert "grid-template-columns: repeat(auto-fit, minmax(10rem, 1fr));" in css
assert "background: linear-gradient(180deg, #ffffff, #f7fbf8);" in css assert "background: linear-gradient(180deg, var(--gi-surface), var(--gi-brand-50));" in css
assert "border-left: 4px solid var(--accent);" in css assert "border-left: 4px solid var(--accent);" in css
@@ -41,7 +41,7 @@ def test_map_workspace_density_css_contracts() -> None:
assert ".map-inspection-surface" in css assert ".map-inspection-surface" in css
assert ".map-workspace-shell .map-toolbar" in css assert ".map-workspace-shell .map-toolbar" in css
assert "grid-template-columns: repeat(auto-fit, minmax(11rem, 1fr));" in css assert "grid-template-columns: repeat(auto-fit, minmax(11rem, 1fr));" in css
assert "background: linear-gradient(180deg, #ffffff, #f7fbf8);" in css assert "background: linear-gradient(180deg, var(--gi-surface), var(--gi-brand-50));" in css
assert "border-left: 4px solid var(--accent);" in css assert "border-left: 4px solid var(--accent);" in css
@@ -50,4 +50,4 @@ def test_quality_workspace_density_css_contracts() -> None:
assert ".quality-results-shell .quality-history-controls" in css assert ".quality-results-shell .quality-history-controls" in css
assert "grid-template-columns: repeat(auto-fit, minmax(8.25rem, 1fr));" in css assert "grid-template-columns: repeat(auto-fit, minmax(8.25rem, 1fr));" in css
assert "grid-template-columns: repeat(auto-fit, minmax(7.5rem, 1fr));" in css assert "grid-template-columns: repeat(auto-fit, minmax(7.5rem, 1fr));" in css
assert "background: linear-gradient(180deg, #ffffff, #f7fbf8);" in css assert "background: linear-gradient(180deg, var(--gi-surface), var(--gi-brand-50));" in css
@@ -57,7 +57,8 @@ def test_ai_lab_preserves_existing_detection_and_segmentation_controls() -> None
assert "onLoadResults" in segmentation assert "onLoadResults" in segmentation
assert "onRunQa" in segmentation assert "onRunQa" in segmentation
assert "selectedSegmentationModelConfigured" in segmentation assert "selectedSegmentationModelConfigured" in segmentation
assert "{segmentationItems.length} vlakken geladen" in segmentation assert "segmentationItems.length" in segmentation
assert "vlakken geladen" in segmentation
assert "Vergelijk met referentielaag" in segmentation assert "Vergelijk met referentielaag" in segmentation
@@ -13,14 +13,14 @@ def test_export_center_exposes_final_handoff_surfaces() -> None:
assert 'className="export-center"' in export_center assert 'className="export-center"' in export_center
assert 'className="export-center-shell"' in export_center assert 'className="export-center-shell"' in export_center
assert 'className="export-summary-surface"' in export_center assert 'className="export-summary-surface"' in export_center
assert 'aria-label="Export summary"' in export_center assert 'aria-label="Samenvatting van de downloads"' in export_center
assert 'className="export-handoff-surface"' in export_center assert 'className="export-handoff-surface"' in export_center
assert 'aria-label="Export handoff readiness"' in export_center assert 'aria-label="Gereedheid voor overdracht"' in export_center
assert 'className="export-actions-surface"' in export_center assert 'className="export-actions-surface"' in export_center
assert 'aria-label="Export artifact actions"' in export_center assert 'aria-label="Acties om resultaten te bewaren"' in export_center
assert 'className="export-state-stack"' in export_center assert 'className="export-state-stack"' in export_center
assert 'className="export-history-surface export-history-disclosure"' in export_center assert 'className="export-history-surface export-history-disclosure"' in export_center
assert 'aria-label="Export history"' in export_center assert 'aria-label="Downloadgeschiedenis"' in export_center
def test_provider_panel_exposes_final_system_surfaces() -> None: def test_provider_panel_exposes_final_system_surfaces() -> None:
@@ -77,4 +77,4 @@ def test_export_system_density_css_contracts() -> None:
assert ".provider-provenance-grid" in css assert ".provider-provenance-grid" in css
assert ".provider-provenance-card" in css assert ".provider-provenance-card" in css
assert "grid-template-columns: repeat(auto-fit, minmax(8rem, 1fr));" in css assert "grid-template-columns: repeat(auto-fit, minmax(8rem, 1fr));" in css
assert "background: linear-gradient(180deg, #ffffff, #f7fbf8);" in css assert "background: linear-gradient(180deg, var(--gi-surface), var(--gi-brand-50));" in css
Binary file not shown.

After

Width:  |  Height:  |  Size: 140 KiB