high priority medium complexity testing pending testing specialist Tier 4

Acceptance Criteria

ContactSearchBar test: typing text and advancing fake async by 299ms does NOT fire the onChanged debounce callback
ContactSearchBar test: typing text and advancing fake async by 300ms DOES fire the onChanged debounce callback with the correct query string
ContactSearchBar test: tapping the clear button resets the text field value to empty and fires onChanged with an empty string
ContactSearchBar test: Semantics widget wraps the input with a non-empty label and hint
ContactViewSwitcher test: tapping each tab calls onChanged with the correct ContactViewType enum value
ContactViewSwitcher test: rendering with alternate org-label strings shows the overridden tab labels
ContactViewSwitcher test: when the visibility flag is false, the widget renders as SizedBox.shrink or is absent from the tree
ContactListScreen integration test: coordinator role renders coordinator-specific UI elements
ContactListScreen integration test: peer mentor role renders peer-mentor-specific UI elements
ContactListScreen integration test: entering a search query filters the displayed card list to only matching items
ContactListScreen integration test: empty state widget appears when search query matches zero items
All tests pass under flutter test with no skipped assertions or test timeouts

Technical Requirements

frameworks
Flutter
flutter_test
BLoC
Riverpod
data models
Contact
PeerMentor
OrgLabels
UserRole
performance requirements
Integration tests must complete within 10 seconds per test case
ui components
ContactSearchBar
ContactViewSwitcher
ContactListScreen
ContactCardWidget
PeerMentorCardWidget

Execution Context

Execution Tier
Tier 4

Tier 4 - 323 tasks

Can start after Tier 3 completes

Implementation Notes

Debounce tests are the trickiest part: wrap the WidgetTester pump sequence inside fakeAsync, type into the field with tester.enterText, then call fakeAsync.elapse(Duration(milliseconds: 299)) and assert callback NOT called, then elapse 1ms more and assert called. For ContactViewSwitcher visibility test, pass visible: false and assert find.byType(ContactViewSwitcher).evaluate().isEmpty or that it has zero size. Integration tests should use a FakeContactRepository injected via Riverpod ProviderScope.overrides or BLoC dependency injection — never hit Supabase. Keep fixtures in a shared test/fixtures/ directory so all test files import from the same source.

Use pump and settle carefully — avoid pumpAndSettle timeouts on animated widgets by using pump(Duration(milliseconds: 300)) instead.

Testing Requirements

Split tests across three files: contact_search_bar_test.dart, contact_view_switcher_test.dart, contact_list_screen_integration_test.dart. Use fakeAsync and FakeTimers from flutter_test to control debounce timing — do not use real delays. For integration tests, override the Riverpod/BLoC provider with a mock repository that returns fixtures from task-001. Test role-aware rendering by injecting different UserRole values via provider override.

Verify filter behaviour by asserting findsNWidgets count before and after entering a query. Run all tests headlessly with flutter test — no device required.

Component
Contact List Screen
ui medium
Epic Risks (2)
medium impact medium prob technical

Design token color values used in role badges, certification status indicators, and availability chips may not meet the WCAG 2.2 AA contrast ratio of 4.5:1 when rendered against card backgrounds, requiring rework after accessibility review and potentially blocking acceptance sign-off.

Mitigation & Contingency

Mitigation: Run the contrast-ratio-validator on every new token combination during widget development. Enforce the CI accessibility lint runner on all PRs touching visualization components, and validate against the contrast-safe-color-palette before finalizing card designs.

Contingency: If contrast failures are found late, adjust token values in the design token theme centrally — since all widgets consume design tokens rather than hardcoded colors, all affected widgets will be corrected by a single token update without per-widget changes.

low impact medium prob dependency

The ContactViewSwitcher is required for Barnekreftforeningen but must not appear for other organizations. If the organization labels provider does not yet expose a reliable feature flag for this widget, it may render universally or be conditionally hidden in an inconsistent way, breaking the role-specific layout contract.

Mitigation & Contingency

Mitigation: Implement view switcher visibility as a constructor parameter on ContactListScreen injected from a provider, defaulting to hidden. Document the integration point for the org labels provider so the flag can be wired without changing the widget's API.

Contingency: If org labels integration is delayed beyond this epic, use a feature flag constant keyed to the Barnekreftforeningen organization ID as a temporary gate, with a tracked issue to replace it with the runtime labels provider before general release.