medium priority low complexity testing pending testing specialist Tier 2

Acceptance Criteria

Test file exists at test/services/way_forward_task_service_test.dart
Successful creation test: given a report with 3 way-forward items, service creates exactly 3 coordinator tasks and emits 3 task queue signals
Idempotency test: calling service twice with the same report_id returns WayForwardTaskCreationResult.alreadyExisted and does NOT call repository insert again
Repository failure rollback test: when repository throws on the 2nd of 3 items, no tasks are persisted and task queue receives no signals
Task queue signal test: verify task queue mock receives exactly one signal per created task, in order
Due date calculation test: given submission date 2026-01-10 and org follow-up offset 7 days, resulting task due_date is 2026-01-17
Due date edge case test: due date calculation handles month-end rollover correctly (e.g., Jan 31 + 7 days = Feb 7)
Coordinator assignment test: when report has no coordinator_id, org default coordinator is assigned to tasks
Coordinator assignment test: when report has a coordinator_id, that coordinator is assigned (not org default)
Line coverage ≥ 90% for way_forward_task_service.dart

Technical Requirements

frameworks
Flutter
flutter_test
mockito
apis
IWayForwardItemRepository (mock)
ITaskQueue (mock)
data models
WayForwardItem
CoordinatorTask
Report
WayForwardTaskCreationResult
performance requirements
All unit tests complete in under 2 seconds with no real async delays
security requirements
Test org IDs and coordinator IDs must be synthetic — no real user data

Execution Context

Execution Tier
Tier 2

Tier 2 - 518 tasks

Can start after Tier 1 completes

Implementation Notes

Before writing tests, confirm WayForwardTaskService exposes its dependencies (repository, task queue, clock) via constructor injection — if not, refactor before writing tests. For the rollback test, if Dart lacks built-in transaction scope, simulate rollback via a collected list: service accumulates created tasks in a local list and only calls repository.insertBatch() after all items are validated — test this by verifying insertBatch is called once with all items or not at all. The idempotency test should assert the exact WayForwardTaskCreationResult.alreadyExisted variant is returned (use expect with isA() or pattern matching on sealed class). Define a buildReport({String?

coordinatorId, List items}) factory in test/helpers/ to reduce boilerplate across tests.

Testing Requirements

Pure unit tests with flutter_test and mockito. Mock IWayForwardItemRepository and ITaskQueue using @GenerateMocks. For rollback test, use when().thenThrow() on the repository mock for the second invocation using mockito's answer sequencing (thenAnswer chained calls). Verify task queue signal count with verify(mockQueue.signal(any)).called(N).

Due date calculation tests should be extracted into a separate group() block that tests the pure calculation function directly if it is extracted. Use fake DateTime via a Clock abstraction — do not rely on DateTime.now() in tests. Run flutter test --coverage to confirm ≥ 90% line coverage.

Component
Way Forward Task Service
service medium
Epic Risks (2)
medium impact high prob technical

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.

medium impact medium prob dependency

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.