Unit test Scheduler Service pipeline stages
epic-scenario-based-follow-up-prompts-scheduler-and-ui-task-016 — Write unit tests for the Scenario Prompt Scheduler Service covering: activity fetch with date window filter, rule engine integration returning zero and multiple candidates, deduplication correctly filtering previously dispatched prompts, dispatch invocation count, and delivery recording. Mock all external dependencies with Mockito.
Acceptance Criteria
Technical Requirements
Execution Context
Tier 5 - 253 tasks
Can start after Tier 4 completes
Implementation Notes
The Scheduler Service should be designed for testability: constructor-inject all dependencies (activity repository, rule engine, delivery repository, dispatch service) as abstract interfaces. This makes Mockito mocking trivial. Use @GenerateMocks([ActivityRepository, ScenarioRuleEngine, DeliveryRepository, DispatchService]) at the top of the test file and run build_runner once. For the date window filter test, inject a clock abstraction (or DateTime factory function) so tests can control 'now' without time-dependent flakiness.
Structure each test as Arrange → Act → Assert. For the deduplication test, seed the delivery repository mock to return specific promptIds as already-delivered, then assert the filtered list length. Use captureAny() with verify() to assert the exact arguments passed to dispatch and recordDelivery. Avoid testing private methods directly — test behavior through the public runScheduler() entry point.
Testing Requirements
Pure Dart unit tests using flutter_test and mockito. Generate mocks with @GenerateMocks annotation and build_runner. Test structure: one describe-equivalent group per pipeline stage (fetch, rule engine, deduplication, dispatch, recording). Use fake_async package if scheduler relies on timers.
Each test must be independent — setUp creates fresh mock instances. Verify mock interactions with verify() and verifyNever(). Run with: flutter test test/services/scenario_prompt_scheduler_test.dart --coverage. Coverage report must show >= 90% for the scheduler service file.
Do not use integration_test package for these tests.
If the scheduler runs concurrently (e.g., two overlapping cron invocations due to edge function retry), duplicate prompts could be dispatched before the first run's history records are committed, breaking the deduplication guarantee.
Mitigation & Contingency
Mitigation: Use a Postgres advisory lock or unique constraint on (user_id, scenario_id, activity_ref) in the prompt history table to make concurrent writes idempotent; design the scheduler to check history inside a transaction.
Contingency: If concurrency issues persist in production, add a distributed lock via Supabase Edge Function concurrency limit (max_instances=1) for the evaluation function as a hard guard.
Coordinators may find scenario configuration unclear if trigger conditions are expressed as raw JSON or technical terminology, leading to misconfiguration and irrelevant prompts being sent to peer mentors.
Mitigation & Contingency
Mitigation: Design the ScenarioConfigurationScreen to display human-readable descriptions of each template's trigger condition (e.g., 'Send 3 days after first contact if wellbeing concern was flagged') rather than raw rule properties; validate with an HLF coordinator in a design review before implementation.
Contingency: If coordinators still misconfigure rules after launch, add a preview mode that shows a simulated prompt based on a test activity before the rule is enabled.