high priority low complexity testing pending testing specialist Tier 3

Acceptance Criteria

A widget test simulates an organization switch by overriding the active organization provider and pumping the widget — the rendered text updates to reflect the new org's terminology
A widget test simulates a terminology sync update (label map contents change for the same org) and asserts the widget re-renders with updated text
Tests confirm that no `setState`, `invalidate`, or `refresh` calls are needed by the caller — reactivity is internal to the widget
A test verifies that switching from org A (key resolved) to org B (key missing) triggers the fallback rendering path correctly
A test verifies that switching from org A (key missing, showing fallback) to org B (key resolved) correctly shows the resolved string
All widget tests run in under 2 seconds total using flutter_test without a device or emulator
Tests are isolated — no shared mutable state between test cases (each test creates its own ProviderContainer or ProviderScope override)
Test file is co-located with the widget file or in the corresponding test/ directory with a matching name

Technical Requirements

frameworks
Flutter
Riverpod
flutter_test
data models
OrganizationLabelMap
OrganizationId
performance requirements
Each test case must complete within 500ms — use `tester.pump()` not `tester.pumpAndSettle()` where possible to avoid waiting on animations
ui components
TerminologyAwareTextWidget (under test)
ProviderScope with overrides (test harness)

Execution Context

Execution Tier
Tier 3

Tier 3 - 413 tasks

Can start after Tier 2 completes

Implementation Notes

Use Riverpod's `ProviderScope` with `overrides` parameter in `tester.pumpWidget(ProviderScope(overrides: [...], child: TerminologyAwareTextWidget(...)))`. To simulate state changes, use a `StateNotifierProvider` override with a mutable notifier, call `container.read(provider.notifier).setLabelMap(newMap)`, then call `await tester.pump()`. Verify with `expect(find.text('expected string'), findsOneWidget)`. For org switching, override the active org provider, not just the label map, to also test that the org-change path triggers a label map reload.

If the label map provider derives from the active org provider, switching the org provider should cascade — test this cascade explicitly. Avoid `tester.pumpAndSettle()` unless animations are involved, as it can mask timing issues.

Testing Requirements

All tests are widget tests using flutter_test and Riverpod's ProviderScope override mechanism. Test scenarios: (1) Initial render with org A label map — assert correct resolved text. (2) Mutate provider state to org B label map — call `tester.pump()` — assert text updates. (3) Update label map values for the same org — assert text updates.

(4) Org switch from resolved to missing key — assert fallback renders. (5) Org switch from missing key to resolved — assert resolved text renders. Use `StateProvider` or `StateNotifierProvider` overrides to inject controlled label maps. Do not use real Supabase connections in these tests — all data is inline.

Add a group('TerminologyAwareTextWidget reactive rebuild') block to keep the test suite organized.

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.