Write unit and integration tests for pause state machine
epic-peer-mentor-pause-management-core-workflows-task-013 — Write comprehensive tests for PauseManagementService covering all valid transitions (active→paused, paused→active, any→expired_cert), all invalid transition guards (cannot pause already-paused, cannot reactivate active mentor), notification dispatch side effects, and repository persistence calls. Use flutter_test with mocked repository and notification service. Achieve >90% branch coverage on the state machine logic.
Acceptance Criteria
Technical Requirements
Execution Context
Tier 6 - 158 tasks
Can start after Tier 5 completes
Implementation Notes
The state machine should be modeled as a pure function or a class method that accepts the current PeerMentorStatus and a requested transition, returning a Result/Either type rather than throwing exceptions — this makes branch coverage measurement straightforward. When mocking the repository, stub both the success path and failure path (e.g., Supabase network error) to ensure error propagation is tested. For the expired_cert transition, ensure the test simulates the certification expiry event as an input to the service rather than relying on a timer, since timers are difficult to test reliably. Use mockito's captor or argument matchers to assert the exact PauseRecord payload written to the repository.
Avoid testing UI or BLoC layer here — those belong in widget and integration tests.
Testing Requirements
Unit tests only — no widget or integration tests in this task. Use flutter_test with mockito or mocktail for mocking PauseManagementRepository and PauseNotificationService. Organize tests in groups: 'valid transitions', 'invalid transition guards', 'notification side effects', 'repository persistence'. Use setUp() to construct a fresh PauseManagementService with mocks before each test.
Use verify() / verifyNever() to assert mock interactions. Run flutter test --coverage and confirm coverage report shows ≥90% branch coverage on the service file. Parameterize transition tests where possible to avoid duplication.
Concurrent status transitions (e.g., coordinator and automated scheduler both attempting to update the same mentor's status simultaneously) may produce race conditions or inconsistent state in the database, leading to audit log gaps or incorrect notifications.
Mitigation & Contingency
Mitigation: Implement all status transitions as atomic Postgres RPC functions with optimistic locking (version column or updated_at check). Use database-level constraints rather than application-level guards as the final enforcement point.
Contingency: Add a compensation job that reconciles status and log table consistency on each nightly scheduler run, surfacing any discrepancies to coordinator dashboards.
The coordinator-to-mentor assignment relationship may not always be 1:1 or may be stale (coordinator reassigned after a pause was set), causing notifications to be sent to the wrong coordinator or not sent at all.
Mitigation & Contingency
Mitigation: Query the assignment relationship at notification dispatch time rather than caching it at pause creation time. Add a fallback to notify the chapter administrator if no active coordinator assignment exists.
Contingency: Log all undeliverable notification attempts with the originating mentor ID so administrators can manually follow up, and surface undelivered notification counts on the coordinator dashboard.
The CoordinatorPauseRosterScreen may load slowly for coordinators managing large rosters with many concurrent certification expiry queries, degrading usability on low-bandwidth mobile connections.
Mitigation & Contingency
Mitigation: Use a single Supabase RPC that joins mentor status, certification expiry, and assignment data in one query rather than N+1 individual calls. Implement pagination with a configurable page size and skeleton loading states.
Contingency: Add an offline cache of the last-fetched roster state using Riverpod with SharedPreferences, ensuring coordinators can at minimum view stale data when connectivity is poor.