high priority low complexity testing pending testing specialist Tier 2

Acceptance Criteria

Test file exists at the expected path mirroring the source file's location under test/
Test: writeString('org_selection.selected_org_id', 'uuid-123') followed by readString returns 'uuid-123'
Test: readString on a key not set in setMockInitialValues returns null
Test: writeString then delete then readString returns null
Test: delete on a key that was never written does not throw
Test: writeInt/readInt round-trip with boundary values (0, -1, 2147483647)
Test: writeBool/readBool round-trip for both true and false
Test: writeJson/readJson round-trip with a simple Organization-like map
Test: readJson with a malformed JSON string stored via setMockInitialValues throws FormatException
Test: concurrent writes to different keys both persist correctly (use Future.wait with two simultaneous writes)
flutter test --coverage reports 100% line and branch coverage on local_storage_adapter.dart
All tests pass with flutter test on both debug and release (--release) profiles

Technical Requirements

frameworks
Flutter
flutter_test
shared_preferences
performance requirements
All tests complete in under 5 seconds total — SharedPreferences mock is synchronous-backed and should be fast
security requirements
Test fixtures must not contain real UUIDs, personal data, or production org IDs — use clearly synthetic values like 'test-org-id-001'

Execution Context

Execution Tier
Tier 2

Tier 2 - 518 tasks

Can start after Tier 1 completes

Implementation Notes

Keep the test file strictly focused on LocalStorageAdapter behavior — do not test OrgSelectionStorageKeys constants here (those have their own test per task-001). Use descriptive test names that read as sentences: test('returns null when key has not been written', ...) rather than test('readString null', ...). Group tests by method using group('readString', ...) blocks for readability. For the concurrent test, note that SharedPreferences mock in flutter_test is synchronous under the hood — the concurrency test primarily validates that the adapter does not introduce any accidental state mutation between calls.

If the adapter internally caches values, the concurrent test will catch stale-read bugs. Add a comment at the top of the test file referencing the 100% coverage requirement so future contributors know not to reduce coverage.

Testing Requirements

All tests are pure unit tests using flutter_test — no WidgetTester needed. Call SharedPreferences.setMockInitialValues({}) in setUp() to reset state between tests; do not rely on test execution order. For the concurrent write test, use Future.wait([adapter.writeString(key1, val1), adapter.writeString(key2, val2)]) and then read both keys to assert both persisted. For the FormatException test, use SharedPreferences.setMockInitialValues({'org_selection.bad_key': 'not-valid-json{{'}) and then call adapter.readJson('org_selection.bad_key', (m) => m) and expect it to throw FormatException.

Run coverage with: flutter test --coverage test/infrastructure/local_storage_adapter_test.dart and inspect lcov.info to confirm 100% branch coverage. If coverage is below 100%, identify the uncovered branch (likely a null-check or catch block) and add a targeted test case.

Component
Local Storage Adapter
infrastructure low
Epic Risks (2)
medium impact medium prob technical

SharedPreferences behaves differently on iOS (NSUserDefaults) vs Android (SharedPreferences) for edge cases such as first-launch cold reads, storage quota exceeded, or process kill mid-write. If the adapter does not account for these differences, the persistence layer can silently return null on one platform while returning a stale value on the other, causing incorrect routing decisions downstream.

Mitigation & Contingency

Mitigation: Write platform-specific integration tests using flutter_test device runners for both iOS and Android. Document known platform delta in the adapter's inline comments and encode defensive fallback for null returns at the repository boundary.

Contingency: If platform delta causes persistent issues, replace SharedPreferences with flutter_secure_storage for this key — the LocalStorageAdapter abstraction makes this a single-file swap with no impact on the repository or service layer.

high impact low prob dependency

The shared_preferences Flutter plugin may have a version conflict with other plugins already in the project pubspec.yaml. A conflict discovered late in the epic blocks all downstream epics.

Mitigation & Contingency

Mitigation: Resolve and pin the shared_preferences version in pubspec.yaml as the very first task of this epic before writing any implementation code. Run flutter pub get and resolve any version conflicts immediately.

Contingency: If version pinning is impossible due to transitive conflicts, implement LocalStorageAdapter using path_provider + dart:io for JSON file storage as an alternative — the interface contract remains unchanged.