high priority low complexity testing pending testing specialist Tier 2

Acceptance Criteria

Test: fetchReminderConfig(orgId) with a mock that returns a valid row asserts that the returned ReminderConfig domain model has correct reminder_days and escalation_days values parsed from the mock response
Test: updateReminderDays(orgId, days) with a successful mock response asserts that the correct Supabase update call is made with the right table name, column filter (org_id = orgId), and new value
Test: updateEscalationDays(orgId, days) mirrors the above assertion for the escalation_days column
Test: fetchReminderConfig with a mock simulating RLS rejection (Supabase returns 0 rows for wrong org) asserts that the repository throws an OrgNotFoundException or equivalent typed exception — not a null return
Test: any repository method with a mock that throws a network/socket exception asserts that the repository wraps and rethrows a typed RepositoryException with the original cause preserved
All tests use flutter_test with a mock Supabase client (mockito or mocktail stub); no real network calls are made in any test
Test file is co-located with the repository source under test/repositories/ and follows the naming convention reminder_config_repository_test.dart
All 5+ test cases pass with flutter test and produce no analyzer warnings

Technical Requirements

frameworks
Flutter
flutter_test
mockito or mocktail
apis
Supabase Flutter SDK (mocked)
Supabase PostgREST client (mocked)
data models
ReminderConfig
OrgNotFoundException
RepositoryException
performance requirements
All unit tests must complete in under 2 seconds total; no async delays or real timers
security requirements
Tests must assert that RLS rejection (empty result set for wrong org_id) surfaces as a typed exception — never silently returns default values

Execution Context

Execution Tier
Tier 2

Tier 2 - 518 tasks

Can start after Tier 1 completes

Implementation Notes

The main challenge is mocking Supabase's fluent builder chain (from → select → eq → single). With mocktail, create a MockSupabaseClient and stub each chained call returning a new mock at each step. Alternatively, extract a thin SupabaseQueryRunner abstraction over the chain so tests only need to mock one method. For the RLS rejection scenario: Supabase returns an empty list (not an error) when RLS blocks access — the repository must explicitly check for empty and throw, rather than calling .single() which would throw a Supabase-specific exception with an unhelpful message.

Document this behavior in the test as a comment so future developers understand why the empty-list branch exists.

Testing Requirements

Pure unit tests using flutter_test. Use mocktail (preferred over mockito for null-safety ergonomics) to stub the Supabase client's from().select().eq().single() and from().update().eq() call chains. Create a test helper that builds a standard mock row map matching the reminder_config table schema to avoid duplication across test cases. Each test case should be independent with its own mock setup in setUp or individual test bodies.

Target 100% branch coverage of the ReminderConfigRepository class.

Epic Risks (3)
high impact medium prob integration

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.

medium impact medium prob dependency

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.

high impact low prob security

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.