high priority medium complexity testing pending testing specialist Tier 2

Acceptance Criteria

Test: recordNotificationSent persists a record with correct fields: user_id, scenario_type, sent_at (within 1 second of test execution), delivery_status='pending', retry_count=0
Test: updateDeliveryStatus transitions delivery_status from 'pending' to 'delivered' and updates delivered_at timestamp
Test: updateDeliveryStatus transitions delivery_status from 'pending' to 'failed' and records error_code
Test: updateDeliveryStatus called with an invalid status value throws an ArgumentError before making any Supabase call
Test: upsertCooldown stores the cooldown record with correct user_id, scenario_type, and last_sent_at fields; subsequent call for same key updates last_sent_at without creating a duplicate
Test: getCooldown returns the correct last_sent_at datetime for a user/scenario combination
Test: getCooldown returns null when no cooldown record exists for the given user/scenario combination
Test: getPendingRetries returns only records where retry_count < 3 AND delivery_status = 'failed'
Test: getPendingRetries returns an empty list when no eligible retry records exist
Test: when Supabase throws a PostgrestException with a unique constraint violation code, repository propagates a typed DuplicateNotificationException
Test: when Supabase throws a network exception, repository propagates a typed RepositoryNetworkException
All tests use mocked Supabase client — no real network calls
Achieved branch coverage for ScenarioNotificationRepository is >= 90%

Technical Requirements

frameworks
Flutter
flutter_test
mockito or mocktail
apis
Supabase PostgreSQL 15
performance requirements
All unit tests complete in under 3 seconds total
security requirements
Test fixtures must not contain real device tokens, user UUIDs, or PII
Constraint violation test must verify that the repository does not silently swallow duplicate notification errors — they must surface as typed exceptions

Execution Context

Execution Tier
Tier 2

Tier 2 - 518 tasks

Can start after Tier 1 completes

Implementation Notes

The trickiest tests are the getPendingRetries filter assertions — configure the mock to return a list containing records with mixed retry_count and status values, then assert only the eligible ones are returned. If the filtering happens in the repository's Dart code (after fetching all records), mock a broader result set; if it happens via Supabase query filters, verify the correct .lte('retry_count', 2) and .eq('delivery_status', 'failed') filter calls are made on the query builder. For the cooldown upsert idempotency test, configure the mock to return the upserted record on both calls and verify the Supabase upsert() is called with onConflict set to the correct constraint column. Wrap all repository method calls in try/catch in tests to confirm typed exceptions are thrown rather than raw Supabase or Dart core exceptions.

Testing Requirements

All tests are unit tests using flutter_test with mocktail or mockito for Supabase client mocking. Structure tests in groups: 'recordNotificationSent', 'updateDeliveryStatus', 'cooldown operations', 'getPendingRetries', 'error handling'. Test the PostgrestException unique constraint violation path by configuring the mock to throw a PostgrestException with code '23505' (PostgreSQL unique violation). Test the network exception path by throwing a SocketException.

Verify exact Supabase query arguments (table name, filter columns, filter values) using verify() assertions to catch regressions if the repository implementation changes table or column names. Run flutter test --coverage and confirm >= 90% branch coverage on the repository file.

Component
Scenario Notification Repository
data medium
Epic Risks (3)
high impact medium prob dependency

FCM service account key and APNs certificate configuration may be missing or misconfigured in the Supabase Edge Function secrets store, blocking end-to-end push delivery testing until resolved by the infrastructure owner.

Mitigation & Contingency

Mitigation: Raise a credentials-setup task in the project board at epic start; document the exact secret names required in scenario-evaluation-config so the infrastructure owner can provision them independently of development work.

Contingency: Implement a mock push-notification-dispatcher stub that records payloads to the database for local testing, allowing the rest of the feature to proceed while credentials are obtained.

high impact low prob security

Incorrect RLS policies on the scenario_notifications or notification_preferences tables could allow one user to read or modify another user's notification records, constituting a data privacy breach.

Mitigation & Contingency

Mitigation: Write dedicated RLS policy tests using Supabase's built-in test framework before any application code touches the tables; require a peer security review of all policy definitions before merging.

Contingency: If a policy gap is discovered post-merge, immediately disable the affected table's read policy, notify the security lead, and deploy a hotfix with corrected policies before re-enabling access.

medium impact medium prob dependency

Norwegian Bokmål ARB localisation strings for all scenario message templates may not be available at implementation time, causing content-builder tests to fail and delaying integration.

Mitigation & Contingency

Mitigation: Define all required ARB message keys in a tracked document shared with the content owner at epic kickoff; use English placeholder strings that follow the final format so template injection logic can be tested independently.

Contingency: Ship with English-only strings in the first release and gate Norwegian strings behind a feature flag that is enabled once translations are reviewed and approved.