"""Design-token checks for src/javis/gui/theme.py (WCAG 2.2 AA contrast).""" from __future__ import annotations import re import pytest from javis.gui import theme # (foreground, background) pairs rendered as text: need 4.5:1 (SC 1.4.3). TEXT_PAIRS = [ ("text", "bg"), ("text", "surface"), ("text", "surface2"), ("text", "input"), ("muted", "bg"), ("muted", "surface"), ("muted", "surface2"), ("accent", "bg"), ("accent", "surface"), ("on_accent", "primary"), ("on_accent", "primary_hover"), ("success", "bg"), ("error", "bg"), ("error", "error_bg"), ("warn_fg", "bg"), ("tool_fg", "tool_bg"), ("tool_muted", "tool_bg"), ("code_fg", "code_bg"), ("link", "bg"), ] # Control boundaries and focus indicators: need 3:1 (SC 1.4.11). UI_PAIRS = [ ("stroke_strong", "bg"), ("stroke_strong", "surface"), ("focus", "bg"), ("focus", "surface"), ("primary", "bg"), ("on_accent", "primary"), ] @pytest.mark.parametrize("name", sorted(theme.THEMES)) @pytest.mark.parametrize("fg,bg", TEXT_PAIRS) def test_text_contrast(name, fg, bg): t = theme.THEMES[name] assert theme.contrast_ratio(t[fg], t[bg]) >= 4.5, f"{name}: {fg} on {bg}" @pytest.mark.parametrize("name", sorted(theme.THEMES)) @pytest.mark.parametrize("fg,bg", UI_PAIRS) def test_ui_contrast(name, fg, bg): t = theme.THEMES[name] assert theme.contrast_ratio(t[fg], t[bg]) >= 3.0, f"{name}: {fg} vs {bg}" def test_palettes_share_keys(): assert set(theme.PAL_DARK) == set(theme.PAL_LIGHT) def test_accent_hue_kept(): # The redesign must keep the brand colours of the dark theme. assert theme.PAL_DARK["accent"].lower() == "#da7756" assert theme.PAL_DARK["bg"] == "#1e1e1e" def test_contrast_math(): assert theme.contrast_ratio("#000000", "#ffffff") == pytest.approx(21.0) assert theme.readable_on("#DA7756") == "#1e1e1e" assert theme.readable_on("#3c3c3c") == "#ffffff" @pytest.mark.parametrize("name", sorted(theme.THEMES)) def test_qss_is_well_formed(name): qss = theme.build_qss(theme.THEMES[name], "Segoe UI") assert qss.count("{") == qss.count("}") # every palette value used in the sheet is a full hex colour for hex_color in re.findall(r"#[0-9a-fA-F]+\b", qss): assert len(hex_color) in (4, 7), hex_color assert "variant=\"primary\"" in qss