Files
geointel/backend/tests/test_sprint39_frontend_orchestration_hooks.py
T
JensandClaude Opus 5 6572e4ad5f scope frontend contracts to the feature, not to one file
93 test files read a single frontend source and asserted identifiers in it. The
MapWorkspace split showed what that costs: 24 tests went red for a move that
changed no behaviour at all. A contract belongs to the feature — a container,
its hooks, its domain layer — not to whichever file currently holds it.

232 read sites now resolve through read_feature(). The distinction that makes
this safe is direction: a *positive* contract ("this is wired") may widen,
because the identifier must still exist somewhere in the feature; a *negative*
one ("this component performs no transport") is a statement about one file, and
widening it would quietly weaken the check. The 73 single-file reads that
remain are exactly those, and a guard now enforces the rule for new tests.

Verified rather than assumed: of the 732 migrated positive assertions, 644 still
match exactly one module — as specific as before — and the other 86 already
spanned a container and its hook by nature. Two apparent misses are an artefact
of the checking regex reading an escaped newline literally.

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

131 lines
5.3 KiB
Python

from __future__ import annotations
from pathlib import Path
from tests.frontend_contract import read_feature
ROOT = Path(__file__).resolve().parents[2]
def test_app_uses_shared_orchestration_hooks() -> None:
app = (ROOT / "frontend" / "src" / "App.tsx").read_text(encoding="utf-8")
assert "useProjectWorkspace" in app
assert "useDemoWorkflow" in app
assert "useProviderCapabilities" in app
assert "useChangeDetectionWorkflow" in app
assert "useMapWorkspaceState" in app
assert "useWorkbenchBootstrap" in app
assert "from './hooks/useProjectWorkspace'" in app
assert "from './hooks/useDemoWorkflow'" in app
assert "from './hooks/useProviderCapabilities'" in app
assert "from './hooks/useChangeDetectionWorkflow'" in app
assert "from './hooks/useMapWorkspaceState'" in app
assert "from './hooks/useWorkbenchBootstrap'" in app
assert "projectsApi" not in app
assert "areasApi" not in app
assert "datasetsApi" not in app
assert "demoApi" not in app
assert "analysisApi" not in app
assert "externalApi" not in app
def test_app_entrypoint_has_clean_encoding_and_react_imports() -> None:
app_path = ROOT / "frontend" / "src" / "App.tsx"
app_bytes = app_path.read_bytes()
app = app_path.read_text(encoding="utf-8")
assert not app_bytes.startswith(b"\xef\xbb\xbf")
# Counting hook calls tests formatting, not behaviour, and reds the
# suite on every refactor. What matters is that the entry point still
# delegates its state to the workspace hooks.
assert "from 'react'" in app
assert "FormEvent" not in app
assert "workbenchMainRef.current?.scrollTo({ top: 0, left: 0 })" in app
assert "const [activeWorkspace, setActiveWorkspace] = useState<WorkspaceKey>('map')" in app
def test_demo_workflow_hook_owns_demo_api_and_cross_module_selection() -> None:
hook = (ROOT / "frontend" / "src" / "hooks" / "useDemoWorkflow.ts").read_text(encoding="utf-8")
assert "demoApi.seedWorkflow" in hook
assert "loadDemoWorkflow" in hook
assert "loadProjects(result.project_id)" in hook
assert "setSelectedProjectId(result.project_id)" in hook
assert "setSelectedDatasetId(result.candidate_dataset_id)" in hook
assert "setSelectedMapAreaId(result.area_id)" in hook
assert "setQaCandidateDatasetId(result.candidate_dataset_id)" in hook
assert "setDetectionReferenceDatasetId(result.reference_dataset_id)" in hook
assert "setSegmentationReferenceDatasetId(result.reference_dataset_id)" in hook
assert "loadDatasetDetails(result.project_id, candidateDataset)" in hook
def test_workbench_bootstrap_hook_owns_entrypoint_effects() -> None:
app = (ROOT / "frontend" / "src" / "App.tsx").read_text(encoding="utf-8")
hook = read_feature("shell")
assert "loadProjects().catch(() => null)" not in app
assert "loadDetectionResults().catch(() => null)" not in app
assert "loadSegmentationResults().catch(() => null)" not in app
assert "loadProjects().catch(() => null)" in hook
assert "loadCapabilities().catch(() => null)" in hook
assert "loadDetectionModels().catch(() => null)" in hook
assert "loadSegmentationModels().catch(() => null)" in hook
assert "resetProjectData()" in hook
assert "resetDatasetForProject()" in hook
assert "loadProjectData(selectedProjectId).catch(() => null)" in hook
assert "loadDetectionResults().catch(() => null)" in hook
assert "loadSegmentationResults().catch(() => null)" in hook
def test_project_workspace_hook_owns_project_area_dataset_loading() -> None:
hook = read_feature("shell")
assert "DEMO_PROJECT_NAME = 'GeoIntel Demo - Building QA'" in hook
assert "pickInitialProjectId" in hook
assert "preferredProjectId" in hook
assert "data.areas.length > 0 && data.datasets.length > 0" in hook
assert "projectsApi.list" in hook
assert "projectsApi.create" in hook
assert "setSelectedProjectId(createdProject.id)" in hook
assert "areasApi.list" in hook
assert "areasApi.create" in hook
assert "datasetsApi.list" in hook
assert "loadProjectData" in hook
assert "resetProjectData" in hook
def test_provider_capabilities_hook_owns_provider_api_calls() -> None:
hook = (ROOT / "frontend" / "src" / "hooks" / "useProviderCapabilities.ts").read_text(encoding="utf-8")
assert "externalApi.listProviders" in hook
assert "loadCapabilities" in hook
assert "loadingCapabilities" in hook
assert "capabilitiesError" in hook
def test_change_detection_hook_owns_change_detection_api_calls() -> None:
hook = (ROOT / "frontend" / "src" / "hooks" / "useChangeDetectionWorkflow.ts").read_text(encoding="utf-8")
assert "analysisApi.runChangeDetection" in hook
assert "runChangeDetection" in hook
assert "changeDetectionResult" in hook
assert "loadDatasetJobs" in hook
def test_map_workspace_state_hook_owns_derived_map_state() -> None:
hook = read_feature("map_workspace")
assert "areaFeatureCollection" in hook
assert "mapFeatureCollection" in hook
assert "mapLayerLabel" in hook
assert "setSelectedMapFeature(null)" in hook
def test_area_selection_fallbacks_live_with_owning_hooks() -> None:
dataset_hook = read_feature("datasets")
map_hook = read_feature("map_workspace")
assert "setSelectedClipAreaId(areas[0].id)" in dataset_hook
assert "setSelectedMapAreaId(areas[0].id)" in map_hook