Unit tests for AssignmentContactTrackingRepository
epic-assignment-follow-up-reminders-foundation-task-010 — Write unit tests for AssignmentContactTrackingRepository covering: update last_contact_date, fetch overdue assignments with various threshold values, empty result when no assignments are overdue, org scoping enforcement, and index-backed query efficiency. Include edge case where last_contact_date is null (never contacted).
Acceptance Criteria
Technical Requirements
Execution Context
Tier 2 - 518 tasks
Can start after Tier 1 completes
Implementation Notes
The medium complexity rating comes from the threshold date calculation. The repository computes a cutoff DateTime as DateTime.now().subtract(Duration(days: thresholdDays)) and passes it to the Supabase query as a filter. To make this testable, inject a Clock or DateTimeProvider into the repository constructor (default: () => DateTime.now()) so tests can pass a fixed clock. The null last_contact_date case maps to a SQL OR condition: last_contact_date IS NULL OR last_contact_date < cutoff.
Ensure the repository implementation covers both branches and the test mocks both scenarios. For the boundary case, decide and document whether the threshold is strict (lt) or inclusive (lte) — this affects reminder frequency and should match product requirements from the likeperson.md spec (Blindeforbundet: 10-day automatic reminder).
Testing Requirements
Unit tests with flutter_test and mocktail. The null last_contact_date edge case is the most important test in this file — it encodes a product decision (never-contacted = always overdue) that must be explicitly tested and documented. Use a helper buildMockAssignment({DateTime? lastContactDate}) factory to reduce boilerplate across test cases.
For threshold boundary testing, use a fixed 'now' via dependency injection or a clock abstraction to make cutoff calculations deterministic. Aim for full branch coverage including null check, empty result, and exception paths.
Adding last_contact_date to the assignments table may conflict with existing RLS policies or trigger-based logic that monitors the assignments table. If the migration is not carefully reviewed, existing assignment management features could break in production.
Mitigation & Contingency
Mitigation: Review all existing triggers, policies, and foreign key constraints on the assignments table before writing the migration. Run the migration against a staging Supabase instance with production-like data and execute the full existing test suite before merging.
Contingency: Roll back the migration using Supabase's versioned migration history. Apply the schema change as an additive-only migration (nullable column with default) to ensure zero downtime and reversibility.
The PushNotificationService wraps an existing FCM integration whose internal API contract may have changed or may not expose the payload formatting required for deep-link CTAs. Misalignment discovered late delays the dispatch service epic.
Mitigation & Contingency
Mitigation: Before implementing the wrapper, read the existing push notification integration code and confirm the method signatures, payload structure, and token management model. Agree on a stable interface contract in a shared Dart abstract class.
Contingency: If the existing service is incompatible, implement a thin adapter layer that translates reminder payloads to the existing service's format, isolating the reminder feature from upstream changes.
Incorrect RLS policies on notification_log could allow coordinators to read reminder records belonging to peer mentors in other chapters, exposing sensitive assignment information across organisational boundaries.
Mitigation & Contingency
Mitigation: Write explicit RLS policies with integration tests that assert cross-chapter queries return zero rows. Use Supabase's built-in auth.uid() and join through the org membership tables to scope all queries.
Contingency: If a policy gap is discovered post-merge, immediately disable the affected table's SELECT policy, deploy a corrected policy, and audit recent queries in Supabase logs for any cross-boundary reads.