Integration test: full map feature user flow
epic-geographic-peer-mentor-map-ui-accessibility-task-018 — Write a Flutter integration test covering the complete coordinator map feature flow: open map screen, verify mentors appear as markers, open filter panel, apply availability filter, verify marker set updates, tap a marker, verify popup loads instantly from state, navigate to peer mentor detail via deep link, return to map, toggle to list fallback, verify list shows same filtered set, and toggle back to map without filter reset. Run test on both iOS and Android simulators.
Acceptance Criteria
Technical Requirements
Execution Context
Tier 7 - 84 tasks
Can start after Tier 6 completes
Implementation Notes
The biggest risk in this test is map tile rendering — real map tiles require network access and can be slow or unavailable in CI. Configure the map plugin to use an offline tile provider or a blank tile source in test mode, controlled by a build-time constant (e.g., const bool.fromEnvironment('INTEGRATION_TEST')). For marker count assertions, assign a Key('map-marker-{mentorId}') to each MapMarkerWidget so you can find them precisely. The popup 500ms timing assertion should use tester.pump(Duration(milliseconds: 500)) then assert the popup is visible — avoid pumpAndSettle for timing-sensitive checks.
Use a fixture class that generates consistent PeerMentor test data by ID so assertions are stable across runs. Ensure back navigation in the test uses tester.pageBack() rather than hardware back button simulation for cross-platform consistency.
Testing Requirements
Flutter integration test using the integration_test package. Stub all Supabase calls with deterministic seed data (minimum 10 mentors, mixed availability states, 3+ specialisations). Use testWidgets() with a WidgetTester and IntegrationTestWidgetsFlutterBinding.ensureInitialized(). Assert UI state after each user action using find.byType(), find.byKey(), and find.bySemanticsLabel().
Marker count assertions: count rendered MapMarkerWidget instances and compare to expected filtered set size. Configure the test to run in CI via GitHub Actions (or equivalent) using flutter test integration_test/ --device-id=
Flutter's map canvas (flutter_map) does not natively support semantic focus traversal for screen readers, meaning map markers may be entirely invisible to VoiceOver/TalkBack users. If the accessible list fallback is not treated as a first-class view, screen reader users will have no access to the feature.
Mitigation & Contingency
Mitigation: From sprint 1, treat mentor-list-fallback as a fully featured primary view, not an afterthought. Implement and test it in parallel with the map canvas. Make the view-toggle-button keyboard focusable and announced on every screen state. Conduct VoiceOver testing on device before submitting each PR touching UI components.
Contingency: If map canvas accessibility cannot be achieved for marker focus traversal, make the view-toggle-button the default focus target on screen load for VoiceOver users (detected via screen-reader-detection-service) so they are immediately directed to the list fallback without needing to discover the toggle.
The mentor-info-popup must occupy no more than 40% of visible map area on small screens. On devices with screen heights under 667px (iPhone SE), overlapping with the filter panel or obscuring most of the map could severely degrade usability.
Mitigation & Contingency
Mitigation: Implement the popup as a bottom sheet capped at 40% of screen height with a ScrollView for overflow content. Test on iPhone SE (375x667pt) and the smallest commonly used Android form factor in the device lab. Define max-height as a percentage constant in location-privacy-config or design tokens.
Contingency: If the popup cannot fit all required fields within 40% height on smallest targets, truncate assigned contact count and certification badge to icons-only in the compact view, with a 'View Profile' button always visible at the bottom of the popup regardless of scroll position.
Filter state must remain perfectly synchronised between the map view and the list fallback. If the filter panel emits state that is not consumed identically by both views, coordinators switching between views will see inconsistent mentor sets, eroding trust in the feature.
Mitigation & Contingency
Mitigation: Store active filter criteria in a single shared Riverpod provider owned by the map-view-screen and consumed by both map-marker-widget (via mentor-location-service) and mentor-list-fallback. Write integration tests that apply a filter, switch views, and assert identical mentor counts in both views.
Contingency: If filter sync proves brittle, simplify to a single filter state object passed explicitly as a constructor argument to both views on each rebuild, eliminating indirect state sharing.