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
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:
@@ -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:
|
||||||
|
|||||||
@@ -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 |
Reference in New Issue
Block a user