Write unit tests for query builder and repository
epic-bufdir-data-aggregation-data-layer-task-008 — Write comprehensive unit tests for the Aggregation Query Builder and Bufdir Metrics Repository using flutter_test and mockito. Tests must cover: org-isolation filter always applied, correct RPC parameter mapping, view query correctness, snapshot save/retrieve/delete round-trips, cache-hit vs cache-miss paths, and domain error mapping for Supabase failures. The mock repository generated from the abstract interface must be verified to be usable as a drop-in for service-layer tests.
Acceptance Criteria
Technical Requirements
Execution Context
Tier 6 - 158 tasks
Can start after Tier 5 completes
Implementation Notes
Use mockito's @GenerateMocks annotation on a @GenerateMocks([AggregationQueryBuilder, SupabaseClient]) class and run build_runner to generate mocks. Organize tests in nested group() blocks mirroring the class structure. For the MockBufdirMetricsRepository usability test, create a minimal BufdirSomeService class in the test file itself that accepts IBufdirMetricsRepository and verify the mock can be passed to it — this validates the interface is correctly abstract. Use setUp() to reset mock state between tests.
For error mapping tests, throw PostgrestException with specific statusCode values and assert the resulting Left() contains the correct DomainFailure subtype. Avoid testing private implementation details — only test through public method signatures.
Testing Requirements
This task IS the testing work. Deliverable is a test file (test/data/repositories/bufdir_metrics_repository_test.dart) using flutter_test groups: 'AggregationQueryBuilder', 'BufdirMetricsRepository - read operations', 'BufdirMetricsRepository - snapshot persistence', 'BufdirMetricsRepository - error mapping', and 'MockBufdirMetricsRepository usability'. Run flutter test --coverage and confirm line coverage >= 90% for both classes. All tests must pass on CI without environment variables pointing to a real Supabase instance.
Supabase RPC functions return JSON with PostgreSQL numeric types (bigint, numeric) that do not map cleanly to Dart int/double. Silent truncation or JSON parsing errors could corrupt participant counts in the final Bufdir submission without any runtime exception.
Mitigation & Contingency
Mitigation: Define explicit Dart fromJson factories for all RPC result models with type-safe parsing and assertion checks. Add a contract test that compares raw RPC JSON output against expected Dart model values using a known seed dataset.
Contingency: If type mismatches are found in production metrics, expose a validation endpoint in BufdirMetricsRepository that re-fetches and compares raw RPC output against the persisted snapshot, flagging any discrepancies before export proceeds.
Persisted metric snapshots can become stale if additional activities are registered after the snapshot is saved but before the export is finalized. Coordinators might unknowingly export data that does not reflect the latest activity registrations.
Mitigation & Contingency
Mitigation: Store a snapshot_generated_at timestamp and a record_count_at_generation field in the snapshot. When the coordinator views cached results, compare the current activity count for the period against the snapshot value and display a 'Data updated since last aggregation — re-run?' warning if counts differ.
Contingency: Add a mandatory staleness check before the export confirmation dialog can proceed: if the snapshot is more than 24 hours old or the record count has changed, require the coordinator to re-run aggregation before the export button is enabled.