critical priority high complexity testing pending testing specialist Tier 3

Acceptance Criteria

Test suite tagged 'accessibility_components' contains at least 18 test cases: 6 for ActivityWizardStepSemantics, 6 for AccessibleBottomNavigation, and 6 for AccessibleModalSheet
ActivityWizard — step announcement: advancing to a new step triggers a SemanticsAction or liveRegion update announcing the new step name and number (e.g., 'Step 2 of 5: Date'); verified via SemanticsController
ActivityWizard — focus placement: after step transition, semantic focus lands on the first interactive element of the new step, not on the step header or progress indicator
ActivityWizard — inline error reading: submitting a step with invalid data causes the error message to be announced via a liveRegion or assertive aria-live equivalent; error text is confirmed via semantics tree
AccessibleBottomNavigation — label correctness: each of the 5 tab items has a Semantics label matching its visible label text exactly (Home, Contacts, Add, Work, Notifications)
AccessibleBottomNavigation — selected state: the currently selected tab has SemanticsFlag.isSelected = true and all others have isSelected = false; verified after each of 5 tab switches
AccessibleBottomNavigation — tab-switch announcement: switching tabs triggers an announcement of the new tab name; verified via SemanticsController.announce or liveRegion
AccessibleModalSheet — focus trapping: while the modal is open, Tab/focus traversal cycles only within the modal's semantic subtree and does not reach elements behind the overlay
AccessibleModalSheet — trigger focus restoration: closing the modal restores semantic focus to the element that triggered the modal open action
AccessibleModalSheet — dialog role announcement: the modal's root Semantics node has SemanticsFlag.scopesRoute and SemanticsFlag.namesRoute set so VoiceOver/TalkBack announces it as a dialog
All tests pass meetsMobileAccessibilityGuideline() and meetsGuideline(textContrastGuideline) Flutter matchers
All tests are headless and executable in CI without a physical device

Technical Requirements

frameworks
Flutter
flutter_test
apis
Flutter SemanticsController
Flutter AccessibilityGuideline matchers (meetsMobileAccessibilityGuideline, meetsGuideline)
Flutter SemanticsFlag API
ActivityWizardStepSemantics (internal)
AccessibleBottomNavigation (internal)
AccessibleModalSheet (internal)
data models
ActivityWizard step model
BottomNavItem
ModalSheet trigger reference
performance requirements
Full test suite (18+ tests) must complete in under 3 minutes on a standard CI runner
Each test must call tester.pumpAndSettle() with a timeout no greater than 5 seconds
security requirements
Test fixtures must not use real user data — use named constants for all displayed text
No network calls in any test — all data providers must be mocked
ui components
ActivityWizardStepSemantics
AccessibleBottomNavigation
AccessibleModalSheet

Execution Context

Execution Tier
Tier 3

Tier 3 - 413 tasks

Can start after Tier 2 completes

Implementation Notes

The highest-risk area is the focus-trapping test for AccessibleModalSheet — Flutter's semantics tree does not natively enforce focus trapping in tests the way a browser does. The recommended approach is to collect all SemanticsNode IDs reachable via repeated SemanticsAction.moveFocusForward from within the modal and assert the set never contains a node whose ancestor is outside the modal's overlay entry. For liveRegion / announcement verification, Flutter's SemanticsController.announce is the correct API — but in tests you may need to spy on it by wrapping the SemanticsBinding. Use a TestWidgetsFlutterBinding.ensureInitialized() override with a custom SemanticsBinding to capture announcements.

For the ActivityWizard step announcement test, ensure the wizard step model is injectable (pass steps as a constructor parameter) so tests can drive step transitions without touching real activity data. The AccessibleBottomNavigation tests should use the real widget (not a mock) to catch regressions in the actual Semantics node setup — use a minimal Scaffold + BottomNavigation fixture rather than the full app.

Testing Requirements

Use flutter_test exclusively (not flutter_driver or integration_test package) to keep tests fast and headless. Enable semantics globally in each test with tester.ensureSemantics() and dispose the returned handle in tearDown. Use tester.getSemantics(find.byType(X)) to retrieve SemanticsData for assertion. For announcement tests, use a SemanticsController mock that records SemanticsAction.announce calls and verify the recorded announcements list.

For focus trapping tests, iterate through all reachable semantics nodes while the modal is open and assert that none are outside the modal's subtree. For tab-switch tests, programmatically call setState or tap the BottomNavItem and then assert SemanticsFlag.isSelected via tester.getSemantics(). Structure tests in three files: activity_wizard_semantics_test.dart, accessible_bottom_nav_test.dart, accessible_modal_sheet_test.dart. Share a common AccessibilityTestFixtures class for repeated widget pump setups.

All three files must carry the flutter_test tag 'accessibility_components' for selective CI execution.

Component
Activity Wizard Step Semantics
ui medium
Epic Risks (3)
high impact high prob integration

Flutter does not natively enforce a focus trap within a bottom sheet or modal dialog in the semantic tree — VoiceOver and TalkBack can navigate outside the sheet to background content. Implementing a reliable focus trap requires overriding the semantic tree, which may conflict with the existing modal helper infrastructure in the app and require changes to shared components beyond this feature's scope.

Mitigation & Contingency

Mitigation: Prototype the focus trap on the first modal sheet implementation before building the remaining sheets. Evaluate Flutter's ExcludeSemantics and BlockSemantics widgets as the trap mechanism, and coordinate with the team owning the shared modal helpers to agree on a non-breaking integration point before writing production code.

Contingency: If a complete semantic focus trap cannot be implemented without breaking existing modal patterns, implement a partial solution using FocusScope with autofocus on the modal's first element and a prominent 'Return to main content' semantic action, documenting the deviation from WCAG 2.4.3 with a scheduled remediation item.

high impact medium prob technical

The activity wizard uses BLoC state management and the UI rebuilds the entire step widget subtree on transition. If the semantic tree is traversed by VoiceOver before the build cycle settles, focus may land on a stale or partially rendered step, causing the wrong step label or progress value to be announced. This is particularly problematic for blind users who cannot visually verify the announcement against the screen.

Mitigation & Contingency

Mitigation: Coordinate ActivityWizardStepSemantics with FocusManagementService (from the core services epic) to delay focus placement until the post-build callback confirms the new step's semantic tree is complete. Write integration tests using the AccessibilityTestHarness that assert the full announcement sequence across all five wizard steps.

Contingency: If post-build focus delay is insufficient due to async BLoC emission timing, add an explicit semantic notification barrier in the wizard cubit that emits a 'step ready' event only after the new widget tree has been marked as built, decoupling the announcement trigger from the raw state transition.

medium impact medium prob scope

Automated WCAG contrast ratio checking on widget tree snapshots may produce false positives for gradient backgrounds, dark-mode overrides, or design token overrides that are resolved at runtime but appear as unresolvable colours at static analysis time. Excessive false positives would erode team trust in the CI gate, leading to suppression rules that also mask real violations.

Mitigation & Contingency

Mitigation: Scope the WCAGComplianceChecker to check only solid-colour backgrounds in the first iteration, explicitly excluding gradients from contrast checks with documented rationale. Design the check output to distinguish 'undetermined' (gradient/unknown) from 'fail' (solid colour below threshold) so the team can take targeted action on genuine failures only.

Contingency: If false positive rates exceed 20% of reported violations during initial CI runs, switch the CI gate from a hard build failure to a warning annotation on the pull request, combined with a mandatory manual review step, until the checker's rule set has been tuned to match actual design token values.