mirror of
https://github.com/ChuckBuilds/LEDMatrix.git
synced 2026-10-04 06:15:09 +00:00
test(element-style): cover the stateless element_color clamp path (#576)
#569 fixed _normalize_color and #572 covered the resolver path. That test's own docstring notes the resolver "normalizes colour separately from element_color", and the other path had no test: the stateless element_color(), which src.common.sports_card delegates to and which every one of the nine scoreboard plugins takes for each per-element colour it draws. That is the path that regressed. element_color() moved here with the per-element customization framework, the coercion rejected out-of-range components where the reader it replaced clamped them, and a rejection reads as "not configured" -- so one component over 255 painted the element white while the user's colour sat in their config. Every scoreboard's test_element_text_colors.py failed on it, and it took two plugin PRs red on CI to surface. Six cases: clamping, in-range untouched, hex, unparseable fallback, missing element, and agreement with sports_card.coerce_rgb. The last is the point -- the two shared readers disagreed about the same value, so this asserts against coerce_rgb directly rather than restating the arithmetic, and any future move of element_color has to keep them consistent. Verified by mutation: restoring the rejecting coercion fails two of the six, alongside the resolver test from #572. Tests only; no source change. Claude-Session: https://claude.ai/code/session_014RRtqXDCnvnY6EQwhT5CV9 Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -25,6 +25,7 @@ from PIL import ImageFont
|
|||||||
|
|
||||||
from src.element_style import (
|
from src.element_style import (
|
||||||
alias_keys,
|
alias_keys,
|
||||||
|
element_color,
|
||||||
ElementStyleResolver,
|
ElementStyleResolver,
|
||||||
_load_font_sized,
|
_load_font_sized,
|
||||||
native_bdf_size,
|
native_bdf_size,
|
||||||
@@ -1282,3 +1283,49 @@ class TestAdoptedModes:
|
|||||||
font = self._live()["score_text"]["properties"]["font"]
|
font = self._live()["score_text"]["properties"]["font"]
|
||||||
assert font["x-options"]["maxFixedSize"] == 16
|
assert font["x-options"]["maxFixedSize"] == 16
|
||||||
assert "null" in font["type"]
|
assert "null" in font["type"]
|
||||||
|
|
||||||
|
|
||||||
|
class TestElementColorClamps:
|
||||||
|
"""An out-of-range component is clamped, not thrown away.
|
||||||
|
|
||||||
|
#569 fixed this in _normalize_color and #572 covered the resolver path,
|
||||||
|
whose own test notes that "the resolver path normalizes colour separately
|
||||||
|
from element_color". This covers the other one: the stateless element_color()
|
||||||
|
that src.common.sports_card delegates to, which is the path all nine
|
||||||
|
scoreboard plugins take for every per-element colour they draw.
|
||||||
|
|
||||||
|
It regressed once already. element_color() moved here with the per-element
|
||||||
|
customization framework, the coercion rejected out-of-range components where
|
||||||
|
the reader it replaced clamped them, and rejection reads as "not configured"
|
||||||
|
-- so a single component over 255 painted the element white while the user's
|
||||||
|
chosen colour sat in their config. Every scoreboard's
|
||||||
|
test_element_text_colors.py failed on it.
|
||||||
|
"""
|
||||||
|
|
||||||
|
CFG = {"customization": {
|
||||||
|
"rank_text": {"text_color": [999, -5, 20]},
|
||||||
|
"score_text": {"text_color": "#FF0000"},
|
||||||
|
"period_text": {"text_color": [0, 255, 255]},
|
||||||
|
"team_name": {"text_color": "nonsense"},
|
||||||
|
}}
|
||||||
|
|
||||||
|
def test_out_of_range_components_are_clamped(self):
|
||||||
|
assert element_color(self.CFG, "rank_text") == (255, 0, 20)
|
||||||
|
|
||||||
|
def test_in_range_values_are_unchanged(self):
|
||||||
|
assert element_color(self.CFG, "period_text") == (0, 255, 255)
|
||||||
|
|
||||||
|
def test_hex_still_parses(self):
|
||||||
|
assert element_color(self.CFG, "score_text") == (255, 0, 0)
|
||||||
|
|
||||||
|
def test_an_unparseable_value_still_falls_back(self):
|
||||||
|
assert element_color(self.CFG, "team_name") == (255, 255, 255)
|
||||||
|
|
||||||
|
def test_a_missing_element_still_falls_back(self):
|
||||||
|
assert element_color(self.CFG, "detail_text") == (255, 255, 255)
|
||||||
|
|
||||||
|
def test_it_agrees_with_coerce_rgb(self):
|
||||||
|
from src.common.sports_card import coerce_rgb
|
||||||
|
for value in ([999, -5, 20], [300, 300, 300], [-1, -1, -1], [0, 128, 255]):
|
||||||
|
cfg = {"customization": {"rank_text": {"text_color": value}}}
|
||||||
|
assert element_color(cfg, "rank_text") == coerce_rgb(value, (0, 0, 0)), value
|
||||||
|
|||||||
Reference in New Issue
Block a user