medium priority low complexity testing pending testing specialist Tier 4

Acceptance Criteria

All widget tests are located in `test/widgets/contact/` following existing test file conventions
MultiChapterAffiliationChip read-only test: renders correct number of chips for a 3-chapter input list
MultiChapterAffiliationChip edit mode test: tapping an unselected chapter fires onSelectionChanged with that chapter added
MultiChapterAffiliationChip cap test: when 5 chapters are already selected, tapping a 6th chapter does NOT fire onSelectionChanged
MultiChapterAffiliationChip cap test: inline warning banner widget is present in tree when selection count equals 5
MultiChapterAffiliationChip empty state test: renders empty-state widget when availableChapters list is empty
AssignmentStatusIndicator test: renders with correct background color token for each of the three statuses (active, pending, inactive)
AssignmentStatusIndicator test: org label override replaces default label text correctly
AssignmentStatusIndicator semantic test: `Semantics` widget exposes a meaningful label readable by screen readers
Golden snapshot tests cover: chip in read-only (3 chapters), chip in edit-mode at cap (5 selected), status indicator in all 3 states
All tests pass with `flutter test` in CI with no flakiness (no `pumpAndSettle` with arbitrary durations)
`flutter test --coverage` reports >= 90% line coverage for both widget files

Technical Requirements

frameworks
Flutter
flutter_test
data models
ChapterId
ChapterAffiliation
AssignmentStatus
performance requirements
Each test file must run in under 10 seconds on CI
Golden snapshots must use a fixed test device size (e.g., iPhone 14 logical resolution) declared in test setup
security requirements
Test data must use anonymized/synthetic chapter names and IDs — no real member data in test fixtures
ui components
MultiChapterAffiliationChip
AssignmentStatusIndicator
WidgetTester pump helpers

Execution Context

Execution Tier
Tier 4

Tier 4 - 323 tasks

Can start after Tier 3 completes

Implementation Notes

Create a shared `test_helpers.dart` in `test/widgets/contact/` that builds a minimal MaterialApp wrapper with design token theme applied — do not repeat this boilerplate in every test file. Use a `FakeChapterRepository` stub (simple in-memory list) rather than mocking Supabase — these are pure widget tests and must not hit the network. For the cap enforcement test, build the widget with `selectedIds` already containing 5 items and assert `IgnorePointer` is active using `tester.widget(find.byType(IgnorePointer)).ignoring == true`. For semantic tests, wrap in `withSemantics: true` in `pumpWidget` options and use `SemanticsController`.

Golden snapshot CI setup: ensure `--dart-define=FLUTTER_TEST_GOLDENS=true` flag is used in CI to skip golden updates and only verify. Document how to update goldens locally in a comment block at the top of each golden test file.

Testing Requirements

This task IS the testing task. Use `flutter_test` exclusively — no third-party test libraries. Structure tests with clearly named `group()` blocks per widget and `testWidgets()` per scenario. Use `find.byType`, `find.text`, and `find.byKey` for locating widgets.

Prefer `pump()` over `pumpAndSettle()` for synchronous widget operations. For golden tests, use `matchesGoldenFile` and store snapshots in `test/goldens/`. Run `flutter test --update-goldens` only when intentionally updating; goldens must be committed and reviewed in PRs. Accessibility tests should use `tester.getSemantics()` to assert meaningful `SemanticsNode` labels.

Epic Risks (3)
high impact medium prob security

Blindeforbundet's encryption key retrieval mechanism may not be finalised at implementation time, or session key availability via Supabase RLS may be inconsistent, causing decryption failures that expose masked placeholders to users and degrade the experience.

Mitigation & Contingency

Mitigation: Agree with Blindeforbundet on key storage and retrieval contract before implementation starts. Prototype key retrieval in a spike against the staging Supabase instance and validate the full decrypt/verify cycle with real test data before committing to the implementation.

Contingency: Implement a fallback that shows a 'field temporarily unavailable' state with a retry affordance. Log decryption failures server-side for audit. Escalate to Blindeforbundet stakeholders to unblock key management before the service tier epic begins.

medium impact medium prob technical

NHF contacts may belong to up to 5 chapters, each governed by separate RLS policies. A coordinator's chapter scope may not cover all affiliations, causing partial profile reads or silent data omissions that are difficult to detect in tests.

Mitigation & Contingency

Mitigation: Map all RLS policy combinations for multi-chapter contacts early. Write integration tests that create contacts with 5 affiliations and query them from coordinators with varying chapter scopes. Use Supabase's RLS test utilities to verify row visibility per role.

Contingency: Add an explicit 'affiliation partially visible' state in the repository response model so the UI can communicate scope limitations to the coordinator rather than silently showing incomplete data.

low impact medium prob scope

Organisation-specific validation rules (e.g., NHF chapter limit, Blindeforbundet encrypted field edit flow) may expand in scope during implementation as edge cases are discovered, causing the validator to grow beyond the planned complexity.

Mitigation & Contingency

Mitigation: Define the complete validation rule set with product and org stakeholders before coding begins. Document each rule with its source organisation and acceptance test. Use a rule registry pattern so new rules can be added without modifying core validator logic.

Contingency: Timebox validator enhancements to 2 hours per additional rule. Defer non-blocking rules to a follow-on maintenance task rather than blocking the epic delivery.