medium priority low complexity testing pending testing specialist Tier 3

Acceptance Criteria

NotificationListItem: for each notification type (reminder, expiry, scenario, pause, system), a test verifies the correct icon widget is rendered
NotificationListItem: for each notification type, a test verifies the correct icon/badge color is applied (matching design tokens)
NotificationListItem: unread indicator (dot or badge) is visible when `isRead == false` and hidden when `isRead == true`
NotificationListItem: timestamp text renders as a relative string (e.g., '2 minutes ago') not an absolute datetime
NotificationListItem: tapping the item triggers the `onTap` callback exactly once
NotificationListItem: swipe-to-dismiss gesture triggers the `onDismiss` callback exactly once
NotificationListItem: Semantics tree contains correct labels for the item, unread state, and dismiss action
NotificationEmptyState: headline text ('No notifications') is present in the widget tree in the unfiltered state
NotificationEmptyState: CTA button ('Clear filter') is absent when `isFilterActive == false`
NotificationEmptyState: CTA button ('Clear filter') is present when `isFilterActive == true`
NotificationEmptyState: Semantics tree contains correct announcement for the empty state
All widget tests pass with `flutter test` and no golden file dependencies

Technical Requirements

frameworks
flutter_test
data models
Notification
NotificationType
performance requirements
All widget tests complete within 30 seconds total
security requirements
Test fixture notifications must not contain real user data
ui components
NotificationListItem
NotificationEmptyState
Dismissible (Flutter built-in)
Semantics

Execution Context

Execution Tier
Tier 3

Tier 3 - 413 tasks

Can start after Tier 2 completes

Implementation Notes

Wrap each test's `pumpWidget` call in a `MaterialApp` with a test `Localizations` delegate to prevent localization lookup failures. For the swipe-to-dismiss test, ensure the `Dismissible` key is deterministic (based on notification ID) so `find.byType(Dismissible)` resolves unambiguously. For color assertions on icons, use `tester.widget(find.byType(Icon))` to extract the Icon widget and assert `.color`. For timestamp rendering, inject a fixed `DateTime` via a `now` parameter or a clock abstraction in the widget to make relative time assertions deterministic.

For the Semantics tests, enable semantics in the test using `tester.ensureSemantics()` before pumping and dispose it afterward.

Testing Requirements

Widget tests using flutter_test and WidgetTester. Place in `test/features/notifications/widgets/`. Create two test files: `notification_list_item_test.dart` and `notification_empty_state_test.dart`. Use `tester.pumpWidget(MaterialApp(home: Scaffold(body: widgetUnderTest)))` as the pump wrapper.

For icon/color tests, use `find.byIcon(...)` and `find.byWidgetPredicate(...)` to locate and inspect widgets. For swipe-to-dismiss, use `tester.drag(find.byType(Dismissible), const Offset(-500, 0))` followed by `pumpAndSettle()`. For semantics, use `tester.getSemantics(find.byType(...))` and assert on label and hint values. No golden files — behavioral and semantic assertions only.

Component
Notification List Item
ui low
Epic Risks (3)
high impact medium prob technical

Supabase Realtime channels on mobile networks can drop silently. If reconnection logic is flawed, users miss notifications without knowing it, undermining the audit-trail guarantee.

Mitigation & Contingency

Mitigation: Implement exponential-backoff reconnection with a maximum of 5 retries; expose a channel-status stream to the BLoC so it can trigger a full-fetch fallback when the channel reconnects after a gap.

Contingency: If Realtime reliability proves insufficient in production, fall back to polling the repository every 60 seconds as a background supplement to the Realtime channel.

high impact medium prob security

Coordinator and org-admin RLS expansions require joining user_roles and org_memberships tables. An incorrect policy could expose notifications to wrong users or block legitimate access entirely.

Mitigation & Contingency

Mitigation: Write dedicated RLS integration tests for each role (peer mentor, coordinator, org admin) using separate Supabase test projects. Review policies with the security checklist before merging.

Contingency: If an RLS defect is discovered post-deployment, disable the expanded-scope policy and revert to user-scoped-only access while a corrected migration is prepared and tested.

medium impact medium prob integration

JSONB payload structure may vary across notification types created by different Edge Functions (reminder, expiry, scenario, pause). Missing or renamed fields will cause runtime parse failures.

Mitigation & Contingency

Mitigation: Define a canonical NotificationPayload union type in a shared schema document. Each Edge Function must validate its payload against this schema before inserting. Add fallback parsing with default values in the domain model.

Contingency: Wrap all payload parsing in try/catch and log malformed payloads to a monitoring channel; render a generic notification item rather than crashing when the payload cannot be parsed.