Unit test suite for MentorFilterService
epic-geographic-peer-mentor-map-core-services-task-013 — Write comprehensive unit tests for MentorFilterService covering: empty filter passthrough, availability-only filter, specialisation-only filter, combined availability + specialisation, validation rejection of invalid inputs, and FilterCriteria serialisation to Supabase query parameters. Verify that paused mentors are excluded by default. Target 90%+ coverage on filter service classes.
Acceptance Criteria
Technical Requirements
Execution Context
Tier 4 - 323 tasks
Can start after Tier 3 completes
Implementation Notes
The filter service should be a pure Dart class with no Flutter or BLoC dependencies, making it easy to test without `flutter_test` widget infrastructure. Serialisation tests are the highest-value tests here — ensure the Supabase `eq`, `in_`, and `overlaps` parameter names match what the repository actually passes to the Supabase client. For the paused mentor exclusion test, confirm whether exclusion happens in the filter service or the location service — it should be documented clearly and tested at the authoritative layer. If `FilterCriteria` uses `freezed`, generated equality simplifies assertion; otherwise override `==` and `hashCode`.
Keep fixture data minimal: 5–8 mentor objects covering all status and specialisation combinations is sufficient.
Testing Requirements
Pure unit tests with `flutter_test`. No BLoC or widget testing in this task — filter service is a plain Dart class. Use parameterised tests (`test.each` equivalent via a loop with `test()` calls) for serialisation assertions covering multiple filter combinations. Group tests with `group()` blocks per scenario.
Create a `fixtures/filter_criteria_fixtures.dart` with reusable `FilterCriteria` instances. Assert exact exception types for validation rejection tests using `expect(() => ..., throwsA(isA
The dual BLoC state machines (map view state + filter state) may introduce subtle synchronisation bugs where filter changes do not correctly re-trigger viewport queries, causing stale data to appear on the map.
Mitigation & Contingency
Mitigation: Define all BLoC state transitions in a state diagram before implementation. Use flutter_bloc's BlocObserver in development mode to log every state transition. Write explicit unit tests for filter-change → re-query transitions.
Contingency: If state synchronisation bugs appear in integration testing, refactor to a single unified BLoC that owns both map viewport state and filter state, eliminating cross-BLoC dependencies.
Cached mentor location data may become stale (mentors move, pause, or revoke consent) and coordinators in offline mode could be shown incorrect mentor information, leading to wasted outreach.
Mitigation & Contingency
Mitigation: Display a clear timestamp on cached data indicating when it was last synced. Set cache TTL to 24 hours and show an 'offline — data from [date]' banner. Revoked consent removes the mentor from the cache on next successful sync via contact-cache-sync-repository.
Contingency: If cache staleness causes user complaints, reduce TTL to 4 hours and implement background sync on app foreground. Accept that very-recently-revoked mentors may appear briefly in offline mode — document this as a known limitation in the privacy policy.