high priority medium complexity testing pending testing specialist Tier 1

Acceptance Criteria

Test file exists at test/accessibility/semantics_service_facade_test.dart
All tests pass with flutter test — zero failures, zero skipped
Queuing test: 3 polite announcements added, verify they are announced in FIFO order
Priority test: assertive announcement inserted mid-queue is announced before remaining polite items
announceNow test: clears all pending items and announces immediately
clearQueue test: pending items are removed and no further announcements are made
Locale test: announcement with explicit Locale('nb') passes that locale to the underlying service
Locale fallback test: announcement without locale uses device locale
Dispose test: after dispose(), calling announce() does not throw and does not announce
Mock injection test: MockAnnouncementService substituted via Riverpod.overrideWithValue() is used by a consumer widget
Queue delay test: verify configured delay (e.g. 200ms) is observed between consecutive announcements using fake async
Test coverage for the facade class is at or above 85% lines and branches

Technical Requirements

frameworks
Flutter
Riverpod
flutter_test
apis
SemanticsService.announce
data models
AnnouncementPriority
AnnouncementItem
performance requirements
All tests complete in under 5 seconds total using fakeAsync where timers are involved
security requirements
Test announcement strings must not contain real PII — use placeholder values like 'test message'

Execution Context

Execution Tier
Tier 1

Tier 1 - 540 tasks

Can start after Tier 0 completes

Implementation Notes

The primary challenge is testing timer-based queue processing without real wall-clock delays. Use fakeAsync() and tick/pump to advance fake time. For SemanticsService.announce, it is a static call that ultimately goes to a platform channel — in unit tests this will throw unless you set up a mock MethodChannel.

The preferred approach is to use the abstract interface (AnnouncementService) and a FakeAnnouncementService that never calls the real SemanticsService. Only test the concrete FlutterAnnouncementService's interaction with the platform if you set up a TestDefaultBinaryMessenger mock for the semantics channel. Separate these concerns: pure logic tests (queuing, priority, locale) use FakeAnnouncementService; platform integration tests are marked @Tags(['integration']) and run separately.

Testing Requirements

Use flutter_test exclusively. Use fakeAsync + pump/pumpAndSettle for timer-based tests. Create a FakeAnnouncementService that implements AnnouncementService and records all calls to a List for verification. For Riverpod integration tests, use ProviderContainer with overrides.

Structure tests in clearly named groups: 'queuing behavior', 'priority handling', 'locale handling', 'lifecycle (dispose)', 'riverpod integration'. Each group should have 3-5 focused test cases.

Component
Semantics Service Facade
infrastructure medium
Epic Risks (2)
high impact medium prob technical

Flutter's SemanticsService behaves differently between iOS (VoiceOver) and Android (TalkBack) in edge cases — e.g., announcement queuing, focus-gain timing, and attribute support. If the facade does not correctly abstract these differences, announcements may be silent or misfired on one platform, causing regression on the other platform to go unnoticed until device testing.

Mitigation & Contingency

Mitigation: Write platform-divergence unit tests early using SemanticsServiceFacade mocks. Validate announcement delivery on a physical iPhone (VoiceOver) and Android device (TalkBack) at the end of each sprint. Document known platform differences in the facade's inline API comments.

Contingency: If a platform difference cannot be abstracted cleanly, expose a platform-specific override path in the facade and implement targeted workarounds per platform, accepting the added complexity in exchange for correct behaviour.

medium impact medium prob scope

Accessibility preferences stored in local storage may need new fields as higher-tier epics are implemented (e.g., announcement verbosity, sensitive-field guard toggle). Schema changes to an already-persisted store risk data migration failures or silent defaults on existing installs, breaking user preferences.

Mitigation & Contingency

Mitigation: Design the AccessibilitySettingsRepository with a versioned JSON schema from the start, using merge-with-defaults on read so new fields fall back gracefully. Define the full expected field list upfront based on all downstream epic requirements before writing the first record.

Contingency: If migration fails on a live install, fall back to full reset-to-defaults with a one-time in-app notification informing the user that accessibility preferences have been reset and inviting them to reconfigure.