high priority low complexity testing pending testing specialist Tier 6

Acceptance Criteria

Test suite contains at least 8 distinct test cases covering all documented lifecycle phases
loadOrganizations() test asserts the returned list matches the mocked Supabase response exactly (id, displayName, logoUrl fields)
selectOrganization() test verifies OrgPersistenceRepository.save() is called once with the correct org id
getSelectedOrganization() cold-start test confirms that on service construction the persisted id is read from OrgPersistenceRepository and the matching Organization object is returned
getSelectedOrganization() returns null when OrgPersistenceRepository returns null (no prior selection)
clearSelection() test verifies OrgPersistenceRepository.clear() is called and subsequent getSelectedOrganization() returns null
Post-selection initialization test verifies that after selectOrganization() the label provider refresh method is called exactly once
All tests pass with flutter_test and produce zero analyzer warnings
OrgPersistenceRepository and SupabaseClient are fully mocked — no real I/O occurs
Test file is located under test/ mirroring the lib/ directory structure

Technical Requirements

frameworks
flutter_test
mockito or mocktail for Dart mocks
Riverpod (ProviderContainer for service instantiation)
apis
OrgPersistenceRepository interface
Supabase client mock
data models
Organization (id, displayName, logoUrl, isSelected)
OrgSelectionService
OrgPersistenceRepository
performance requirements
All tests must complete in under 2 seconds total
No async leaks — all futures must be awaited or fakeAsync-wrapped
security requirements
No real Supabase credentials used in tests
No org IDs or personal data hardcoded — use fixture constants

Execution Context

Execution Tier
Tier 6

Tier 6 - 158 tasks

Can start after Tier 5 completes

Implementation Notes

Instantiate OrgSelectionService inside ProviderContainer so Riverpod dependency injection mirrors production wiring. Stub OrgPersistenceRepository as an interface mock — do not use the concrete implementation. For the cold-start scenario, construct the service after setting up the persistence mock to return a stored id, then assert the service exposes the correct Organization on first access without an explicit selectOrganization() call. The post-selection label provider refresh assertion depends on how OrgSelectionService notifies OrgLabelsProvider; if via a Riverpod ref.invalidate() call, capture the ref using a spy ProviderContainer.

Keep fixture data in a separate test/fixtures/org_fixtures.dart file to share across test-009 and test-010.

Testing Requirements

Unit tests only using flutter_test. Use setUp() to construct a fresh service instance per test to prevent state leakage. Apply mockito/mocktail to stub OrgPersistenceRepository.load(), save(), and clear(), and the Supabase client list response. Use fakeAsync + pump() for any stream-based assertions.

Group tests into describe-style group() blocks: 'loadOrganizations', 'selectOrganization', 'getSelectedOrganization', 'clearSelection', 'post-selection side-effects'. Assert call counts with verify() to confirm no unexpected interactions. Aim for 100% branch coverage of OrgSelectionService public methods.

Component
Organization Selection Service
service low
Epic Risks (2)
high impact medium prob technical

The OrgLabelsProvider must be fully initialized before any UI widget renders organization-specific text. If the service triggers label initialization asynchronously and the UI builds before the labels stream emits, widgets will briefly display raw label keys instead of human-readable text, which constitutes a WCAG 2.2 AA failure for screen readers that announce whatever text is present at render time.

Mitigation & Contingency

Mitigation: Design the OrgSelectionService.select() method to await OrgLabelsProvider initialization before completing its Future — callers receive a resolved future only after labels are ready. Use an AsyncValue loading state to gate UI rendering via Riverpod's when() pattern.

Contingency: If awaiting initialization causes perceivable UI lag, implement an optimistic render with a skeleton loading state that is announced by the live-region-announcer as 'Loading organization content' so screen readers do not announce raw keys.

medium impact medium prob integration

If the label definitions loaded from the backend for each organization do not match the label key registry used in the UI, widgets will fall back to raw keys silently. This is particularly harmful for Blindeforbundet users relying on VoiceOver, where a raw key announced by a screen reader is incomprehensible.

Mitigation & Contingency

Mitigation: Define a compile-time label key registry (enum or const strings) and assert at OrgLabelsProvider initialization that all required keys are present in the loaded map. Log a structured warning for any missing key and substitute a human-readable fallback string rather than the raw key.

Contingency: If a label schema mismatch reaches production, the OrgLabelsProvider fallback mechanism ensures users see a reasonable English default rather than a raw key. A backend label patch can be deployed without an app release.