high priority medium complexity testing pending testing specialist Tier 6

Acceptance Criteria

BufdirFieldRowWidget test suite covers: valid state (no icon, correct label semantics), error state (error icon present, tooltip with issueMessage, color matches errorForeground token), warning state (warning icon present, tooltip with issueMessage, color matches warningForeground token)
BufdirReportSectionWidget test suite covers: initial collapsed state (content not in tree), tap header expands (content in tree), tap again collapses, heading semantics node has correct heading level
BufdirValidationSummaryBanner test suite covers: isEmpty true → banner not visible after animation; isEmpty false → banner visible with correct counts; filter toggle 'Errors' only → warning rows absent; filter toggle 'Warnings' only → error rows absent; both toggles off → all rows present
BufdirValidationSummaryBanner live-region test: inject mock SemanticsService, update provider state with new errors, assert announce() called with assertive-equivalent string
Golden tests generated for: BufdirFieldRowWidget in all 3 validation states at 1x and 2x font scale; BufdirValidationSummaryBanner expanded with mixed issues; BufdirReportSectionWidget expanded with 3 field rows
All golden tests use a controlled ThemeData with explicit design token color values — no system theme dependency
All tests pass with flutter test --platform chrome for layout consistency checks
Test file follows the one-describe-per-widget convention with nested group() blocks per scenario
No test uses sleep() or manual delays — all async operations use tester.pumpAndSettle()
CI-ready: tests runnable with flutter test with no additional setup beyond flutter pub get

Technical Requirements

frameworks
Flutter
Riverpod
flutter_test
data models
bufdir_column_schema
bufdir_export_audit_log
performance requirements
Full test suite completes in under 60 seconds on standard CI runner
Golden file generation uses a fixed pixel ratio (2.0) for reproducibility across machines
security requirements
No real Supabase credentials used in tests — all providers mocked via ProviderScope overrides
No network calls made during widget tests — use fake implementations only
ui components
BufdirFieldRowWidget
BufdirReportSectionWidget
BufdirValidationSummaryBanner

Execution Context

Execution Tier
Tier 6

Tier 6 - 158 tasks

Can start after Tier 5 completes

Implementation Notes

Organize test files mirroring source structure: test/features/bufdir/widgets/bufdir_field_row_widget_test.dart, bufdir_report_section_widget_test.dart, bufdir_validation_summary_banner_test.dart. Use a shared test_helpers.dart file for common fixtures: buildTestApp() wrapper with ProviderScope + MaterialApp + Directionality, sampleValidationSummaryData() factory, sampleSectionData() factory. For golden tests, set window.physicalSize and window.devicePixelRatio explicitly before pumping to ensure consistent output. Place golden files in test/goldens/bufdir/ and commit them.

For SemanticsService announcement testing, subclass SemanticsService and inject via a Riverpod override or use Flutter's test binding's SemanticsBinding. Document any known TalkBack/VoiceOver behavior differences in a test README.

Testing Requirements

This task IS the testing task. Structure: (1) Unit tests for model classes (task-006 models) — pure Dart, no widget tree; (2) Widget tests for each component in isolation using pumpWidget + ProviderScope with overrides; (3) Golden tests using matchesGoldenFile — run flutter test --update-goldens once to generate baselines, then CI runs without --update-goldens flag; (4) Semantics tests using tester.getSemantics() to assert label and heading level; (5) Interaction tests using tester.tap() and tester.pump() for expand/collapse and filter toggles; (6) Announce tests using a fake SemanticsService injected via Riverpod override. Target: 100% branch coverage on all three widget classes.

Component
Bufdir Field Row Widget
ui medium
Epic Risks (2)
high impact medium prob technical

Implementing the tap-to-scroll-and-focus behavior from the validation banner to a specific field row in a long scrollable list is complex in Flutter. If focus management is incorrectly implemented, VoiceOver users who navigate to the banner and select an issue will not be moved to the relevant field row, breaking the accessibility workflow and violating WCAG 2.4.3 (Focus Order).

Mitigation & Contingency

Mitigation: Use BufdirAccessibilityUtils focus management utilities (built in the foundation epic) with explicit GlobalKey-based scroll anchors on each field row. Test with a real iOS device running VoiceOver during widget development, not only in the Flutter accessibility inspector.

Contingency: If programmatic scroll-to-focus cannot be reliably achieved before the TestFlight deadline, fall back to a navigation approach where tapping a banner issue opens a modal detail sheet for that field row rather than scrolling in place, and file a follow-up ticket for the inline scroll implementation.

medium impact low prob technical

The validation summary banner must reactively update its issue count as underlying aggregated data changes (e.g., if the coordinator has navigated away and data was refreshed). If the banner's Riverpod provider is not correctly scoped, it may display stale issue counts or fail to disappear when all issues are resolved, eroding coordinator trust in the validation system.

Mitigation & Contingency

Mitigation: Drive the banner exclusively from the same Riverpod provider that powers the full preview model — do not maintain a separate local state for issue counts. Write a widget test that simulates a data refresh mid-review and asserts the banner updates within one frame.

Contingency: If stale state reaches production, add a manual refresh button to the banner as a short-term workaround while the provider scoping is corrected in the next release cycle.