high priority medium complexity testing pending testing specialist Tier 6

Acceptance Criteria

Integration test app launches with a seeded certification record whose expires_at is within 7 days from test execution date
Notifications tab renders ExpiryNotificationBanner without any manual interaction after app launch
Tapping ExpiryNotificationBanner triggers navigation to NotificationDetailView confirmed by finding the detail view's root widget key in the widget tree
Peer mentor role variant of NotificationDetailView renders exactly the view-certification-status action and no coordinator-only actions
Coordinator role variant of NotificationDetailView renders view-certification-status, trigger-course-enrollment, and acknowledge-lapse actions
Coordinator taps acknowledge-lapse: integration test confirms the action completes (loading indicator disappears, success feedback shown)
After acknowledge-lapse completion, navigating back to Notifications tab shows ExpiryNotificationBanner is absent from the list
All text elements visible during the flow have a contrast ratio of at least 4.5:1 against their background (WCAG 2.2 AA normal text)
All large text elements (18pt+ or 14pt bold+) have a contrast ratio of at least 3:1 (WCAG 2.2 AA large text)
Semantics tree at each screen in the flow contains labelled nodes for all interactive controls with no duplicate or empty labels
Test executes on both iOS Simulator and Android Emulator without platform-specific failures
Full flow completes within 30 seconds on a standard CI runner

Technical Requirements

frameworks
Flutter
flutter_test (integration_test package)
BLoC
Supabase (test/local instance or mock server)
apis
Supabase PostgREST (for seeding certification record)
Supabase Auth (for role-based session injection)
data models
certification
assignment
performance requirements
Full integration test flow must complete within 30 seconds
No real external network calls to production Supabase — use a local Supabase instance or intercepted mock
security requirements
Test Supabase credentials must be isolated to a test project and never overlap with production credentials
No real personnummer or PII in test seed data
ui components
Notifications tab scaffold
ExpiryNotificationBanner
NotificationDetailView
ActionButton (acknowledge-lapse)
Loading indicator overlay

Execution Context

Execution Tier
Tier 6

Tier 6 - 158 tasks

Can start after Tier 5 completes

Implementation Notes

Create the test at integration_test/certificate_expiry_notification_flow_test.dart. Abstract all seed/teardown into a CertificationTestFixture class to keep test bodies readable. Use a ProviderOverride or BlocOverride at the app level to inject a test-mode Supabase client pointing to the local test instance. The acknowledge-lapse action likely triggers an optimistic UI update followed by a Supabase RPC call — use tester.pumpAndSettle with a generous timeout (e.g.

10 seconds) to allow the async round-trip. For the banner-removal assertion after acknowledge-lapse, confirm both that the BLoC state has transitioned (no ExpiryNotificationBanner in tree) and that a re-query of the Notifications tab does not re-surface the banner. When running on CI, ensure the local Supabase instance is started as a service step before flutter test integration_test.

Testing Requirements

Use the Flutter integration_test package (integration_test/app_test.dart). Seed a certification record via a test helper that calls Supabase directly or uses a fake repository injected at app startup. Use IntegrationTestWidgetsFlutterBinding.ensureInitialized(). Navigate to the Notifications tab by tapping the bottom nav item.

Use tester.tap and tester.pumpAndSettle for navigation and async state resolution. For contrast checking, use the flutter_test AccessibilityGuideline with meetsGuideline(textContrastGuideline) and meetsGuideline(labeledTapTargetGuideline). Run once with a seeded peer mentor session and once with a coordinator session. Use tester.ensureSemantics() and verify the SemanticsController for each screen transition.

Include tearDown that removes the seeded certification record to prevent test pollution.

Epic Risks (2)
medium impact medium prob technical

The persistent banner must remain visible across app sessions and only disappear when a specific backend condition is met (renewal or coordinator acknowledgement). If the BLoC state is not properly sourced from the notification record repository on every app launch, the banner may disappear prematurely or fail to reappear after a session restart.

Mitigation & Contingency

Mitigation: Drive the banner's visibility exclusively from a Supabase real-time subscription on the notification records table filtered by mentor_id and acknowledged_at IS NULL. Never persist banner visibility state locally. Write an integration test that restarts the BLoC and verifies the banner reappears from the database source.

Contingency: If real-time subscriptions introduce latency or connection reliability issues in offline-first scenarios, add a local cache flag that is only cleared when the repository confirms the acknowledgement write succeeded, with a cache TTL of 24 hours as a fallback.

high impact low prob security

The notification detail view must conditionally render coordinator-specific actions based on the authenticated user's role. Incorrect role resolution could expose the 'Acknowledge Lapse' action to peer mentors or hide it from coordinators, breaking the workflow and potentially allowing unauthorised state changes.

Mitigation & Contingency

Mitigation: Source the role check from the existing role_state_manager BLoC that is already authenticated against Supabase role claims. Do not rely on a local flag. The coordinator acknowledgement service backend also validates role server-side, providing defence in depth. Add widget tests that render the detail view with mentor and coordinator role fixtures and assert the presence or absence of coordinator actions.

Contingency: If a role resolution bug is found in production, immediately disable the acknowledge action via a feature flag and patch the role check in a hotfix release. The server-side validation in the coordinator acknowledgement service ensures no actual state change can occur even if the button is incorrectly rendered.