high priority low complexity testing pending testing specialist Tier 3

Acceptance Criteria

PeriodPresetList widget test: tapping a preset item fires the onPresetSelected callback with the correct PeriodPresetIdentifier value
PeriodPresetList widget test: when the preset list is empty, an empty-state widget (not an error) is rendered
CustomDateRangePicker widget test: selecting an end date earlier than the start date renders a visible validation error message
CustomDateRangePicker widget test: selecting a valid date range updates widget state and triggers the onRangeChanged callback with the correct DateTimeRange
Both widgets: every interactive element (buttons, list items, date fields) has a minimum touch target of 44×44dp as verified via tester.getSize()
SemanticsController assertions confirm all interactive elements have non-empty semantic labels readable by TalkBack and VoiceOver
All tests pass in both light and dark mode (if theme variants exist)
Test file contains at least: 3 tests for PeriodPresetList and 4 tests for CustomDateRangePicker
No golden file dependencies — tests use finder-based assertions only for portability

Technical Requirements

frameworks
Flutter
flutter_test
Riverpod (ProviderScope wrapping in pumpWidget)
data models
activity
annual_summary
performance requirements
All widget pump operations complete within 5 seconds in CI
No async leaks — all timers and streams disposed after each test
security requirements
Tests must not reference real organisation IDs or PII — use hardcoded test UUIDs
ui components
PeriodPresetList
CustomDateRangePicker

Execution Context

Execution Tier
Tier 3

Tier 3 - 413 tasks

Can start after Tier 2 completes

Implementation Notes

Wrap each widget in a minimal ProviderScope with stubbed providers — avoid real Supabase calls. Use a FakeAsync or pumpAndSettle for any animated transitions in CustomDateRangePicker. For touch target assertions, find the GestureDetector or InkWell ancestor of each interactive element and assert tester.getSize(finder) >= Size(44, 44). Store semantic test setup in a shared setUp() block to reduce boilerplate.

If the widget uses a Riverpod AsyncValue, test both loading and data states. Prefer finder.first over index-based finders to keep tests resilient to list reordering.

Testing Requirements

Widget tests only (no integration test infrastructure needed). Use flutter_test's WidgetTester. Wrap widgets under test in a MaterialApp + ProviderScope with mocked providers (override periodPresetServiceProvider with a stub). Use SemanticsController (tester.ensureSemantics()) to verify semantic labels.

Use tester.getSize() to assert 44×44dp touch targets. Cover: happy path selection, empty state, invalid range ordering, valid range selection, and touch target sizing. Aim for 100% branch coverage of both widgets.

Component
Period Preset List Widget
ui low
Epic Risks (3)
high impact medium prob security

Supabase RLS policies for period preset configuration may be missing or incorrectly scoped, causing one organisation's presets to leak to another or write operations to fail silently.

Mitigation & Contingency

Mitigation: Define and review RLS policies for the bufdir_period_presets table in the migration file before any repository code is written. Include an integration test that verifies cross-organisation isolation using two distinct org credentials.

Contingency: If RLS is misconfigured in production, immediately disable the period preset fetch endpoint and fall back to hardcoded global presets until the policy is corrected and redeployed.

medium impact medium prob technical

The activities table may lack a composite index on (organisation_id, activity_date), causing the range count query in BufdirAggregationRepository to perform a full table scan and exceed acceptable response time for large organisations.

Mitigation & Contingency

Mitigation: Add a migration that creates a composite index on (organisation_id, activity_date) as part of this epic. Benchmark the count query against a representative dataset (10 000+ rows) before marking the epic complete.

Contingency: If query latency is unacceptable after indexing, move the count query to a Supabase RPC function that leverages a materialised view or partial index, accepting a slight staleness window.

medium impact medium prob technical

Flutter's native date picker widgets have known accessibility gaps (missing semantic labels, non-standard focus traversal) that may prevent WCAG 2.2 AA compliance out of the box, requiring a custom implementation.

Mitigation & Contingency

Mitigation: Evaluate third-party accessible date picker packages (e.g., table_calendar with custom semantics) against WCAG 2.2 AA criteria before beginning implementation. Document the chosen approach in the epic kick-off.

Contingency: If no package meets accessibility requirements, implement a simple text-field-based date entry with explicit semantic labels and format hints as an accessible fallback, deferring a fully visual calendar to a later iteration.