Unit tests for ScenarioRuleEngine evaluate() algorithm
epic-scenario-based-follow-up-prompts-core-logic-task-009 — Write comprehensive unit tests for the ScenarioRuleEngine covering: exact contact type match, wildcard contact type, single and combined wellbeing flag conditions, duration boundary values (inclusive/exclusive edges), delay window eligibility including cooldown guard, rules with no matching criteria (should not trigger), and empty rule set. Target 100% branch coverage on the evaluate() method.
Acceptance Criteria
Technical Requirements
Execution Context
Tier 4 - 323 tasks
Can start after Tier 3 completes
Implementation Notes
Structure the test file as: (1) imports and fixture declarations at the top, (2) setUp() building a fresh ScenarioRuleEngine with mock dependencies for each test, (3) test groups in dependency order matching the condition evaluation chain. For boundary value testing, consider a parameterized helper: void runBoundaryTest(int duration, int min, int max, bool expectMatch) — this prevents copy-paste drift when the boundary logic changes. Extract ActivityMetadataBuilder and ScenarioRuleBuilder factory helpers into test_helpers/scenario_fixtures.dart using the builder pattern (return a base object and allow named parameter overrides) so individual tests only specify the fields relevant to their assertion. Document in a top-of-file comment which tasks are under test and what the coverage target is.
If Mockito is not already a dev dependency, prefer hand-written test doubles over adding a new package dependency — the interfaces are simple enough.
Testing Requirements
This task IS the testing task. Organize tests using flutter_test's group() and test() functions. Use a TestPromptHistoryRepository (hand-written test double implementing PromptHistoryRepository) that returns configurable last-prompt timestamps. Use a TestClock (hand-written or Mockito mock) injected into ScenarioRuleEngine for deterministic time control.
Apply table-driven tests using a List of test cases for boundary value scenarios to maximize coverage with minimal boilerplate. Include a 'golden path' integration-style test at the bottom of the file that chains task-005 evaluate() and task-006 getPrioritizedMatch() together on a realistic scenario pulled from the HLF peer mentor follow-up use case described in the requirements documentation.
The Rule Engine must support a flexible JSON rule schema that can express compound conditions (e.g., contact_type AND wellbeing_flag AND delay_days). Underestimating schema expressiveness may require breaking changes to the rule format after coordinators have already configured rules.
Mitigation & Contingency
Mitigation: Define and freeze the rule JSON schema (trigger_type enum, metadata_conditions structure, delay logic) before any implementation begins; validate schema against all known HLF scenarios documented in the feature spec.
Contingency: If schema changes are needed after deployment, implement a schema version field and a migration utility that upgrades stored rules to the new format without coordinator intervention.
Deep-link navigation to the activity wizard with pre-filled arguments may fail if the user's session has expired or if the wizard route is not yet mounted in the navigator stack, causing unhandled navigation exceptions.
Mitigation & Contingency
Mitigation: Implement session state check before navigation; if session is expired, redirect to biometric/login screen and store the pending deep-link URI for post-auth redirect using go_router's redirect mechanism.
Contingency: If post-auth redirect proves unreliable, fall back to navigating to the home screen with a visible action banner that re-triggers the wizard with pre-filled arguments.