high priority medium complexity testing pending testing specialist Tier 8

Acceptance Criteria

Integration test: valid coordinator credentials → LoginSuccess → app navigates to coordinator home screen
Integration test: valid org admin credentials → LoginSuccess → app navigates to org admin home screen
Integration test: valid peer mentor credentials → LoginSuccess → app navigates to peer mentor home screen
Integration test: user with no recognized role → LoginSuccess → app shows no-access screen
Integration test: invalid credentials → LoginCredentialError → login form displays plain-language error message (not raw exception)
Integration test: simulated network failure (offline HTTP mock) → LoginNetworkError → login form displays network error message
Integration test: BLoC disposed and recreated after successful login → restoreSession() returns valid session → LoginSuccess emitted without re-entering credentials
Integration test: BLoC disposed and recreated after session expiry → LoginFormIdleState emitted → login form shown
Error messages rendered in the UI are human-readable English strings (not error codes or exception class names)
All integration tests are hermetic — no shared state between test cases, no real Supabase network calls in CI
Tests run successfully on flutter test runner without requiring a device

Technical Requirements

frameworks
Flutter
flutter_test
flutter_bloc
bloc_test
apis
Supabase Auth HTTP API (mocked via http mock or dedicated test Supabase project)
AuthService
LoginFormBLoC
data models
AuthSession
UserRole
LoginFormState (all variants)
AppRoute (navigation targets)
performance requirements
Full integration test suite must complete in under 60 seconds
HTTP mock layer must respond within 10ms to avoid test flakiness
security requirements
Test Supabase project (if used) must be isolated from production — separate project with disposable test users
Test credentials must not be committed to source control — use environment variables or flutter_test secrets
Session tokens generated during tests must not be stored persistently beyond test tearDown
ui components
LoginScreen
CoordinatorHomeScreen
OrgAdminHomeScreen
PeerMentorHomeScreen
NoAccessScreen
AppTextField (email, password)
AppButton (submit)

Execution Context

Execution Tier
Tier 8

Tier 8 - 48 tasks

Can start after Tier 7 completes

Implementation Notes

Prefer mocking the HTTP layer over using a real test Supabase project to keep tests hermetic and fast in CI. The Supabase Flutter SDK accepts a custom httpClient — inject a MockClient from the http_mock_adapter or mockito package. For role-based routing tests, seed the mock to return different role values in the user metadata and verify the router directs to the correct screen. The no-access screen test requires seeding a user with an authenticated session but no role in the roles table — mock the role lookup to return null.

Keep integration tests in `integration_test/` directory following Flutter conventions, but since these use mocks (no real device needed), they can also live in `test/integration/` for faster CI execution. Coordinate with the navigator/router implementation to ensure navigation assertions use the correct route names or widget finders.

Testing Requirements

Use flutter_test with WidgetTester for UI-level integration tests. Pump the full app widget tree (or a scoped subtree covering auth → home navigation) with dependency-injected mocks. For HTTP layer, use the http package's MockClient or intercept at the Supabase client level with a custom httpClient parameter. Structure tests in groups: 'role-based routing', 'error surface', 'session persistence'.

Each test must call tester.pumpAndSettle() after actions. For session persistence test: dispose BLoC, create new instance with same storage mock, verify restored state. TestFlight note: these automated tests run on the flutter_test runner in CI; the separate TestFlight build is for human testers.

Component
Login Form BLoC
service medium
Epic Risks (2)
high impact medium prob integration

Supabase GoTrue returns HTTP error codes and string messages that may change between SDK versions. Incorrect or incomplete mapping could cause the wrong user-facing message to be shown (e.g., showing a generic error instead of a specific credential error), violating the plain-language feedback acceptance criteria and potentially exposing security-sensitive information.

Mitigation & Contingency

Mitigation: Pin the supabase_flutter SDK to a specific minor version in pubspec.yaml. Write integration tests that mock the Supabase HTTP layer and assert each error code maps to the correct domain exception. Document the mapping table as a constant in AuthService.

Contingency: If an unrecognized error code is received at runtime, catch it as an UnknownAuthException and display a generic safe message. Alert via crash reporting for triage and SDK update.

medium impact medium prob technical

If the user taps the sign-in button multiple times rapidly, concurrent authentication requests could result in race conditions: duplicate network calls, out-of-order state emissions, or multiple session tokens being written to secure storage.

Mitigation & Contingency

Mitigation: Use bloc concurrency transformer (droppable or restartable) to ensure only one authentication event is processed at a time. The BLoC should guard against submission while in LoginLoading state.

Contingency: Add a UI-level disable on the submit button when loading state is active as a secondary guard independent of BLoC concurrency control.