Integration and widget tests for user management screen
epic-admin-portal-user-management-task-014 — Write integration tests and widget tests covering: paginated list rendering, filter combination correctness against Supabase RLS views, role assignment flow, activation/deactivation toggle with confirmation, invitation submission, multi-chapter affiliation display without duplicate user rows, and navigation to user profile. Use flutter_test with mocked Supabase responses.
Acceptance Criteria
Technical Requirements
Execution Context
Tier 7 - 84 tasks
Can start after Tier 6 completes
Implementation Notes
Structure tests to mirror the BLoC state machine: each test should start from a known BLoC state (e.g., UserManagementLoaded with a seeded user list), pump the widget, perform an interaction, and assert the resulting state and rendered UI. Use `BlocProvider.value` to inject pre-configured BLoC instances rather than relying on the widget's internal BLoC creation. For multi-chapter affiliation deduplication tests, create a fixture with 3 UserProfile objects sharing the same userId but different chapterIds — verify the list renders 1 row with 3 chapter badges. For pagination tests, use a ScrollController and `tester.drag()` to simulate scroll-to-bottom, then verify the BLoC received a FetchNextPageEvent.
For confirmation dialogs (toggle), use `find.byType(AlertDialog)` and tap the confirm/cancel buttons explicitly. Separate test fixtures into a `test/fixtures/` directory (e.g., user_fixtures.dart) and share them across widget and integration tests to avoid duplicating mock data. Add a `// ARRANGE / ACT / ASSERT` comment structure to every test for readability.
Testing Requirements
Use flutter_test for widget tests and integration_test for end-to-end screen flows. Use bloc_test's `blocTest()` for BLoC unit tests covering each event/state transition. Use mocktail for mocking UserManagementService and SupabaseClient. Organise tests in groups: (1) Widget rendering group — initial state, loading state, empty state, error state; (2) Filter group — single filter, combined filters, filter reset; (3) Role assignment group — happy path, permission denied path; (4) Toggle group — confirm flow, cancel flow, optimistic UI rollback on failure; (5) Invite group — validation, success, server error; (6) Multi-chapter group — deduplication rendering; (7) Navigation group — row tap, deep link.
Run widget tests with `flutter test test/screens/user_management/` and integration tests with `flutter test integration_test/user_management_test.dart`. Aim for zero flaky tests — use `tester.pumpAndSettle()` carefully and prefer explicit `tester.pump(Duration)` for async operations with known durations.
Displaying NHF users with membership in up to 5 local chapters in a flat list view without duplicating entries requires a non-trivial aggregation query. Incorrect query design could result in duplicated user rows or missing chapter affiliations, confusing admins and causing incorrect role assignments.
Mitigation & Contingency
Mitigation: Design the user list query to GROUP BY user_id and aggregate chapter affiliations as an array field. Use AdminRepository's typed models to surface this aggregated structure to the UI. Validate with a test dataset containing users in 5 chapters.
Contingency: If aggregation query complexity proves too high for real-time filtering, implement a separate multi-chapter affiliation fetch triggered only when a specific user row is expanded, reducing query complexity for the base list.
Composable multi-dimensional filters (role + chapter + status + certification state) applied server-side against an org with 2,000+ users may produce slow queries, particularly when filtering by certification state requires joining an additional table.
Mitigation & Contingency
Mitigation: Ensure the relevant filter columns (role, status, chapter_id, certification_expiry) are indexed in Supabase. Use cursor-based pagination rather than OFFSET to maintain consistent performance at high page numbers. Profile filter query combinations against a large dataset during development.
Contingency: If multi-filter performance degrades in production, introduce a denormalised search index table updated on user status changes, allowing the list query to filter from a single table.
Deactivating a user account that has ongoing activity assignments, open expense claims, or active chapter affiliations may leave orphaned records or break downstream workflows if the deactivation does not trigger correct cascade handling.
Mitigation & Contingency
Mitigation: Define and document the expected state of each dependent record type on user deactivation before implementing the toggle. Implement deactivation as a UserManagementService operation that checks for and warns about open dependencies before persisting. Write integration tests covering each dependency type.
Contingency: If orphaned record issues are discovered post-launch, provide an admin-accessible reconciliation view that surfaces users with inconsistent dependency states and allows manual resolution without requiring a code deploy.