high priority medium complexity testing pending testing specialist Tier 5

Acceptance Criteria

Unit tests for field-encryption-utils cover encrypt/decrypt round-trip: encrypted value differs from plaintext, decrypted value matches original input
Unit tests cover error cases: decryption with wrong key throws typed EncryptionError, null/empty input handled without crash
Widget test: EncryptedFieldDisplay renders in masked state on initial mount (plaintext not visible in widget tree)
Widget test: tapping reveal button opens confirmation dialog; confirming dialog transitions widget to revealed state showing plaintext
Widget test: live region (Semantics node with liveRegion: true) announces field reveal via screen reader
Widget test: after configurable timeout (default 30s), widget automatically reverts to masked state without user interaction
Widget test: read-receipt service mock is invoked exactly once when field transitions to revealed state
Widget test: read-receipt service is NOT invoked when widget is constructed or when it re-masks
Line coverage for EncryptedFieldDisplay widget file is at or above 90% as reported by flutter test --coverage
All tests pass in CI with flutter_test package; no skipped or flaky tests

Technical Requirements

frameworks
Flutter
flutter_test
Riverpod
data models
EncryptedField
ReadReceiptRecord
performance requirements
All widget tests complete within 10 seconds total
No real async timers — use fake async (FakeAsync) for timeout testing
security requirements
Plaintext values must never appear in widget tree in masked state — assert via find.text(plaintext) returns zero matches
Encryption key material must not be logged in test output
ui components
EncryptedFieldDisplay
RevealConfirmationDialog

Execution Context

Execution Tier
Tier 5

Tier 5 - 253 tasks

Can start after Tier 4 completes

Implementation Notes

Use `flutter_test`'s `FakeAsync` (via `fake_async` package or `tester.pump(Duration(...))`) to simulate the re-mask timeout — never rely on real `Future.delayed` in widget tests. Inject the read-receipt service as a Riverpod provider override so tests remain hermetic. For the live region assertion, use `tester.getSemantics(find.byType(EncryptedFieldDisplay))` and check `SemanticsFlag.isLiveRegion`. Ensure the reveal dialog is a separate widget so it can be found independently.

For coverage, generate lcov with `flutter test --coverage` and check `coverage/lcov.info` — focus on branch coverage for the timeout and error paths. Avoid testing Supabase or network code here; those belong in integration tests.

Testing Requirements

Unit tests (flutter_test): field-encryption-utils encrypt/decrypt round-trip with valid and invalid keys, null/empty input edge cases, wrong-key decryption error type. Widget tests (flutter_test + WidgetTester): use pumpWidget with ProviderScope to inject mock read-receipt service via Riverpod override. Use FakeAsync to advance time for re-mask timeout without real waiting. Assert Semantics tree for live region node.

Verify mock invocation count with a simple counter or Mockito. Target 90%+ line coverage on the widget file; run `flutter test --coverage` and inspect lcov report. Group tests clearly: 'field-encryption-utils', 'EncryptedFieldDisplay — masked state', 'EncryptedFieldDisplay — reveal flow', 'EncryptedFieldDisplay — timeout', 'EncryptedFieldDisplay — read receipt'.

Component
Encrypted Field Display Widget
ui high
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.