high priority low complexity testing pending testing specialist Tier 4

Acceptance Criteria

Test suite contains at least 10 distinct widget tests covering all documented scenarios
Logo display test verifies Image widget renders when logoUrl is provided and non-null
Placeholder fallback test verifies a fallback icon/initials widget renders when logoUrl is null or empty
Name truncation test verifies text overflow is handled (ellipsis or maxLines) when org name exceeds card width
Active-state border test verifies a visible border or highlight is applied when isActive=true and absent when isActive=false
Tap callback test verifies onTap callback is invoked exactly once when the card is tapped using tester.tap()
Semantic label test verifies Semantics widget wraps the card and label matches org name and active state
Screen-reader test uses SemanticsHandle/SemanticsController to verify VoiceOver/TalkBack would announce the card correctly
Touch target test verifies the tappable area is at minimum 48x48 logical pixels using tester.getSize()
WCAG contrast test verifies foreground text color against background using design token values meets 4.5:1 ratio for normal text
All tests pass with flutter test --no-pub with zero failures
No golden file dependencies — tests use semantic and size assertions only

Technical Requirements

frameworks
Flutter
flutter_test
data models
Organization
OrgBrandingTokens
performance requirements
All widget tests complete within 30 seconds total
No network calls during tests — all external dependencies mocked
security requirements
No real org data or credentials used in test fixtures — use synthetic test data only
ui components
OrgCardWidget
Semantics
GestureDetector or InkWell (tap target)
Image or NetworkImage (logo)
Text (name with overflow)

Execution Context

Execution Tier
Tier 4

Tier 4 - 323 tasks

Can start after Tier 3 completes

Implementation Notes

Use pumpWidget with a MaterialApp wrapper to ensure theme and directionality are available. Stub any OrgBrandingCache or repository calls using a fake implementation injected via constructor or provider override. For contrast ratio assertion, implement a helper: double contrastRatio(Color fg, Color bg) using the WCAG relative luminance formula. The 48dp touch target check: Flutter's Material guidelines recommend 48x48dp minimum — verify via tester.getSize() and assert >= Size(48, 48).

For semantic label test, use tester.getSemantics(find.byType(OrgCardWidget)) and assert label contains org name. Keep test file co-located with widget: test/widgets/org_card_widget_test.dart.

Testing Requirements

Widget tests only (no integration test runner required). Use WidgetTester from flutter_test. Mock image loading with a stub NetworkImage or use a MemoryImage. Use SemanticsHandle to inspect the semantic tree.

Verify touch target size via tester.getSize(find.byType(OrgCardWidget)). For contrast ratio: extract design token color values and compute luminance ratio in test assertions (helper function recommended). Test both isActive=true and isActive=false states. Test with a short org name (<20 chars) and a long org name (>40 chars).

Coverage target: 100% of OrgCardWidget's public API surface.

Component
Organization Card Widget
ui low
Epic Risks (3)
high impact medium prob technical

iOS Keychain and Android Keystore have meaningfully different failure modes and permission models. The secure storage plugin may throw platform-specific exceptions (e.g., biometric enrollment required, Keystore wipe after device re-enrolment) that crash higher-level flows if not caught at the adapter boundary.

Mitigation & Contingency

Mitigation: Wrap all storage plugin calls in try/catch at the adapter layer and expose a typed StorageResult<T> instead of throwing. Write integration tests on real device simulators for both platforms in CI using Fastlane. Document the exception matrix during spike.

Contingency: If a platform-specific failure cannot be handled gracefully, fall back to in-memory-only storage for the current session and surface a non-blocking warning to the user; log the event for investigation.

high impact medium prob integration

Setting a session-level Postgres variable (app.current_org_id) via a Supabase RPC requires that RLS policies on every table reference this variable. If the Supabase project schema has not yet defined these policies, the configurator will set the variable but queries will return unfiltered data, giving a false sense of security.

Mitigation & Contingency

Mitigation: Include a smoke-test RPC in the SupabaseRLSTenantConfigurator that verifies the variable is readable from a policy-scoped query before marking setup as complete. Coordinate with the database migration task to ensure RLS policies reference app.current_org_id before the configurator is shipped.

Contingency: If RLS policies are not in place at integration time, gate all data-fetching components behind a runtime check in SupabaseRLSTenantConfigurator.isRlsScopeVerified(); block data access and surface a developer warning until policies are confirmed.

medium impact medium prob technical

Fetching feature flags from Supabase on every cold start adds network latency before the first branded screen renders. On slow connections this may cause a perceptible blank-screen gap or cause the app to render with default (unflagged) state before flags arrive.

Mitigation & Contingency

Mitigation: Persist the last-known flag set to disk in the FeatureFlagProvider and serve stale-while-revalidate on startup. Gate flag refresh behind a configurable TTL (default 15 minutes) so network calls are not made on every launch.

Contingency: If stale flags cause a feature to appear that should be hidden, add a post-load re-evaluation pass that reconciles the live flag set with the rendered widget tree and triggers a targeted rebuild where needed.