Write integration tests for data layer
epic-travel-expense-registration-foundation-task-011 — Write integration tests covering the full data layer: expense type catalogue fetch and offline fallback, expense claim create/read/update with offline queue sync, receipt upload and signed URL retrieval, threshold configuration load and cache invalidation, and auto-approval edge function invocation. Use flutter_test and a local Supabase emulator or mock server. Assert that all repository methods handle network failure gracefully.
Acceptance Criteria
Technical Requirements
Execution Context
Tier 3 - 413 tasks
Can start after Tier 2 completes
Implementation Notes
Do not use `mockito` or similar mocking libraries for these tests — the intent is true integration against a real (emulated) database. Use the actual repository classes (ExpenseRepository, ReceiptRepository, etc.) instantiated with the emulator Supabase client. Seed data should be declared in `test/fixtures/expense_seed.sql` and loaded via `supabase db reset --local` or the emulator's REST seed endpoint in `setUpAll`. For offline simulation, wrap the Supabase client in a `NetworkAwareSupabaseClient` that checks a `NetworkInfo` abstraction — this is testable via injection.
The CI step order must be: (1) `supabase start`, (2) `supabase db reset --local` to apply seed, (3) `flutter test integration_test/`, (4) `supabase stop`. Watch for Supabase emulator Storage — it requires the `storage` service to be running; confirm `config.toml` includes it.
Testing Requirements
These tests ARE the deliverable. Structure: `integration_test/data_layer/` with one file per domain area (expense_types_test.dart, expense_claims_test.dart, receipt_test.dart, threshold_config_test.dart, auto_approval_test.dart). Each file uses `setUpAll` to seed the emulator with fixture data and `tearDownAll` to clean up. Use `flutter_test`'s `TestWidgetsFlutterBinding` for async support.
For offline tests, inject a `NetworkInfoMock` that simulates no connectivity. For edge function tests, use the emulator's local function URL. Document how to run the suite in the project README (or in task-012 documentation).
Row-level security policies for expense claims must correctly scope data to organisation, role (peer mentor sees own claims only, coordinator sees org-wide queue), and claim status. Incorrect RLS can expose claims cross-organisation or prevent coordinators from accessing the attestation queue.
Mitigation & Contingency
Mitigation: Define RLS policies in code-reviewed migration files. Write integration tests that attempt cross-org reads with different JWT roles and assert access denial. Review with a second engineer before merging migrations.
Contingency: If RLS is misconfigured post-deployment, disable the affected policy temporarily and apply a hotfix migration within the same release window. No claim data is exposed publicly due to Supabase project-level auth requirement.
The auto-approval Edge Function is triggered server-side on expense insert. Cold-start latency or Edge Function failures can block the submission response and degrade UX, especially on mobile networks.
Mitigation & Contingency
Mitigation: Implement the auto-approval Edge Function client with a timeout and graceful fallback: if no result is received within 5 seconds, treat the claim as 'pending' and poll for the status update via Supabase Realtime. Keep the Edge Function warm with a periodic ping.
Contingency: If Edge Function reliability is unacceptable, move auto-approval evaluation to a database trigger or Postgres function as an interim measure, accepting that threshold configuration changes require a migration rather than a settings update.
The expense type catalogue and threshold configuration are cached locally for offline use. If an organisation updates their catalogue exclusion rules or thresholds while a peer mentor is offline, the local cache may allow submissions that violate the new policy.
Mitigation & Contingency
Mitigation: Cache entries include a TTL (24 hours). On connectivity restore, refresh cache before allowing new submissions. Server-side validation in the Edge Function and save functions provides a second enforcement layer.
Contingency: If a stale-cache submission passes client validation but fails server validation, surface a clear error message explaining that the expense type rules have been updated and prompt the user to review their selection with the refreshed catalogue.