Write unit tests for repository and vault client
epic-external-system-integration-configuration-foundation-task-012 — Write comprehensive unit tests for OrganizationIntegrationRepository and IntegrationCredentialVault using flutter_test and mocktail. Cover: CRUD success paths, Supabase error mapping, JSONB serialization round-trips, vault RPC call contracts, and null-safety edge cases. Achieve minimum 80% coverage on all repository and vault client methods.
Acceptance Criteria
Technical Requirements
Execution Context
Tier 5 - 253 tasks
Can start after Tier 4 completes
Handles integration between different epics or system components. Requires coordination across multiple development streams.
Implementation Notes
Use mocktail's `when().thenAnswer()` pattern for async Supabase calls. Create a shared `FakeSupabaseClient` helper class in `test/helpers/` that all repository tests can extend — this prevents duplication of mock wiring. For JSONB round-trip tests, store the expected JSON fixture as a `.json` file in `test/fixtures/` and load it with `rootBundle` or `File` — do not inline large JSON strings in test code. For vault RPC tests, capture the actual arguments passed to the mock using `verify(mockClient.rpc(captureAny(), params: captureAnyNamed('params')))` to assert the exact parameter shape.
Be careful with Dart null-safety: use `isNull` and `isNotNull` matchers rather than `== null` comparisons in `expect()` calls. Group tests with `group()` matching the class under test, and use `setUp()` for mock initialization.
Testing Requirements
Pure unit tests using flutter_test and mocktail. Mock the Supabase client at the lowest abstraction boundary — do not mock repository methods themselves. Test groups: (1) Repository CRUD success paths — verify correct Supabase query construction and domain object mapping; (2) Repository error mapping — inject PostgrestException with each relevant code (23505 duplicate, 42501 permission denied, PGRST116 not found) and assert the correct domain exception is thrown; (3) JSONB round-trips — serialize a fully-populated IntegrationConfig, deserialize from the mocked Supabase response, and assert field equality including nested FieldMappings; (4) Vault RPC contracts — verify storeCredential calls the correct RPC function name with expected parameters, retrieveCredential decodes the response envelope, rotateCredential invalidates old references; (5) Null-safety — test nullable fields returning null from Supabase, empty list responses, and missing optional JSONB keys. Run with `flutter test --coverage` and enforce 80% minimum via lcov threshold.
Supabase Vault API has limited documentation for Dart/Flutter clients; wrapping it correctly for credential rotation and secret reference management may require significant trial and error, delaying the vault component and blocking all downstream credential-dependent work.
Mitigation & Contingency
Mitigation: Spike the Vault integration in the first sprint using a minimal proof-of-concept (store, retrieve, rotate one secret). Document the API surface before building the full vault client. Identify any missing Dart SDK bindings early.
Contingency: If Supabase Vault is too complex, fall back to Supabase's encrypted column approach (pgcrypto) for credential storage as a temporary measure, with a planned migration path to Vault once the API is understood.
Incorrect RLS policy configuration on organization_integrations could allow org admins of one organization to read or modify another organization's integration credentials, creating a serious data breach and compliance violation.
Mitigation & Contingency
Mitigation: Write integration tests that explicitly attempt cross-org data access using different JWT tokens and assert 0 rows returned. Include RLS policy review in PR checklist. Use Supabase's local development stack for policy validation before deployment.
Contingency: If a breach is discovered post-deployment, immediately revoke all integration credentials, rotate vault secrets, notify affected organizations, and apply emergency RLS patches.
JSONB columns for field_mappings and sync_schedule lack database-level schema enforcement; AI-generated or malformed JSON could silently corrupt integration configurations, causing export failures that are hard to diagnose.
Mitigation & Contingency
Mitigation: Define TypeScript/Dart model classes with strict deserialization and validation. Add database check constraints or triggers that validate JSONB structure at write time. Version the JSONB schema to enable forward-compatible migrations.
Contingency: Build a repair script that scans organization_integrations for invalid JSONB and resets corrupted records to a safe default state, alerting the admin of the affected organization.