Write Unit Tests for Report Schema Service
epic-structured-post-session-report-services-task-007 — Write comprehensive unit tests for report-schema-service covering cache-hit, cache-miss, TTL expiry, schema parse errors, and multi-org isolation scenarios. Mock org-field-config-loader and report-schema-cache dependencies. Achieve 90%+ line coverage with flutter_test and mockito.
Acceptance Criteria
Technical Requirements
Execution Context
Tier 2 - 518 tasks
Can start after Tier 1 completes
Implementation Notes
If ReportSchemaService doesn't already accept a clock parameter for TTL calculations, add a ClockProvider abstraction (a simple DateTime Function() typedef) before writing tests — this avoids flaky time-dependent tests. Use mockito's when().thenAnswer() for async mocks returning Futures. For the background refresh test, use a Completer to capture whether the async loader was called after the initial return. Ensure that test helper factories (e.g., buildMockSchema({version: '1.0', orgId: 'org-a'})) are defined in test/helpers/ to keep test bodies readable.
Do not test private methods directly — test through the public API and rely on coverage to validate internals.
Testing Requirements
Pure unit tests using flutter_test and mockito. Use setUp() to create fresh mock instances before each test to prevent state leakage. Use verify() and verifyNever() from mockito to assert loader call counts. Use fake DateTime injection (pass clock as a parameter or use a Clock abstraction) to control TTL expiry without real time.sleep().
Run flutter test --coverage and verify lcov report shows ≥ 90% line coverage for report_schema_service.dart specifically. Group tests by scenario using group() blocks: 'cache hit', 'cache miss', 'TTL expiry', 'parse errors', 'multi-org isolation'.
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.