Integration Test: Speech Adapter Lifecycle and Error Recovery
epic-structured-post-session-report-services-task-009 — Write integration tests for speech-to-text-adapter covering the full lifecycle: permission grant flow, start/stop recording, partial transcript streaming, locale switching, app-background session release, and error recovery for denied permissions and no-speech timeouts. Use flutter_test with mocked native speech API bridge to simulate platform responses.
Acceptance Criteria
Technical Requirements
Execution Context
Tier 1 - 540 tasks
Can start after Tier 0 completes
Implementation Notes
The key challenge in this test suite is correctly mocking the MethodChannel without a real device. Use the pattern: final log =
For locale switching, confirm the adapter's contract: does it emit a final partial transcript before restarting, or discard it? Document this behaviour explicitly in a test description string. Important user context: Blindeforbundet and HLF require speech-to-text for post-session report writing (not during sessions) — tests should reflect this: recording is user-initiated post-session, never auto-started.
Testing Requirements
Integration tests using flutter_test. Use TestWidgetsFlutterBinding and mock the native MethodChannel (e.g., 'com.app/speech') using TestDefaultBinaryMessengerBinding.instance.defaultBinaryMessenger.setMockMethodCallHandler() to intercept platform calls. Use fakeAsync() for timeout and streaming tests to avoid real delays. Use StreamController in the mock bridge to emit partial transcripts in sequence.
For lifecycle tests, call ServicesBinding.instance.handleAppLifecycleStateChanged(AppLifecycleState.paused) to simulate backgrounding. Verify state transitions using expectLater() on the adapter's state stream. All tests grouped by lifecycle phase: 'permissions', 'recording lifecycle', 'streaming', 'locale', 'background', 'error recovery'.
Flutter's speech_to_text package behaviour differs meaningfully between iOS and Android — microphone permission flows, locale availability, background audio session interference, and partial-result timing all vary. Inconsistent behaviour could make voice input unreliable for the primary audience (visually impaired peer mentors on iOS VoiceOver).
Mitigation & Contingency
Mitigation: Test speech-to-text-adapter on physical iOS and Android devices from the start, not just simulators. Write platform-specific test cases for permission flows and locale detection. Design the adapter's public interface to be platform-agnostic so that a native bridge could replace the package if needed.
Contingency: If speech_to_text proves unreliable on a platform, implement a native-speech-api-bridge (already identified in the component catalogue) as a drop-in replacement within the adapter, keeping the external interface unchanged so no UI code needs to change.
The coordinator task queue notification mechanism is not fully specified. If the queue system is owned by another team or uses an external service, way-forward-task-service may block on an undefined integration contract, delaying this epic.
Mitigation & Contingency
Mitigation: Define the task queue notification interface as an abstract Dart interface early in the epic. Implement a stub that writes a flag to the database so coordinator list queries can detect new tasks, deferring the real notification integration to a later epic.
Contingency: If the queue integration remains undefined at implementation time, ship way-forward-task-service with database persistence only and add a TODO-flagged notification hook. Coordinators will still see items on next page load; push notification delivery is deferred.