high priority high complexity testing pending testing specialist Tier 6

Acceptance Criteria

AdminPortalBloc unit tests cover all events: LoadDashboardStats, PropagateScope, TriggerExport, CancelExport, ChangePage, ApplyFilter, ClearFilter — each verified for correct state transitions
BLoC tests verify initial state is AdminPortalInitial and loading states are emitted before success/failure states for async operations
Scope propagation tests confirm org_admin scope restricts data to authenticated admin's organisation subtree and super_admin scope returns all organisations
Export job lifecycle tests cover: job queued → in-progress → completed and job queued → in-progress → failed, verifying correct ExportState emissions
Pagination tests verify page index increments/decrements correctly, boundary conditions (page 0 min, maxPage max), and correct data slice is emitted per page
Filter state tests verify filter application changes emitted data, clearing filter restores unfiltered state, and multiple simultaneous filters compose correctly
Widget test for AdminDashboardScreen renders stat cards with injected mock BLoC data and shows loading indicators during AdminPortalLoading state
Widget test for CertificationStatusPanel renders correct certification counts, expiry badges, and links using mock data; verifies empty state UI
Widget test for ActivityLogViewer renders paginated activity rows, pagination controls are tappable, and log entries display correct metadata
Widget test for AdminExportPanel renders export format options, triggers export event on button tap, shows progress indicator during export, and shows success/error feedback
Widget test for RoleAssignmentPanel renders user list with current roles, confirmation dialog appears before role change, and RoleChanged event is dispatched on confirm
All widget tests use mocktail or bloc_test MockBloc to inject controlled states without real Supabase calls
flutter test --coverage reports minimum 80% line coverage for all files in the admin portal epic
All tests pass in CI with zero flaky failures across 3 consecutive runs
Test file names follow convention: {widget_or_bloc}_test.dart, placed in test/admin_portal/ mirroring the lib/ structure

Technical Requirements

frameworks
Flutter
BLoC (bloc_test package)
flutter_test
mocktail
data models
AdminPortalState
AdminPortalEvent
OrgAdminScope
AdminActivity
AdminReimbursement
ExportJob
performance requirements
Full test suite must complete in under 60 seconds on CI
No individual test should exceed 5 seconds (use fake async for timers)
Use fakeAsync and pump/pumpAndSettle judiciously — avoid unnecessary real async waits
security requirements
Mock Supabase client must never make real network calls — use dependency injection to inject mocks
Test data must not contain real PII — use clearly fictional names and IDs
Ensure mock scope objects correctly simulate org isolation so tests verify security boundaries
ui components
AdminDashboardScreen
CertificationStatusPanel
ActivityLogViewer
AdminExportPanel
RoleAssignmentPanel

Execution Context

Execution Tier
Tier 6

Tier 6 - 158 tasks

Can start after Tier 5 completes

Implementation Notes

Use the bloc_test package's blocTest() function — it handles setUp, tearDown, and assertion boilerplate cleanly. For widget tests, create a helper buildTestWidget(Widget child, {AdminPortalBloc? bloc}) that wraps with MaterialApp + BlocProvider to reduce repetition. Mock Supabase by injecting a mock AdminRepository into the BLoC constructor rather than mocking Supabase directly — this keeps tests layer-appropriate.

For the RoleAssignmentPanel confirmation dialog, use tester.tap() to trigger the dialog and then tester.tap(find.text('Confirm')) to confirm — ensure pumpAndSettle() after each interaction. For pagination tests, verify both the emitted state's currentPage and the rendered widget's page indicator text. Coverage gaps are most common in error branches — explicitly test every catch block by having mock repositories throw exceptions. Run `flutter test --coverage && genhtml coverage/lcov.info -o coverage/html` locally to inspect uncovered lines before submitting.

Testing Requirements

