high priority medium complexity testing pending testing specialist Tier 7

Acceptance Criteria

Integration test suite covers the complete forward role switch path: login → home screen variant A → open Role Switch Widget → select role B → home screen variant B rendered correctly
After role switch, Role-Aware Bottom Navigation renders exactly the tab set defined for the new role (no stale tabs from previous role)
Route Guard blocks navigation to a route that is forbidden under the new role and redirects to the correct fallback screen
Switching back to the original role fully restores home screen variant A and the original tab set
BLoC state for active role is correctly persisted across the switch and reflects the new role in all consuming widgets
Role Switch Widget closes after selection and no duplicate navigation events are fired
Test uses a seeded multi-role user fixture (not a live Supabase account) to ensure deterministic results in CI
All integration test cases pass on both iOS and Android Flutter integration test targets
Test execution time does not exceed 60 seconds for the full suite on a standard CI runner

Technical Requirements

frameworks
Flutter
flutter_test
BLoC
Riverpod
apis
Supabase Auth (mocked or seeded test tenant)
data models
UserRole
RolePermissions
UserSession
performance requirements
Role switch state transition must settle within 500ms from user tap to home screen re-render in test environment
security requirements
Test fixtures must not contain real user credentials — use a dedicated CI test account or Supabase local dev instance
Route guard must be exercised for at least one forbidden route per role transition to confirm authorization is re-evaluated on switch
ui components
Role Switch Widget
Role-Based Home Screen (all variants)
Role-Aware Bottom Navigation
Route Guard

Execution Context

Execution Tier
Tier 7

Tier 7 - 84 tasks

Can start after Tier 6 completes

Implementation Notes

The key complexity here is waiting for asynchronous BLoC state transitions before asserting UI state. Use await tester.pumpAndSettle() after each action, but set a generous timeout (3–5s) to avoid false failures from animation completion. For route guard enforcement, navigate programmatically using the GoRouter test helper or by finding and tapping a link widget that leads to a role-restricted route — do not call router.go() directly in the test as this bypasses the guard. Seed the test user fixture at the start of the test run using a beforeAll-equivalent setup.

Use Riverpod's ProviderContainer overrides to inject a mock AuthRepository so the test does not depend on a live Supabase instance. Pay special attention to StatefulShellRoute tab state preservation: after a role switch, tabs that existed in both roles should not lose their navigation stack.

Testing Requirements

Use Flutter integration_test package (not flutter_test widget tests) to drive a real app instance. Create a test fixture factory that seeds a multi-role user with at least two roles (e.g., peer_mentor + coordinator). Structure tests as a sequential scenario using testWidgets with WidgetTester pump-and-settle after each BLoC state emission. Mock Supabase calls using a local Supabase instance or an HTTP mock layer (e.g., http_mock_adapter) to avoid flakiness.

Include at least: (1) happy-path role switch, (2) switch-back state restoration, (3) route guard enforcement after switch, (4) rapid double-tap on Role Switch Widget (should not cause duplicate transitions). Run on both platforms in CI.

Component
Role Switch Widget
ui medium
Epic Risks (3)
high impact medium prob technical

Combining GoRouter's declarative redirect logic in the route guard with StatefulShellRoute's stateful branch management is known to produce subtle bugs where the shell rebuilds unnecessarily on role switches, losing tab state or causing double-navigation events.

Mitigation & Contingency

Mitigation: Implement the route guard as a GoRouter redirect callback that only evaluates role from an already-resolved Riverpod provider (not async). Use a dedicated ShellRoute navigator key per tab branch to anchor state independently of role-driven rebuilds. Write integration tests for the full navigation graph.

Contingency: If StatefulShellRoute state loss is confirmed during QA, fall back to a manual tab state preservation approach using a TabStateManager service that caches the last route per tab and restores it after role switches, decoupling tab state from the shell lifecycle.

medium impact high prob scope

The role-based home screen must render three significantly different layouts (coordinator dashboard, peer mentor activity summary, org admin overview). If these variants are implemented as a single widget with conditionals, the file will become unmaintainable and difficult to test in isolation, especially as each variant grows with downstream feature additions.

Mitigation & Contingency

Mitigation: Design the role-based home screen as a router/dispatcher widget that delegates to three separate variant widgets (CoordinatorHomeView, PeerMentorHomeView, OrgAdminHomeView). Each variant is independently testable and can be developed by separate team members in parallel.

Contingency: If variant coupling has already occurred before this risk is addressed, refactor to the dispatcher pattern in a dedicated cleanup task before feature handoff. The dispatcher pattern is a straightforward extraction that carries low refactoring risk.

medium impact medium prob integration

The no-access screen must link global admin users to the correct admin portal URL, which may differ per organization (NHF, HLF, Blindeforbundet each have their own admin portals). Hardcoding a single URL will result in wrong or broken links for some global admin users.

Mitigation & Contingency

Mitigation: Source the admin portal URL from the organization's configuration record in Supabase rather than hardcoding it. The no-access screen reads the active org context and resolves the portal URL dynamically. Provide a safe fallback to a generic Norse Digital Products support page if the URL is not configured.

Contingency: If dynamic URL resolution is not ready when the no-access screen ships, display a static instruction to contact the organization's administrator along with a support email address as an interim measure, and track the URL configuration task as a follow-up.