high priority medium complexity testing pending testing specialist Tier 5

Acceptance Criteria

Activity fetch test: verifies that only activities within the configured date window [now - lookback, now] are queried; activities outside the window are not passed to the rule engine
Rule engine — zero candidates: when rule engine returns empty list, dispatch is never called and no delivery record is written
Rule engine — multiple candidates: when rule engine returns N candidates, deduplication reduces to only non-previously-dispatched prompts; correct subset is passed to dispatch
Deduplication test: given a list where 2 of 5 candidates have existing delivery records, exactly 3 prompts are dispatched
Dispatch invocation count: mock verifies dispatchPrompt is called exactly once per non-deduplicated prompt
Delivery recording: after dispatch, recordDelivery is called with the correct promptId and userId for each dispatched prompt
Error path: if activity fetch throws, the scheduler catches the error, logs it, and does not invoke dispatch
All tests are hermetic — no network calls, no Supabase connections, no Flutter widget tree required
Test file achieves >= 90% line coverage of the Scheduler Service class as reported by flutter test --coverage

Technical Requirements

frameworks
Flutter
flutter_test
mockito
build_runner
data models
ScenarioPrompt
Activity
PromptDeliveryRecord
SchedulerConfig
performance requirements
Full unit test suite must complete in under 10 seconds
No async timeouts — use fake async or explicit Future completion
security requirements
Test data must not contain real user identifiers or personal data — use UUIDs like 'test-user-001'

Execution Context

Execution Tier
Tier 5

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.

Component
Scenario Prompt Scheduler Service
service high
Epic Risks (2)
high impact medium prob technical

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.

medium impact medium prob scope

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.