critical priority medium complexity testing pending testing specialist Tier 2

Acceptance Criteria

AccessibilityAuditRunner.runTouchTargetAudit() walks the full semantics tree and inspects every SemanticsNode that has at least one of: SemanticsFlag.isButton, SemanticsFlag.isTextField, SemanticsFlag.isLink, SemanticsFlag.isCheckBox, SemanticsFlag.isRadioButton, SemanticsFlag.isSlider
Each qualifying node's rect (SemanticsNode.rect) is checked: width >= 44.0 and height >= 44.0 logical pixels; any node failing either dimension is recorded as a TouchTargetViolation
TouchTargetViolation records include: routeName, semanticsNodeId, semanticsLabel, actualWidth, actualHeight, requiredMinimum (44.0), and widgetPath (ancestor chain for developer debugging)
Nodes that are invisible (SemanticsNode.isInvisibleToUser == true) or explicitly excluded via a SemanticsExcludeSemantics widget are skipped
The audit runs against all screens in the key flows: activity wizard (all steps), contact list, contact detail, settings, bottom navigation tabs, and notification list
A screen with all 44dp-compliant targets produces zero violations
A deliberately undersized button (e.g., 32×32) is correctly detected and recorded
The audit produces a per-screen summary (screenName, totalInteractiveNodes, violationCount) in addition to the individual violation list

Technical Requirements

frameworks
Flutter
flutter_test
apis
SemanticsController
SemanticsNode.rect
SemanticsNode.getSemanticsData
SemanticsFlag
WidgetTester.semantics
data models
TouchTargetViolation
TouchTargetAuditScreenSummary
AccessibilityAuditResult
performance requirements
Full touch target audit across all key flows must complete within 20 seconds
Tree walking must be non-destructive and not trigger widget rebuilds
security requirements
No widget content or user data from semantics labels should be logged to external systems
ui components
AppButton
AppTextField
BottomNavigationBar
ContactCard
ActivityTypeCard
NotificationItem

Execution Context

Execution Tier
Tier 2

Tier 2 - 518 tasks

Can start after Tier 1 completes

Implementation Notes

Start from the root SemanticsNode returned by WidgetTester.semantics.find(find.byType(MaterialApp)) and do a depth-first walk. Filter nodes by checking node.getSemanticsData().hasFlag(SemanticsFlag.isButton) etc. Use node.rect for the actual bounding rect in logical pixels — this already accounts for padding added by InkWell/GestureDetector. Do not use node.transform unless you need screen coordinates; logical pixel rect is sufficient for the 44dp check.

The design token system should define sizing.minTouchTarget = 44.0 — reference this constant in the assertion rather than hardcoding 44.0. This requirement is directly tied to WCAG 2.5.8 (Target Size Minimum, AA) and is critical for NHF users with motor impairments and elderly users across all three organizations.

Testing Requirements

Unit tests: verify TouchTargetViolation serialization; verify the 44dp comparison logic handles edge cases (exactly 44.0 passes, 43.9 fails, 0.0 fails). Integration tests: pump a widget tree containing both compliant (48×48) and non-compliant (32×32) interactive elements, run the audit, assert exactly the non-compliant elements appear in violations. Integration test using the real AppButton widget: confirm it passes (AppButton should be sized to design token sizing.minTouchTarget = 44). Coverage target: 95% of touch-target walking logic.

Component
Accessibility Audit Runner
infrastructure medium
Epic Risks (2)
high impact medium prob dependency

Flutter's SemanticsController used in integration tests is an internal or semi-internal API that can break between Flutter stable releases. If the audit runner relies heavily on undocumented semantics tree traversal, a Flutter upgrade could silently disable the audit checks without a build failure, creating false confidence.

Mitigation & Contingency

Mitigation: Use only the public flutter_test accessibility APIs (meetsGuideline, SemanticsController.ensureSemantics) and wrap all SemanticsController calls in a versioned helper class with explicit assertions that the expected semantics tree shape is still available. Pin the Flutter SDK range in pubspec.yaml.

Contingency: If SemanticsController APIs break on a Flutter upgrade, fall back to widget-level golden tests that include the semantics tree snapshot, combined with manual Switch Access and VoiceOver QA checklists executed before each release.

low impact medium prob resource

Flutter integration tests that simulate Switch Access traversal on multiple screens can be slow (30–120 seconds per test flow), which may make the audit runner impractical to run on every CI commit if the test suite already has long run times.

Mitigation & Contingency

Mitigation: Scope the audit runner to a dedicated integration test target that runs on pull requests targeting main and on nightly builds, not on every push. Parallelise test shards in CI to keep wall-clock time acceptable. Profile audit run times during development and trim any flows that duplicate coverage.

Contingency: If CI run times exceed acceptable thresholds, split the audit runner into a fast smoke suite (touch targets and semantic labels only, runs on every PR) and a thorough traversal suite (Switch Access simulation, runs nightly), with the nightly failure blocking the release branch rather than every PR.