Files
hockey_new/tests/test_mapping_rules.py
2026-08-19 15:08:39 +03:00

167 lines
5.4 KiB
Python

from __future__ import annotations
from hockey_data.agent_bridge import (
_mapping_numeric_value,
_mapping_rule_command,
_mapping_rule_matches,
_mapping_value_function,
)
def _item(value: object) -> dict[str, object]:
return {"value": value}
def test_mapping_numeric_value_supports_stats_formats() -> None:
assert _mapping_numeric_value("25") == 25.0
assert _mapping_numeric_value("51%") == 51.0
assert _mapping_numeric_value("08:14") == 494.0
assert _mapping_numeric_value("1:02:03") == 3723.0
assert _mapping_numeric_value("12,5") == 12.5
def test_mapping_rule_matches_numeric_time_and_text() -> None:
assert _mapping_rule_matches("25", "gt", "18") is True
assert _mapping_rule_matches("08:14", ">", "07:59") is True
assert _mapping_rule_matches("49%", "lt", "51%") is True
assert _mapping_rule_matches("HOME", "eq", "home") is True
assert _mapping_rule_matches("Power Play", "contains", "play") is True
assert _mapping_rule_matches("", "empty") is True
def test_text_colour_rule_uses_true_and_false_colours() -> None:
base = {
"enabled": True,
"action": "text_colour",
"left_key": "stats.home",
"operator": "gt",
"right_mode": "field",
"right_key": "stats.away",
"true_value": "#E5CEA8",
"false_value": "#FFFFFF",
}
command, error = _mapping_rule_command(
base,
field_type="text",
input_ref="53",
selected_name="HOME_SHOTS.Text",
default_data_key="stats.home",
by_key={"stats.home": _item(31), "stats.away": _item(25)},
)
assert error == ""
assert command == {
"Function": "SetTextColour",
"Input": "53",
"SelectedName": "HOME_SHOTS.Text",
"Value": "#E5CEA8",
}
command, error = _mapping_rule_command(
base,
field_type="text",
input_ref="53",
selected_name="HOME_SHOTS.Text",
default_data_key="stats.home",
by_key={"stats.home": _item(20), "stats.away": _item(25)},
)
assert error == ""
assert command is not None
assert command["Value"] == "#FFFFFF"
def test_visibility_rule_is_deterministic_for_text_and_image() -> None:
rule = {
"enabled": True,
"action": "visibility",
"left_key": "stats.home",
"operator": "gt",
"right_mode": "field",
"right_key": "stats.away",
"true_value": "on",
"false_value": "off",
}
text_command, text_error = _mapping_rule_command(
rule,
field_type="text",
input_ref="53",
selected_name="HOME_ARROW.Text",
default_data_key="stats.home",
by_key={"stats.home": _item(10), "stats.away": _item(7)},
)
assert text_error == ""
assert text_command is not None
assert text_command["Function"] == "SetTextVisibleOn"
image_command, image_error = _mapping_rule_command(
rule,
field_type="image",
input_ref="53",
selected_name="HOME_ARROW.Source",
default_data_key="image.path",
by_key={"stats.home": _item(5), "stats.away": _item(7)},
)
assert image_error == ""
assert image_command is not None
assert image_command["Function"] == "SetImageVisibleOff"
assert "Value" not in image_command
def test_rule_can_compare_constant_and_reports_missing_source() -> None:
rule = {
"enabled": True,
"action": "visibility",
"left_key": "penalties",
"operator": "gte",
"right_mode": "value",
"right_value": "10",
"true_value": "on",
"false_value": "off",
}
command, error = _mapping_rule_command(
rule,
field_type="text",
input_ref="1",
selected_name="WARNING.Text",
default_data_key="penalties",
by_key={"penalties": _item(12)},
)
assert error == ""
assert command is not None
assert command["Function"] == "SetTextVisibleOn"
missing, error = _mapping_rule_command(
{**rule, "left_key": "missing"},
field_type="text",
input_ref="1",
selected_name="WARNING.Text",
default_data_key="penalties",
by_key={"penalties": _item(12)},
)
assert missing is None
assert error == "missing_left:missing"
def test_mapping_value_function_respects_mapping_type() -> None:
assert _mapping_value_function("text") == "SetText"
assert _mapping_value_function("image") == "SetImage"
assert _mapping_value_function("source") == "SetImage"
assert _mapping_value_function("color") == "SetColor"
def test_mapping_rule_controls_do_not_trigger_card_rerender() -> None:
from pathlib import Path
source = (Path(__file__).resolve().parents[1] / "hockey_data" / "static" / "admin-directories.js").read_text(encoding="utf-8")
assert 'event.target.closest("button, input, select, textarea, label, a' in source
assert '.hockey-map-rule-wrap' in source
def test_mapping_vmix_scroll_is_preserved_across_save_and_rerender() -> None:
from pathlib import Path
source = (Path(__file__).resolve().parents[1] / "hockey_data" / "static" / "admin-directories.js").read_text(encoding="utf-8")
assert 'mappingVmixScrollTop: 0' in source
assert 'vmixScroll.scrollTop = Math.max(0, Number(state.mappingVmixScrollTop || 0))' in source
assert 'state.mappingVmixScrollTop = vmixScroll.scrollTop' in source
assert 'if (currentScroll) state.mappingVmixScrollTop = currentScroll.scrollTop' in source