Integration test: end-to-end blocked-role navigation enforcement
epic-no-access-screen-access-control-task-010 — Write an integration test simulating a global admin logging in and attempting to navigate to peer-mentor screens. Verify: guard intercepts all navigation, user lands on /no-access, logout button on no-access screen navigates successfully to auth flow, and no peer-mentor data is accessible during the blocked session. Run against a test Supabase environment with a seeded global admin account.
Acceptance Criteria
Technical Requirements
Execution Context
Tier 8 - 48 tasks
Can start after Tier 7 completes
Implementation Notes
The integration test environment requires a dedicated Supabase test project with a seeded `global_admin` role account. Add a `README` note in the `integration_test/` folder documenting the required environment variables (`TEST_SUPABASE_URL`, `TEST_SUPABASE_ANON_KEY`, `TEST_GLOBAL_ADMIN_EMAIL`, `TEST_GLOBAL_ADMIN_PASSWORD`). Use `setUpAll` to sign in once and `tearDownAll` to sign out, reducing auth round-trips. To verify that no peer-mentor data is accessible, check that Supabase RLS policies block the global admin role at the database level — this is more reliable than UI-only assertions.
Consider tagging this test with `@Tags(['integration'])` so it can be excluded from fast unit test runs in CI.
Testing Requirements
Integration test using Flutter's `integration_test` package and `flutter_test`. Use `WidgetTester.pumpAndSettle()` after navigation actions to allow GoRouter redirects to resolve. Authenticate via Supabase test credentials injected from environment variables (use `String.fromEnvironment` or a `test_config.dart` file gitignored from the repo). After login, use `tester.tap` on navigation triggers or programmatic `context.go('/home')` calls.
Assert screen identity by finding unique widget keys or text strings on the No-Access screen. The logout flow assertion should verify the auth screen is presented after tapping logout.
If the GoRouter redirect callback evaluates the no-access route itself as a blocked destination, it will trigger an infinite redirect loop, crashing the navigator.
Mitigation & Contingency
Mitigation: Add an explicit guard condition in the redirect callback: return null (no redirect) when the current location is already the no-access route or the logout route. Write a dedicated unit test covering this exact scenario.
Contingency: If the redirect loop is detected in production, deploy a hotfix that adds the null-return guard; the feature can be toggled off via the existing feature-flag infrastructure while the fix is prepared.
The access-denial-service may read role state before authentication completes (e.g. during app resume), causing a temporary false-positive block that redirects valid peer-mentor users to the no-access screen.
Mitigation & Contingency
Mitigation: Subscribe to the role-state-manager's loading/ready lifecycle and only evaluate role-based access once the RBAC state is confirmed as loaded. Return a 'pending' state that causes the guard to defer rather than redirect.
Contingency: Add a retry mechanism: if a user lands on the no-access screen but their role subsequently resolves as non-blocked, automatically navigate them to the role-based home screen.