Integration testing for mode selector and mentor selection screens
epic-bulk-and-proxy-registration-mentor-selection-task-012 — Write integration and widget tests covering the full mode entry and mentor selection flows: navigation from Proxy Mode Selector into both single and bulk paths, single-select enforcement (only one item selected at a time), multi-select validation gate (Continue blocked with zero selections), select-all / deselect-all behaviour, search filtering preserving existing selections, and accessibility semantics assertions for all three screens using flutter_test and accessibility test helpers.
Acceptance Criteria
Technical Requirements
Execution Context
Tier 8 - 48 tasks
Can start after Tier 7 completes
Implementation Notes
Create a test helper file test/helpers/mentor_selection_helpers.dart that provides: buildMultiSelectScreen(WidgetTester, {List
When asserting disabled state of 'Continue', check both the Semantics node (isEnabled: false) and that the onTap callback is null on the underlying widget. Avoid testing BLoC logic directly in widget tests — keep widget tests focused on UI and BLoC state integration; unit-test BLoC transitions separately in test/blocs/mentor_selection_bloc_test.dart.
Testing Requirements
Use flutter_test WidgetTester for all tests — no integration_test package required unless device-level gesture testing is needed. Structure tests in groups: (1) ProxyModeSelectorScreen navigation group, (2) SingleMentorSelect enforcement group, (3) MultiSelect validation gate group, (4) SelectAll/DeselectAll group, (5) Search and selection preservation group, (6) Accessibility semantics group. Use MockMentorRepository (mockito or manual fake) returning a fixed list of 5–10 synthetic PeerMentor objects. Wrap widgets under test in BlocProvider with a real or fake BLoC seeded with known state.
Use SemanticsController (tester.semantics) for accessibility assertions. After each test group, call tester.pumpAndSettle() to ensure animations complete. Include a tearDown that calls tester.binding.setSemanticsEnabled(false) to release resources.
NHF coordinators may manage dozens of peer mentors across multiple chapters. If the multi-select list renders all contacts in a single unsorted ListView, performance degrades with 50+ items, and coordinators cannot efficiently locate a specific mentor, increasing the probability of selection errors and wrong-person proxy registrations.
Mitigation & Contingency
Mitigation: Use a SliverList with itemExtent for fixed-height rows to enable O(1) scroll position calculation. Implement the search filter using a debounce utility operating on an in-memory list (no extra API calls). Sort the contact list alphabetically by default. Add chapter-filter chips above the list for NHF's multi-chapter coordinators.
Contingency: If performance issues arise in testing with real data sets, introduce pagination with a 'load more' trigger at the bottom of the list and cache rendered rows using Flutter's AutomaticKeepAliveClientMixin.
NHF has a complex 12-national-association / 9-region / 1,400-chapter hierarchy. It is ambiguous whether a coordinator can proxy-register for peer mentors outside their immediately assigned chapter. If the contact list is not correctly scoped by RLS, coordinators might see — and register on behalf of — peer mentors they do not manage, creating fraudulent activity records that skew Bufdir statistics.
Mitigation & Contingency
Mitigation: The Proxy Contact List Provider must query only peer mentors linked to the coordinator's own chapter scope via RLS. Add an explicit Supabase query test asserting that a coordinator from chapter A cannot retrieve peer mentors from chapter B. Display each mentor's chapter affiliation in the list row so coordinators can visually verify scope.
Contingency: If RLS scope is found to be too permissive in testing, apply a server-side coordinator_id filter as a secondary guard on the query. Block the feature release until the scope test passes consistently.