Write unit tests for contrast ratio validator
epic-visual-design-accessibility-foundation-task-011 — Create comprehensive flutter_test unit tests for the ContrastRatioValidator covering: known passing pairs (white on black = 21:1), known failing pairs, boundary cases at exactly 4.5:1 and 3:1, edge cases with identical colors (1:1), and all color pairs declared in the Accessibility Token Manifest. Target 100% branch coverage for the luminance algorithm.
Acceptance Criteria
Technical Requirements
Execution Context
Tier 4 - 323 tasks
Can start after Tier 3 completes
Implementation Notes
Identify a Color value whose normalized channel falls between 0.03928 and 0.04045 to write the regression test that distinguishes WCAG 2.0 from WCAG 2.2 linearization — for example, a channel value of ~10/255 ≈ 0.0392. The test should assert the luminance matches the 2.4/0.04045 formula result, not the 2.2/0.03928 result. For manifest-driven tests, define a `ColorPairFixture` model and parse the JSON in `setUpAll`. Keep the fixture file minimal (10-15 pairs) to keep tests fast.
Use `const Color(0xFFRRGGBB)` syntax in tests for readability. Group coverage: the `<=0.04045` and `>0.04045` branches in `relativeLuminance` must each be exercised — the regression test above handles this. For `contrastRatio`, the `L1 >= L2` swap branch must be covered by testing both orders (foreground lighter and foreground darker).
Testing Requirements
Use `flutter_test` exclusively — no additional test packages required. Structure tests with nested `group()` blocks matching the class hierarchy: outer group per class, inner group per method. Use `closeTo(expected, delta)` for all floating-point ratio assertions with delta=0.001. For the parameterized manifest test, load `test/fixtures/manifest_color_pairs.json` using `File` and iterate with `for` loop inside a single test case or use `group`/`test` dynamic generation inside a `setUpAll` block.
Verify that `highestLevel` enum values are correct on boundary conditions — this is where off-by-one logic errors hide. Add a regression test for the known WCAG 2.0 vs 2.2 difference: the linearization threshold 0.04045 (not 0.03928) must be used, verified with a color value that falls between the two thresholds.
The WCAG 2.2 relative luminance formula requires gamma-corrected sRGB calculations. Floating-point rounding differences between Dart and reference implementations could produce off-by-one classifications for near-threshold color pairs, resulting in pairs that just pass or just fail in CI but behave differently at runtime.
Mitigation & Contingency
Mitigation: Implement the algorithm directly from the WCAG 2.2 specification using the exact linearisation constants. Validate the Dart implementation against the W3C reference test vectors and against a known-good JavaScript implementation for at least 50 color pairs spanning the compliance boundaries.
Contingency: If discrepancies are found, add a configurable tolerance margin (e.g., ±0.005 on the ratio) and flag near-threshold pairs as warnings rather than hard failures, escalating to the design team for manual review.
The token manifest is a static data file. If developers add new color tokens to the design-token-provider without updating the manifest, the manifest becomes stale and the CI validator produces false negatives — passing builds that contain unvalidated color pairs.
Mitigation & Contingency
Mitigation: Add a CI step that cross-references every token constant exported by the design-token-provider against the manifest at build time, failing if any token is present in the provider but absent from the manifest. Document this requirement clearly in the contributing guide.
Contingency: If drift is detected post-merge, run a full manifest regeneration script and treat the resulting manifest diff as a blocking pull request with mandatory accessibility review.
The flutter_accessibility_lints package (or custom lint rules) may produce false positives on patterns the team deliberately uses — for example, decorative icon widgets that intentionally omit semantic labels. Excessive false positives will lead developers to add blanket ignore comments, undermining the entire lint strategy.
Mitigation & Contingency
Mitigation: Audit the full lint rule set against the existing codebase before enabling rules. Create a documented list of approved ignore-comment patterns with mandatory justification comments. Restrict ignore patterns to decorative-only contexts.
Contingency: If false positive rates exceed 10% of lint output, disable the highest-noise individual rules and replace them with targeted custom lint rules scoped to the specific patterns the team controls.