high priority high complexity testing pending testing specialist Tier 5

Acceptance Criteria

All widget tests pass in CI with no flaky failures across 3 consecutive runs
Test coverage for BufdirExportScreen and its child cubits is at or above 85% line coverage
Widget test: selecting scope and period enables the 'Preview' button and triggers a fetchPreview() call (verified via mock cubit state transitions)
Widget test: preview panel renders at least one category row with correct record count from mock data
Widget test: unmapped activity warning section is visible when preview data contains unmapped types
Widget test: 'Confirm Export' button is absent when preview has blocking errors
Widget test: tapping 'Confirm Export' opens ExportConfirmationDialog
Widget test: confirming the dialog shows ExportProgressIndicator while export is in progress
Widget test: export success renders completion card and invokes FileDownloadHandler mock
Widget test: export failure renders inline error message with 'Retry' button
Widget test: tapping 'Back to Configuration' from Preview phase returns to Configuration and resets preview state
Accessibility test: ExportReadinessBanner liveRegion announcement fires at each phase transition (verified via SemanticsController)
Accessibility test: all interactive elements have non-empty Semantics labels
Integration test (optional, runs on real device via TestFlight): full happy path — scope selection → period selection → preview load → confirm → download

Technical Requirements

frameworks
Flutter
flutter_test
BLoC (flutter_bloc)
Riverpod
bloc_test
apis
Mocked Bufdir Preview API
Mocked Bufdir Export API
Mocked FileDownloadHandler
data models
ExportScreenState
ExportPreviewResult
ExportJobStatus
ExportReadinessStatus
performance requirements
Full widget test suite must complete in under 60 seconds in CI
No individual test may take longer than 10 seconds (use fake async / pumpAndSettle with timeout)
security requirements
Tests must not make real HTTP calls — all network dependencies must be mocked or faked
No real Supabase credentials or API keys may appear in test files
ui components
BufdirExportScreen (system under test)
Mock ExportScreenCubit
Mock ExportPreviewCubit
Mock BufdirExportService
Mock FileDownloadHandler
Accessibility test harness (SemanticsController)

Execution Context

Execution Tier
Tier 5

Tier 5 - 253 tasks

Can start after Tier 4 completes

Implementation Notes

Use fakeAsync and pump(Duration) instead of pumpAndSettle() everywhere streams or timers are involved — pumpAndSettle times out when streams never complete. For BLoC-dependent widget tests, provide a pre-seeded MockCubit using the whenListen pattern from bloc_test so you can control exact state sequences. For Riverpod overrides, use ProviderScope with overrides: [] in each test's pumpWidget call. The accessibility test harness should call tester.ensureSemantics() at the start of each accessibility test and dispose the SemanticsHandle at the end.

For the live-region announcement test, listen to SemanticsController.onSemanticsUpdate and assert that an announcement containing the expected readiness text was fired after the phase transition pump.

Testing Requirements

Use flutter_test with WidgetTester for all widget-level tests. Use bloc_test's emitsInOrder for cubit state transition assertions. Use mocktail (preferred) or mockito for service and handler mocks. Organise tests in a single test file per major flow: export_screen_configuration_test.dart, export_screen_preview_test.dart, export_screen_execution_test.dart, export_screen_accessibility_test.dart.

Integration test targeting a physical iOS device via TestFlight should be in integration_test/bufdir_export_flow_test.dart and gated behind a CI environment variable so it does not run on every PR.

Component
Bufdir Export Screen
ui medium
Dependencies (3)
Add an ExportReadinessBanner widget at the top of BufdirExportScreen that computes and displays overall export readiness based on: (1) whether a valid scope is selected, (2) whether a valid period is selected, (3) whether the preview loaded without blocking errors, and (4) whether any unmapped activity warnings are present. Use green/amber/red status icons from the contrast-safe colour palette. The banner must announce status changes via a live region so screen reader users hear readiness updates without manually navigating. epic-bufdir-report-export-user-interface-task-011 In BufdirExportScreen's Execution phase, show the ExportConfirmationDialog when the user taps 'Confirm Export'. On confirmation, invoke BufdirExportService.startExport() and transition to the progress sub-phase displaying ExportProgressIndicator. Handle success by transitioning to a completion state that shows a download prompt via FileDownloadHandler. Handle failure with a plain-language error message and a 'Retry' option that stays in the Execution phase. epic-bufdir-report-export-user-interface-task-010 Audit the completed ExportPreviewPanel widget against WCAG 2.2 AA criteria: ensure all interactive and informational elements have semantic labels via Semantics or MergeSemantics; verify colour contrast ratios meet 4.5:1 for normal text and 3:1 for large text using the contrast-ratio-validator; confirm touch targets are minimum 44Ă—44dp; add live-region announcements for state changes (loading complete, warnings appeared); validate with flutter_test accessibility matchers and the accessibility-test-harness. epic-bufdir-report-export-user-interface-task-006
Epic Risks (2)
medium impact medium prob technical

The preview panel requires a round-trip to the edge function to compute aggregated counts. If this call takes 5–15 seconds for large scopes, users may assume the app has frozen and navigate away, potentially triggering duplicate preview requests or leaving the export in an undefined state.

Mitigation & Contingency

Mitigation: Show an immediate skeleton loading state on the preview panel as soon as the period and scope are confirmed, with named stage labels (e.g. 'Querying activities…', 'Computing totals…') streamed from the edge function's progress events. Set a clear user-visible timeout with a retry option. Pre-warm the edge function with a lightweight ping when the scope selector is opened.

Contingency: If preview latency consistently exceeds 10 seconds for large scopes, cache the preview payload in local BLoC state and allow the coordinator to proceed to confirmation without re-fetching if scope and period have not changed since the last preview.

high impact medium prob scope

The export preview panel contains dynamic content (warning badges, loading skeletons, aggregated counts) that must be announced correctly by VoiceOver and TalkBack. Incorrect semantics annotations could make the preview unreadable for blind coordinators, violating the project's WCAG 2.2 AA accessibility mandate.

Mitigation & Contingency

Mitigation: Implement semantic annotations using Flutter's Semantics widget with explicit labels for all dynamic content. Use live region announcements for loading state transitions. Schedule a dedicated accessibility review session with a screen reader user (Blindeforbundet has relevant expertise) before marking the epic complete.

Contingency: If the preview panel cannot be made fully screen-reader-accessible in time for launch, ship a simplified text-only summary mode activated by a toggle at the top of the preview panel, which renders all data as a single readable paragraph with no interactive badges.