high priority medium complexity testing pending testing specialist Tier 8

Acceptance Criteria

Unit tests exist for every organisation (NHF, Blindeforbundet, HLF, Barnekreftforeningen) × every brightness (light, dark) = 8 ColorScheme mapping test cases — each asserts that every ColorScheme slot (primary, onPrimary, surface, onSurface, error, onError, etc.) contains the expected hex value from the design token source
Unit tests exist asserting that a branding override whose foreground/background pair fails WCAG 2.2 AA contrast (ratio < 4.5:1 for normal text, < 3:1 for large text) is rejected and the ThemeBuilder falls back to the compliant base token
Unit tests exist for every component theme factory method (TextTheme, ButtonTheme, AppBarTheme, InputDecorationTheme, etc.) asserting correct property values for at least one org in each brightness
Widget tests mount a minimal MaterialApp for each of the 8 orgĂ—brightness combinations and assert: body text color contrast against surface color meets WCAG 2.2 AA, ElevatedButton minimum tap target size is >= 44Ă—44 logical pixels, primary button label color contrast against button background meets WCAG 2.2 AA
All tests use the flutter_test accessibility harness (meetsTapTargetGuideline, meetsGuideline(textContrastGuideline)) — not manual color comparisons alone
Test file structure follows the existing project test conventions (one test file per source file or per logical group)
All 8 ColorScheme mapping tests must produce zero delta when run against the committed design token JSON files — any token file change that breaks a test must be intentional
CI pipeline passes: `flutter test` exits 0 with all new tests included
Test coverage for theme_builder.dart reaches >= 90% line coverage as reported by flutter test --coverage

Technical Requirements

frameworks
flutter_test (unit and widget test runner)
Flutter accessibility test matchers (meetsTapTargetGuideline, meetsGuideline)
Riverpod ProviderContainer for unit-testing providers in isolation
apis
flutter_test WidgetTester API
flutter_test semantics / accessibility matchers
Riverpod ProviderContainer.read for provider unit tests
Flutter ColorScheme / ThemeData inspection APIs
WCAG contrast ratio calculation utility (project-internal or package)
data models
OrganisationBrandingConfig (fixture data for all 4 orgs)
ThemeData / ColorScheme (under test)
DesignToken (source of expected values in assertions)
performance requirements
Full test suite for this file must complete in < 60 seconds on CI
Widget tests must not use real timers or network — all async dependencies must be faked
security requirements
Test fixtures must not include real production credentials or API keys
Contrast validation tests must use the same algorithm as the production validator to prevent test/production divergence
ui components
Minimal MaterialApp test harness (Text widget, ElevatedButton, TextField for widget tests)
AccessibilityGuideline matchers from flutter_test

Execution Context

Execution Tier
Tier 8

Tier 8 - 48 tasks

Can start after Tier 7 completes

Integration Task

Handles integration between different epics or system components. Requires coordination across multiple development streams.

Implementation Notes

Use Riverpod ProviderContainer (not ProviderScope) for unit tests to keep tests fast and isolated — create a fresh container per test with override() to inject fixture branding configs. For ColorScheme mapping tests, define expected values as constants derived directly from the design token JSON files (parse them in a test helper) rather than hardcoding hex strings — this creates a single source of truth and makes token drift immediately visible. For contrast validation tests, create a test helper `expectContrastRatio(Color fg, Color bg, {double minRatio})` that computes relative luminance using the W3C formula — this is more reliable than relying solely on the accessibility matcher which works on rendered pixels. For widget tests, use `tester.pump()` rather than `pumpAndSettle()` where possible to keep tests fast; only use `pumpAndSettle()` when testing animated transitions.

Group tests with Dart's `group()` by organisation name to make CI output readable. Consider parameterizing org×brightness combinations with a helper to avoid 8 copies of near-identical test bodies — use a list of test cases and a loop calling `testWidgets()`.

Testing Requirements

This task IS the testing task. Self-validation: run `flutter test test/theme_builder_test.dart --coverage` and confirm 0 failures and >= 90% coverage. Peer review checklist: each test has a descriptive name following the pattern 'given_[state]_when_[action]_then_[expectation]'; no test shares mutable state with another; all widget tests call tester.pumpAndSettle() before making assertions; accessibility matcher failures produce a meaningful error message identifying which org/brightness combination failed. Regression gate: add a comment block in the test file listing the design token file hashes that the mapping tests were written against, so future token updates are flagged.

Component
Accessible Theme Builder
infrastructure medium
Epic Risks (2)
high impact low prob scope

One or more of the four partner organisations may supply brand primary colors that cannot be paired with any standard foreground at 4.5:1 contrast (for example, a mid-range hue that is too light for dark text and too dark for white text). Rejecting these colors programmatically could cause a political dispute with the organisation and delay the feature.

Mitigation & Contingency

Mitigation: Before implementation begins, run all four organisations' existing brand primary colors through the contrast-ratio-validator against both white (#FFFFFF) and a near-black (#1A1A1A). Share the results with each organisation's contact person ahead of the theme builder sprint so any problematic colors can be adjusted collaboratively with advance notice.

Contingency: If an organisation insists on a non-compliant brand color, produce a compliant near-match (lightened or darkened along the hue's luminance axis) and present both options with contrast ratio evidence. Document the adjusted token in the manifest with an explicit note that the original brand color was non-compliant, and obtain written sign-off from the organisation.

medium impact medium prob scope

Flutter's ThemeData contains over 30 component theme properties. If the theme-builder only addresses the most common ones (Button, InputDecoration, Card) and leaves others at Flutter defaults, downstream feature teams may unknowingly use default-themed widgets that do not meet sizing or contrast requirements.

Mitigation & Contingency

Mitigation: Produce a full inventory of all ThemeData component theme properties and map each to either a token-driven override or an explicit pass-through decision documented in the theme builder code. Prioritise the inventory by frequency of use in the existing codebase (identified via Grep). Include a check in the CI lint runner that flags widgets using Flutter default component themes not covered by the theme builder.

Contingency: If the full inventory scope exceeds the sprint budget, ship with the highest-frequency components covered and add a tracked backlog item for each uncovered component theme, pairing with a temporary lint suppression comment that includes the backlog reference.