high priority medium complexity testing pending testing specialist Tier 7

Acceptance Criteria

Test: pumping the widget with a provider that returns 3 active ActivityTypes renders exactly 3 list items with the correct resolved label text for each
Test: inactive ActivityTypes included in the provider response are NOT rendered in the list
Test: tapping an ActivityType list item triggers the onSelected callback with the complete ActivityType object including all metadata fields (id, name, triggersReimbursementWorkflow, isTravelExpenseEligible, isActive)
Test: while the provider is in loading state, exactly one CircularProgressIndicator is visible and no list items are rendered
Test: when the provider emits an AsyncError, a retry button or tappable error message is visible
Test: tapping the retry element triggers a provider refresh (verified via mock interaction or by transitioning to loading state)
Test: all list items have a Semantics label present (verified via tester.getSemantics())
Test: the screen title or header text is correctly rendered
All tests use ProviderScope with overrides — no global state leaks between tests
Tests cover both portrait and landscape orientations for layout regression

Technical Requirements

frameworks
Flutter
Riverpod
flutter_test
mocktail
data models
ActivityType
performance requirements
Each widget test pump must complete within 2 seconds including all async resolution
ui components
ActivityTypeSelectionScreen
CircularProgressIndicator
Retry button or error widget
List item widgets with Semantics

Execution Context

Execution Tier
Tier 7

Tier 7 - 84 tasks

Can start after Tier 6 completes

Implementation Notes

Override the activityTypesProvider (or equivalent Riverpod provider) in each test's ProviderScope to return controlled AsyncValue states. For the tap callback test, pass a closure to the onSelected parameter that assigns to a nullable ActivityType local variable, then assert it equals the expected object after tester.tap() and tester.pump(). For semantics tests, call tester.ensureSemantics() before pumping then dispose SemanticsHandle in tearDown. For orientation tests, use tester.binding.setSurfaceSize() to simulate landscape dimensions.

Avoid testing internal implementation details — test observable behavior only (what is rendered, what callback is called).

Testing Requirements

Flutter widget tests using flutter_test. Wrap each test in a ProviderScope with explicit provider overrides returning AsyncValue.data(), AsyncValue.loading(), or AsyncValue.error() as needed. Use tester.pumpWidget() and tester.pumpAndSettle(). Use find.byType(), find.text(), and find.bySemanticsLabel() for assertions.

For tap tests, capture the callback argument using a local variable assigned in a closure passed to onSelected. Test semantics using tester.ensureSemantics() and tester.getSemantics(find.byType(ListTile)). No real network calls or database connections.

Epic Risks (2)
medium impact medium prob scope

Metadata flag combination rules differ between organisations (e.g., Blindeforbundet honorarium thresholds, HLF mutual exclusion of km and transit). Encoding these as generic service-level validation may be insufficient, forcing organisation-specific branching inside the service that becomes unmaintainable as new organisations are onboarded.

Mitigation & Contingency

Mitigation: Model flag validation as a pure function that accepts an ActivityTypeMetadata object and an org configuration record, making org-specific rules data-driven rather than hardcoded. Establish the validation contract in the foundation epic so the service just delegates to the validator.

Contingency: Defer complex cross-flag validation to a lightweight edge function that can be updated without a mobile app release, accepting that initial validation in the mobile service layer is permissive and corrected server-side.

high impact low prob technical

Blindeforbundet users rely on VoiceOver and JAWS. If the selection screen is built with non-semantic widgets that fail accessibility audit late in the sprint, a significant rework of the widget tree may be required, blocking the registration wizard integration.

Mitigation & Contingency

Mitigation: Build the selection screen against the project's established accessibility design tokens and semantics wrapper conventions from the start. Run Flutter's semantic tree inspector and a manual VoiceOver pass before marking any widget task complete.

Contingency: Wrap all tappable items in the project's SemanticsWrapperWidget and schedule a dedicated accessibility review session with a screen reader user from Blindeforbundet before the epic is closed.