medium priority medium complexity testing pending testing specialist Tier 8

Acceptance Criteria

Test: initial page load renders exactly the number of ActivityHistoryItem widgets matching the first page of the mock data fixture
Test: each rendered ActivityHistoryItem displays the correct date, activity type label, and duration from the fixture
Test: scrolling to 80% of the list height triggers a call to the mock service's fetchNextPage method; the next page items are appended below the existing items
Test: when the mock service returns an empty activities list, the empty-state widget (no activities message) is rendered and the list is not present in the widget tree
Test: ActivityHistoryItem widgets for activities with `isProxy == true` render the proxy audit badge widget; items with `isProxy == false` do not render the badge
Test: when a new page loads successfully, a Semantics live region node with an announcement message (e.g. '10 more activities loaded') is present in the semantics tree
Test: when fetchNextPage returns an error, an inline error indicator is shown at the bottom of the list with a retry button; existing items remain visible
Test: rapid scroll to bottom does not trigger multiple simultaneous fetchNextPage calls (debounce/guard is effective)
All tests use a FakeContactDetailService with configurable pages of activity data
Tests are deterministic and pass on both first run and repeated runs with no test ordering dependencies

Technical Requirements

frameworks
Flutter
flutter_test
BLoC
Riverpod
apis
contact-detail-service (mocked, paginated activity endpoint)
data models
ActivityHistoryItem
ActivityPage
Contact
performance requirements
Pagination trigger fires at exactly 80% scroll depth — test asserts the ScrollController threshold logic
Widget tests for list rendering complete in under 3 seconds per test
security requirements
Proxy audit badge must only appear when the activity record is explicitly flagged as proxy — no inference from other fields
Test fixtures use synthetic personal data only
ui components
ActivityHistoryList
ActivityHistoryItem
Proxy audit badge widget
Empty state widget
Pagination loading indicator
Inline pagination error widget

Execution Context

Execution Tier
Tier 8

Tier 8 - 48 tasks

Can start after Tier 7 completes

Implementation Notes

The 80% scroll threshold is typically implemented via a `ScrollController` listener comparing `scrollPosition.pixels` to `scrollPosition.maxScrollExtent * 0.8`. In tests, use `tester.drag(find.byType(ListView), Offset(0, -largeOffset))` to simulate scroll; ensure `pumpAndSettle` is called to let the scroll physics settle. For the proxy badge assertion, add a `Key('proxy-audit-badge-${activity.id}')` to the badge widget to make finder precise. For the live region test, the announcement can be implemented as a zero-size `Semantics(liveRegion: true, label: '${count} more activities loaded', child: SizedBox.shrink())` inserted into the tree when a page loads — test by checking the semantics tree after the second page resolves.

For the multi-call guard, track a boolean `_isFetching` in the cubit and assert it is reset to false only after the response arrives.

Testing Requirements

Use flutter_test with WidgetTester. Create a multi-page fixture dataset (page 1: 10 items with mix of proxy/non-proxy, page 2: 10 items, page 3: empty to signal end of list). Test pagination trigger by calling `tester.drag` on the ListView to scroll to 80% and asserting the mock service received a second call. Use `find.byType(ProxyAuditBadge)` (or equivalent key) to assert badge presence.

For live region test, use `tester.getSemantics()` after page load and check for the announcement node. For rapid-scroll debounce test, trigger two rapid drags and assert fetchNextPage was called exactly once. Coverage target: 85% on ActivityHistoryList and its cubit.

Component
Activity History List
ui low
Epic Risks (3)
medium impact medium prob scope

The encrypted-field-display confirmation dialog adds interaction steps that may frustrate coordinators who access sensitive fields frequently, leading to requests to bypass the flow or skip read-receipt logging, which would violate Blindeforbundet's compliance requirements.

Mitigation & Contingency

Mitigation: Design the confirmation dialog to be as minimal as possible (one clear sentence, single confirm action) and ensure it does not reappear for the same field within a single screen session. Validate the UX with Blindeforbundet coordinators during the TestFlight pilot before finalising.

Contingency: If coordinators raise strong objections, escalate to Blindeforbundet's data protection officer to determine whether a lighter confirmation pattern (e.g., biometric confirmation instead of dialog) satisfies their compliance obligation.

medium impact medium prob technical

The activity-history-list infinite scroll requires paginated Supabase queries. Contacts with hundreds of activities (e.g., an HLF peer mentor with 380 annual registrations) could cause slow page loads or memory pressure on older devices if pagination boundaries are set too large.

Mitigation & Contingency

Mitigation: Use a page size of 20 records with cursor-based pagination. Implement list item recycling using Flutter's ListView.builder. Benchmark memory usage with 400+ item simulation on a low-end test device before TestFlight release.

Contingency: If performance degrades on older devices, reduce page size to 10 and add a time-window filter (last 30 days, last 6 months, all) so the default view loads a manageable record count for most coordinators.

low impact high prob scope

The cognitive load rule engine (from the Cognitive Accessibility feature) mandates no more than 7 fields per screen section. If a contact model has more than 7 editable fields, the edit-contact-screen layout must be split into sections, adding complexity not accounted for in the initial scope.

Mitigation & Contingency

Mitigation: Audit the full contact field list from all four organisations before implementation. Group fields into logical sections (personal info, contact details, affiliation) so no single section exceeds 7 fields. Use the cognitive-load-rule-engine component if it is already delivered by the Cognitive Accessibility feature.

Contingency: If the rule-engine component is not yet available, implement a simple manual section layout with accordion-style expansion for less-frequently edited fields to stay within the 7-field guideline without blocking delivery.