medium priority low complexity testing pending testing specialist Tier 2

Acceptance Criteria

flutter_test's SemanticsController (or AccessibilityGuideline checks) passes for RouteInputFieldsWidget with no violations
meetsGuideline(androidTapTargetGuideline) passes for all interactive elements (48dp tap targets)
meetsGuideline(iOSTapTargetGuideline) passes for all interactive elements
meetsGuideline(labeledTapTargetGuideline) passes — all tappable nodes have labels
meetsGuideline(textContrastGuideline) passes — all text nodes meet ≥4.5:1 contrast for normal text, ≥3:1 for large text
Semantic focus order traverses: origin label → origin field → destination label → privacy notice → destination field (logical top-to-bottom order)
VoiceOver/TalkBack simulation via Semantics tree confirms: origin field announced as 'From, text field, required'; destination field announced as 'Destination, optional, privacy-protected, text field'
Any violations found during audit are fixed in the generator (src code) before this task is closed
A compliance summary comment is added to the widget file header documenting WCAG 2.2 AA pass status and audit date
Both empty-state and error-state renders pass the accessibility audit

Technical Requirements

frameworks
Flutter
flutter_test
performance requirements
Audit tests run in <5 seconds on CI
security requirements
Audit covers error state to ensure error messages are accessible and do not leak sensitive content
ui components
RouteInputFieldsWidget (completed)
flutter_test AccessibilityGuideline matchers
SemanticsController

Execution Context

Execution Tier
Tier 2

Tier 2 - 518 tasks

Can start after Tier 1 completes

Implementation Notes

The flutter_test accessibility guidelines (AccessibilityGuideline) are the primary automated tool. Supplement with a manual checklist for VoiceOver (iOS) and TalkBack (Android) covering: (a) field announcement on focus, (b) error announcement on validation failure, (c) privacy notice reachability without activating the field. If textContrastGuideline fails for the privacy notice caption (likely due to muted secondary color), adjust the design token secondary color to meet the 4.5:1 threshold against the background — do not suppress the guideline check. For the compliance comment in the widget file, use the format: // WCAG 2.2 AA: Audited [DATE] — all four flutter_test guidelines pass in empty, error, and privacy-notice states.

Testing Requirements

Use flutter_test's expect(tester, meetsGuideline(...)) API with all four built-in guidelines: androidTapTargetGuideline, iOSTapTargetGuideline, labeledTapTargetGuideline, and textContrastGuideline. Test in three states: (1) default empty render; (2) origin field in error state (empty submit); (3) destination field with privacy notice visible. Additionally write a Semantics traversal test using tester.getSemantics(find.byType(RouteInputFieldsWidget)) to assert the label strings on each node.

All four guidelines must pass in all three states. Document any guideline that is intentionally skipped and justify why.

Component
Route Input Fields Widget
ui low
Epic Risks (3)
medium impact low prob technical

Triggering MileageCalculationService on every keystroke in the distance field could cause frame drops on lower-end Android devices if the widget rebuild chain is too broad. Jank during real-time calculation would degrade the peer-mentor experience, particularly for users with motor impairments who may type slowly and need immediate feedback.

Mitigation & Contingency

Mitigation: Keep the reimbursement calculation inside the RealtimeReimbursementDisplay widget subtree only, using a StatefulWidget with a local state variable rather than lifting state to the BLoC. This limits rebuilds to a single widget. Profile on a low-end device (Qualcomm Snapdragon 450 class) before code review.

Contingency: If profiling shows frame drops, debounce the onChanged callback by 50ms using a Timer before updating the local state, which remains imperceptible to the user while eliminating excessive rebuilds.

medium impact medium prob scope

The optional destination field requires balancing two competing requirements: WCAG 2.2 AA demands a clear label association for screen readers, while the privacy requirement means the label must communicate optionality and privacy sensitivity without exposing the user to undue pressure to fill it in. A poorly worded label could cause screen-reader users to misunderstand the field's optional nature or feel compelled to enter private location data.

Mitigation & Contingency

Mitigation: Draft label text and hint text with input from at least one screen-reader user during the accessibility review. Use Flutter's Semantics widget to provide a separate semantic label that is more descriptive than the visual placeholder. Test with TalkBack and VoiceOver before sign-off.

Contingency: If user testing reveals confusion, replace the inline hint with a tappable information icon that opens a brief explanation of why the field is optional and how the data is used, reducing cognitive load on the field label itself.

low impact medium prob integration

If OrgRateConfigRepository has not yet resolved the org rate when the form loads (e.g. slow network, first launch with empty cache), the reimbursement display cannot show a meaningful value. Showing '0' or an error state could confuse mentors and undermine trust in the feature.

Mitigation & Contingency

Mitigation: Display a loading skeleton in the reimbursement display widget until the rate is available. Once loaded, animate the value in. Show a subtle 'rate unavailable' message if the fetch times out, but allow form completion and submission (rate will be fetched server-side at submission time).

Contingency: If rate unavailability is frequent due to connectivity issues, store the last successfully fetched rate in SharedPreferences as an additional fallback so the widget can render a stale-but-indicative value with a caveat label.