This task IS the testing task. Tests must include: (1) BLoC unit tests using bloc_test's blocTest() helper with act/expect pattern for every event type; (2) Widget tests using WidgetTester with pumpWidget wrapping widgets in BlocProvider(create: (_) => mockBloc); (3) Golden tests optional but encouraged for AdminDashboardScreen to catch regressions; (4) Use whenListen() from bloc_test to emit sequences of states and verify widget rebuilds; (5) Coverage report generated via `flutter test --coverage` and lcov; (6) Edge case tests: empty data sets, null values in optional fields, network error states, maximum pagination boundary.

Component
Admin Portal BLoC
data high
Dependencies (4)
Add export job lifecycle state management to the AdminPortalBloc. Implement ExportTriggered, ExportProgressUpdated, ExportCompleted, and ExportFailed events. Poll or subscribe to AdminExportService for job status updates. Store the download URL in state when export completes. Ensure concurrent exports are handled gracefully and existing job state is preserved across scope changes. epic-admin-portal-dashboard-ui-task-011 Add pagination and filter state management for both the user list and activity list to the AdminPortalBloc. Define filter models for user list (role filter, chapter filter, search query) and activity list (date range, type, chapter). Ensure filter state persists across tab switches within the admin portal and resets correctly when the org hierarchy scope changes. epic-admin-portal-dashboard-ui-task-014 Add certification reminder state management to the AdminPortalBloc. Implement SendCertificationReminder event that invokes the AdminNotificationDispatcher for the specified mentor(s). Track pending/sent/failed reminder states per mentor ID in the BLoC state so the UI can show confirmation feedback without re-fetching the full certification list. Debounce repeated reminder sends. epic-admin-portal-dashboard-ui-task-013 Compose the complete AdminDashboardScreen by integrating the KPI grid, ActivityLogViewer, CertificationStatusPanel, AdminExportPanel, and RoleAssignmentPanel trigger into a unified tab or section layout. Implement navigation between panels using a tab bar or drawer. Ensure that the org hierarchy scope from the OrgHierarchyNavigator propagates to all panels via the shared AdminPortalBloc. epic-admin-portal-dashboard-ui-task-015
Epic Risks (3)
high impact medium prob technical

If org node selection in AdminStateBLoC does not correctly propagate to all dependent data streams (statistics, activity log, user list, certification panel), some panels may show data from the previously selected org scope, creating a confusing and potentially dangerous mixed-scope view.

Mitigation & Contingency

Mitigation: Model org node selection as a single source of truth in AdminStateBLoC. All downstream providers derive their query parameters from this single stream via Riverpod's watch pattern. Write integration tests that verify every data stream emits a reload event when the selected node changes.

Contingency: If scope propagation bugs are detected in QA, add an explicit full-state reset on org node change (clear all cached data and refetch from scratch) as a safe but less efficient fallback until the targeted propagation is fixed.

medium impact medium prob technical

The Admin Dashboard Screen must adapt its layout for Flutter Web (wider viewports, mouse interaction, larger grid) and mobile embedding. Flutter Web responsive layout support has historically required non-trivial workarounds, and the adaptive grid may introduce significant additional development time.

Mitigation & Contingency

Mitigation: Define breakpoints and grid behaviour in the design system before implementation. Use LayoutBuilder with explicit breakpoint constants rather than MediaQuery scattered across widgets. Prototype the web layout with a skeleton screen before implementing live data binding.

Contingency: If web layout proves intractable within sprint, deliver a mobile-first layout for all platforms initially and track a dedicated web-optimisation task for the next sprint.

high impact low prob security

A bug in the Role Assignment Panel's permission scope validation could allow an org_admin to assign roles beyond their authority (e.g., assigning super_admin to a user), representing a serious privilege escalation vulnerability.

Mitigation & Contingency

Mitigation: Enforce role assignment scope on both the client (disable unavailable roles in the panel UI) and the server (UserManagementService validates the target role is within the admin's permitted scope before persisting). Write security-focused tests that attempt out-of-scope role assignments and assert rejection.

Contingency: If an escalation vulnerability is discovered, immediately disable the role assignment panel via feature flag, revoke any incorrectly assigned roles, and deploy a server-side fix before re-enabling.