high priority medium complexity testing pending testing specialist Tier 6

Acceptance Criteria

All interactive controls (buttons, text fields, type selectors, receipt capture trigger) have non-empty Semantics labels that describe the purpose of the control, not its visual appearance
Focus traversal order in each step follows a logical top-to-bottom, left-to-right sequence matching visual reading order
All text elements achieve at minimum a 4.5:1 contrast ratio against their background; large text (18 sp+) achieves 3:1
All interactive touch targets are at minimum 44×44 dp (WCAG 2.2 SC 2.5.8 target size minimum)
Error state announcements are delivered via a live-region Semantics node so screen readers announce errors without requiring focus change
Status changes (step advance, submission loading, submission success) are announced via SemanticsService.announce()
No success criterion relies on colour as the sole means of conveying information (icons or text labels accompany all colour-coded states)
The screen passes flutter_test Semantics tree assertions for all steps with no unchecked warnings
A written audit report is produced listing each WCAG 2.2 AA success criterion tested, result (pass/fail/not applicable), and remediation applied or justification for any accepted failure
Zero unresolved failures remain after remediation; any accepted deviations are documented with WCAG exception clause cited

Technical Requirements

frameworks
Flutter
flutter_test
Dart
apis
Flutter Semantics API
SemanticsService.announce()
flutter_test SemanticsController
VoiceOver (iOS manual verification)
Accessibility Inspector (Xcode)
data models
WCAG2.2AAAuditReport (structured document)
SemanticsNode tree snapshot
performance requirements
Accessibility tree must not introduce measurable frame-time overhead (< 1 ms per frame for semantics updates)
security requirements
Audit tooling must not transmit screen content or Semantics data to external services
Screen content shown during manual VoiceOver testing must use synthetic/anonymised test data — no real personal data
ui components
All widgets on the expense registration screen across all steps

Execution Context

Execution Tier
Tier 6

Tier 6 - 158 tasks

Can start after Tier 5 completes

Implementation Notes

Structure the audit in two passes: (1) automated pass using flutter_test Semantics assertions — run these as a dedicated test file `expense_registration_screen_a11y_test.dart`; (2) manual pass on device with VoiceOver. For contrast ratio checking, write a utility `contrast_check.dart` that imports AppColors design tokens and computes WCAG contrast ratios — this becomes a regression guard for future colour changes. Common issues to look for in this codebase: icon-only buttons without Semantics.label; custom gesture detectors without Semantics.onTap; TextField errorText that is visually shown but not announced to screen readers (set errorText on InputDecoration rather than a separate Text widget to get automatic announcement); step progress indicator with no semantic label. For any control that is visually obvious but lacks a programmatic label, add ExcludeSemantics only if the information is redundant — document the decision.

The audit report should be committed as `docs/a11y/expense-registration-screen-wcag22-audit.md`.

Testing Requirements

Automated: flutter_test with tester.getSemantics() assertions on every interactive widget in every step — verify label, hint, isButton, isTextField, isEnabled, isFocusable, liveRegion flags. Contrast ratio check: extract design token color values and calculate WCAG contrast ratios programmatically for all text/background combinations used in the screen (can be a Dart script). Touch target test: retrieve render box sizes for all tappable widgets and assert >= 44×44 dp. Manual: run through all steps on a physical iOS device with VoiceOver enabled and confirm all interactive elements are announced correctly and focus order is logical.

Use Xcode Accessibility Inspector to capture the final Semantics tree. Document every tested criterion in the audit report template.

Component
Expense Registration Screen
ui high
Epic Risks (3)
medium impact medium prob dependency

The image_picker Flutter plugin requires platform-specific permissions (NSPhotoLibraryUsageDescription, camera permission) and behaves differently across iOS and Android versions. Permission denial or plugin misconfiguration can silently prevent receipt attachment.

Mitigation & Contingency

Mitigation: Configure all required permission strings in Info.plist and AndroidManifest.xml during initial plugin setup. Use the permission_handler package to check and request permissions before launching the picker, with clear user-facing explanations. Test on both platforms across at least two OS versions.

Contingency: If image_picker proves unreliable on a specific platform version, fall back to file_picker as an alternative that uses the OS document picker interface, which requires fewer permissions on some Android versions.

high impact medium prob technical

The expense form BLoC manages interconnected state across expense type selection, field visibility, receipt requirement, threshold evaluation, and submission flow. Incorrect state transitions can cause UI inconsistencies such as required receipt indicator not updating after amount change, or form appearing valid when mutual exclusion is violated.

Mitigation & Contingency

Mitigation: Model BLoC states as sealed classes with exhaustive pattern matching. Write state transition unit tests covering every combination of: type selection change, amount field change above/below threshold, receipt attachment/removal, and offline mode toggle. Use bloc_test for comprehensive state sequence assertions.

Contingency: If BLoC complexity becomes unmanageable, split into two BLoCs — one for type selection/exclusion state and one for field values/submission — coordinating via a parent provider, accepting the small overhead of inter-BLoC communication.

high impact medium prob technical

The expense type selector must enforce mutual exclusion visually by disabling options and showing conflict tooltips, while remaining fully accessible to screen reader users who cannot perceive visual disable states. Incorrect semantics labelling will fail WCAG 2.2 AA requirements critical for Blindeforbundet and HLF users.

Mitigation & Contingency

Mitigation: Use Flutter Semantics widgets to explicitly set disabled state and provide conflict explanations as semanticLabel strings on disabled options. Run accessibility audits with TalkBack and VoiceOver during widget development, not post-completion. Reference the project's accessibility test harness for required test coverage.

Contingency: If custom widget accessibility is difficult to certify, implement the selector as a standard Flutter Radio/Checkbox group with built-in accessibility semantics and an explanatory Text widget below each conflicting option, sacrificing visual elegance for guaranteed WCAG compliance.