high priority medium complexity testing pending testing specialist Tier 4

Acceptance Criteria

Integration test suite runs successfully via flutter_test + integration_test package on both iOS simulator and Android emulator
Test scenario 1: app boots with NHF as active org, TerminologyAwareTextWidget renders NHF-specific label values for at least 3 distinct label keys
Test scenario 2: active organization is switched to Blindeforbundet, TerminologyAwareTextWidget re-renders and displays Blindeforbundet-specific label values within one pump cycle
Test scenario 3: WcagSemanticsLabelResolver Semantics node is verified to contain the Blindeforbundet-specific semantic label after org switch (using tester.getSemantics())
Test scenario 4: TerminologyAdminPreviewScreen displays correct resolved values for Blindeforbundet's map
Test scenario 5: TerminologyAdminPreviewScreen shows the correct missing entry count for each organization (NHF and Blindeforbundet have different missing counts in test fixtures)
Test fixtures use deterministic mock data — no real Supabase calls in integration tests
All tests pass in CI without flakiness across 3 consecutive runs
Test execution time is under 60 seconds for the full integration test suite

Technical Requirements

frameworks
Flutter
Riverpod
flutter_test
integration_test
apis
OrganizationLabelsNotifier (mocked)
TerminologyRepository (mocked)
LabelKeyRegistry (seeded with test fixtures)
data models
OrganizationLabelMap (NHF fixture)
OrganizationLabelMap (Blindeforbundet fixture)
LabelKeyRegistry (test seed)
performance requirements
Full integration test suite must complete in under 60 seconds
No real network calls — all providers overridden with ProviderScope overrides
security requirements
Test fixtures must not contain real PII or real organization data — use synthetic names and fake label values
ui components
TerminologyAwareTextWidget (under test)
WcagSemanticsLabelResolver (under test)
TerminologyAdminPreviewScreen (under test)

Execution Context

Execution Tier
Tier 4

Tier 4 - 323 tasks

Can start after Tier 3 completes

Implementation Notes

Structure the test file with a shared setUp() that creates the two org fixtures and wires the ProviderScope overrides — avoid copy-paste provider setup across test cases. Use tester.pumpAndSettle() after triggering the org switch to allow all async providers to resolve. For Semantics testing, enable the Semantics tree with SemanticsHandle handle = tester.ensureSemantics() at the top of the test and dispose at the end. The WcagSemanticsLabelResolver Semantics verification should use find.bySemanticsLabel() or tester.getSemantics(find.byType(WcagSemanticsLabelResolver)) — document the exact approach chosen in the test file's top comment.

If the integration_test package requires a main() entrypoint with IntegrationTestWidgetsFlutterBinding.ensureInitialized(), add it and document the run command in the project README.

Testing Requirements

Use the integration_test package for device/emulator-level tests and flutter_test for pump-based widget tests. Create two test fixture files: nhf_label_fixture.dart and blindeforbundet_label_fixture.dart, each with a complete OrganizationLabelMap. Use ProviderScope(overrides: [...]) to inject mocked repositories. Verify Semantics tree with tester.getSemantics() and SemanticsController.

Test the org-switch flow as a single sequential test (not isolated tests) to validate the reactive re-render chain. Include a separate test for the edge case where both orgs have identical label values to ensure no false positives in the missing-entry count.

Epic Risks (3)
high impact medium prob integration

WcagSemanticsLabelResolver's Semantics wrappers may conflict with Semantics nodes already defined by existing accessible widgets (e.g., accessible-bottom-navigation, activity-wizard-semantics), causing duplicate or contradictory screen reader announcements that fail WCAG 2.2 AA criteria.

Mitigation & Contingency

Mitigation: Audit all existing Semantics-annotated widgets in the accessibility feature before implementing WcagSemanticsLabelResolver. Define a clear hierarchy rule: WcagSemanticsLabelResolver always merges with, never replaces, existing Semantics nodes. Use Flutter's debugSemantics output in CI to detect conflicts automatically.

Contingency: If conflicts are discovered in testing, introduce a resolverMode parameter to WcagSemanticsLabelResolver allowing it to operate in 'override' or 'merge' mode per call site; coordinate with the Screen Reader Support feature team to align Semantics strategies.

medium impact medium prob technical

If TerminologyAwareTextWidget subscribes to the full terminology map provider rather than the per-key labelProvider family, a single label update will trigger a full widget-tree rebuild across all screens simultaneously, causing jank on devices used by older peer mentors.

Mitigation & Contingency

Mitigation: Implement TerminologyAwareTextWidget using ref.watch(labelProvider(key)) on the per-key family provider from TerminologyRiverpodProviders so that only widgets bound to the changed key rebuild. Verify with Flutter DevTools 'rebuild tracking' in widget tests.

Contingency: If full-map subscriptions slip through code review, add a Riverpod lint rule that flags direct organizationLabelsNotifierProvider subscriptions inside widget build methods and enforces the per-key family pattern.

medium impact low prob security

The TerminologyAdminPreviewScreen requires coordinator-level access, but if role checks rely solely on client-side guard logic without matching Supabase RLS policies, a peer mentor could potentially access the admin preview by manipulating navigation state.

Mitigation & Contingency

Mitigation: Protect the admin preview route with a server-validated role guard that re-fetches the user's role from Supabase on screen initialization, not just from local state. Add a Supabase RLS policy that restricts label map read access for the admin preview endpoint to coordinator and admin roles only.

Contingency: If unauthorized access is discovered in testing, immediately add a middleware role assertion that redirects non-coordinators to the no-access screen and logs the unauthorized navigation attempt for audit.