End-to-End Integration Test: Notification Pipeline
epic-push-notification-delivery-engine-task-014 — Write integration tests covering the full notification pipeline: FCM token registration, trigger service dispatch for new assignment event, payload delivery to the Flutter client in foreground and background states, deep link resolution to the correct screen, and persistence in NotificationRepository. Use a Supabase test project and a real FCM test device token. Verify preference-based filtering blocks opted-out users.
Acceptance Criteria
Technical Requirements
Execution Context
Tier 5 - 253 tasks
Can start after Tier 4 completes
Implementation Notes
Structure the test suite with a shared TestEnvironment helper class that initializes Supabase with test credentials, creates required test users with assigned roles, seeds FCM tokens, and tears down after completion. Use a test_helpers/notification_test_data.dart file for all seeded data to keep test files clean. For the cold-start test, use flutter_driver to terminate the app, then launch it via a notification click simulation — document that this requires manual steps if full automation is not feasible on CI. Use a dedicated FCM test sender utility (a simple Dart script calling the FCM HTTP v1 API with a service account) to trigger dispatches from within the test suite rather than relying on Supabase triggers during testing.
Annotate flaky async timing tests with a configurable timeout and retry mechanism.
Testing Requirements
Integration test suite (flutter integration_test package) organized into test groups: (1) Token Registration, (2) Foreground Dispatch & Receipt, (3) Background Dispatch & Receipt, (4) Cold-Start Deep Link, (5) Notification Persistence & Idempotency, (6) Preference Filtering. Each group has setup/teardown that seeds and cleans Supabase test data. Use flutter drive or a CI-compatible test runner. Physical device or emulator with Google Play Services required — pure Dart tests cannot test FCM delivery.
Document required test device setup in the test file header. TestFlight device (iOS) must be used for the cold-start scenario.
Flutter's background message handler for FCM must run in a separate Dart isolate. Incorrect dependency initialization in the isolate (e.g., attempting to access Riverpod providers or Supabase before initialization) will cause silent crashes on Android when the app is terminated, resulting in missed notifications that are invisible in crash reporting.
Mitigation & Contingency
Mitigation: Use a minimal top-level background handler function annotated with @pragma('vm:entry-point') that only stores the raw RemoteMessage payload to a platform channel or shared preferences. Process the payload in the main isolate on next app launch. Write an explicit test for terminated-state message handling on Android.
Contingency: If isolate crashes are observed, implement a native Android FirebaseMessagingService subclass that handles background messages without Flutter isolate complexity, falling back to a database-insert-only approach for terminated-state notifications.
Supabase Edge Functions can experience cold-start latency of 1–3 seconds after periods of inactivity. For high-frequency events like assignment creation, cumulative cold starts could cause dispatch delays exceeding the 30-second SLA, reducing the perceived reliability of the notification system.
Mitigation & Contingency
Mitigation: Configure the Edge Function with a keep-warm ping mechanism or use Supabase database webhooks that invoke the function directly on row insert to minimize cold-start frequency. Batch preference lookups within the function to reduce per-invocation Supabase round-trips.
Contingency: If latency SLA is consistently breached, move to a polling or Realtime-subscription architecture within the Edge Function, or pre-compute dispatch targets at preference-save time to eliminate per-dispatch preference queries.
If the deep link handler does not perform server-side role validation before rendering the target screen, a peer mentor who receives a mis-configured notification payload containing a coordinator-only route could access restricted data, violating the role-based access control invariants.
Mitigation & Contingency
Mitigation: The deep link handler must check the user's current role from the RoleStateManager before constructing the navigation route. Coordinator-only routes must be listed in a deny-list checked against the current role. The go_router route guard is a second line of defence.
Contingency: If a role bypass is discovered in testing, immediately add the affected route to the deep link handler deny-list and add a regression test. Audit all notification payload types for route targets that could expose cross-role data.
FCM v1 HTTP API enforces per-project send quotas. For large organisations with many active peer mentors receiving simultaneous assignment notifications, batch dispatch events (e.g., bulk coordinator assignments) could approach quota limits and result in dropped notifications with 429 errors logged silently.
Mitigation & Contingency
Mitigation: Implement exponential backoff retry logic in the Edge Function for 429 responses. Design bulk assignment flows to dispatch notifications in batches with a configurable delay between batches. Monitor FCM console quotas during load testing.
Contingency: If quota limits are hit, implement a notification queue table in Supabase and a separate Edge Function that processes the queue with rate limiting, ensuring eventual delivery without exceeding FCM quotas.