Write integration tests against seeded test database
epic-achievement-badges-evaluation-engine-task-014 — Write end-to-end integration tests for the full badge evaluation pipeline using a seeded Supabase test database. Tests must cover: activity insert triggering evaluation, correct badge award for each criteria type, no duplicate awards for already-earned badges, FCM notification dispatch on award, and audit log creation. Seed data must include Blindeforbundet org with 3rd and 15th honorar threshold badges.
Acceptance Criteria
Technical Requirements
Execution Context
Tier 6 - 158 tasks
Can start after Tier 5 completes
Implementation Notes
Structure tests in `supabase/functions/badge-criteria-edge-function/tests/` directory. Write a shared `test-helpers.ts` with functions: `seedBlindeforbundetOrg()`, `seedBadgeDefinitions()`, `seedPeerMentor(n_activities)`, `truncateTestTables()`. Use Deno's `Deno.serve` to spin up a mock FCM server on a configurable port during tests, recording all incoming POST requests for assertion. Configure the edge function to use the mock FCM URL via an environment variable during test runs.
For the duplicate-award test, insert the badge row in peer_mentor_badges before triggering the evaluation and assert only 1 row exists after. Consider using Supabase's local development stack (`supabase start`) as documented in supabase CLI docs for a fully isolated test environment. Tag each test with `// @scenario: threshold-3` comments for traceability back to acceptance criteria.
Testing Requirements
Integration test suite structure: describe blocks per scenario (threshold-3, threshold-15, duplicate-prevention, audit-log, fcm-dispatch, criteria-not-met). Each test: (1) truncate affected tables, (2) insert seed data for scenario, (3) invoke edge function directly or simulate DB webhook, (4) query database to assert expected state. Use Deno's `beforeEach` hooks for state reset. Mock FCM by running a local HTTP server that records incoming requests and returns 200.
Assert FCM mock received request with correct structure. Use `supabase functions serve` for local edge function execution during tests. Document how to run tests in the deployment runbook created in task-015.
Supabase Edge Functions may experience cold start latency of 500ms–2s when they have not been invoked recently. If evaluation latency consistently exceeds the 2-second UI expectation, the celebration overlay timing SLA cannot be met without the optimistic UI fallback from the UI epic.
Mitigation & Contingency
Mitigation: Keep the edge function warm by scheduling a lightweight health-check invocation every 5 minutes in production. Optimise the function size to minimise Deno module load time. Implement the optimistic UI path in badge-bloc (from the UI epic) as the primary UX path so cold start only affects server-side reconciliation, not perceived responsiveness.
Contingency: If cold starts remain problematic, migrate badge evaluation to a Supabase database function (pl/pgsql) triggered directly by a database trigger on activity insert, eliminating the Edge Function overhead entirely for the evaluation logic while keeping Edge Function only for FCM notification dispatch.
Supabase database webhooks can fail silently if the edge function returns a non-2xx response or times out. A missed webhook means a peer mentor does not receive a badge they earned, which is both a functional defect and a trust issue for organisations relying on milestone tracking.
Mitigation & Contingency
Mitigation: Implement idempotent webhook processing: the edge function reads the activity ID from the webhook payload and checks whether evaluation for this activity has already run (via an audit log query) before proceeding. Add Supabase webhook retry configuration (3 retries with exponential backoff). Monitor webhook failure rates via Supabase logs alert.
Contingency: Implement a nightly reconciliation job (Supabase scheduled function) that scans all activities from the past 24 hours, re-evaluates badge criteria for any peer mentor with no corresponding evaluation log entry, and awards any missing badges. Alert operations if reconciliation awards more than 5% of badges, indicating systematic webhook failure.
The evaluation service loads badge definitions per organisation, but a misconfigured RLS policy or incorrect organisation scoping in the edge function could cause one organisation's badge criteria to be evaluated against another organisation's peer mentor activity data, leading to incorrect or cross-contaminated badge awards.
Mitigation & Contingency
Mitigation: The edge function must extract organisation_id from the webhook payload activity record and pass it explicitly to every database query. Write a security test that seeds two organisations with distinct badge definitions and verifies that evaluating a peer mentor in org A never reads or awards org B definitions. Use Supabase service role key only within the edge function, never the anon key.
Contingency: If cross-org contamination is detected in audit logs, immediately disable the edge function webhook, run a targeted SQL query to identify and revoke incorrectly awarded badges, notify affected organisations, and perform a full security review of all RLS policies on badge-related tables before re-enabling.