Files
hockey_new/tests/test_build196_penalty_lifecycle.py

70 lines
2.7 KiB
Python

"""Execute the production save/tick/native-Countdown closure with a fake clock.
No application startup, external database, browser, network or real vMix is used.
The backend strength fixtures use its real pure calculator, rather than a second
implementation of the penalty arithmetic in JavaScript.
"""
from __future__ import annotations
import json
import os
from pathlib import Path
import shutil
import subprocess
import pytest
from hockey_data.service import HockeyDataService
ROOT = Path(__file__).resolve().parents[1]
def _strengths() -> dict:
settings = {
"strength_regulation_skaters": 5,
"strength_min_skaters": 3,
"strength_state_labels": {
"regulation": {"5x4": {"ru": "PP"}, "4x4": {"ru": "4 на 4"}},
},
}
results = {}
for home, away in ((0, 0), (1, 0), (0, 1), (1, 1)):
penalties = [
{"side": side, "teamPenalty": True, "infraction": {"id": "minor"},
"preset": "2", "durationMs": 120000, "remainingMs": 25000,
"running": True, "startedOnce": True, "finished": False}
for side, count in (("home", home), ("away", away)) for _ in range(count)
]
results[f"{home}:{away}"] = HockeyDataService._strength_payload(
settings, stage="regular", current_period="2",
timer_state={"penalty_board": {"penalties": penalties}}, language="ru",
)
assert results["1:1"]["state_label"] == "4 на 4"
assert results["0:1"]["state_label"] == results["1:0"]["state_label"] == "PP"
return results
SCENARIOS = (
"staggered_save_cadence", "force_save_keeps_earliest_deadline",
"inflight_save_preserves_latest_snapshot", "viewer_and_hydration_do_not_write",
"natural_expiry_refreshes_strength_home", "natural_expiry_refreshes_strength_away",
"native_opposite_stagger_home", "native_opposite_stagger_away",
"native_last_single_home", "native_last_single_away",
"native_simultaneous_home", "native_simultaneous_away",
)
@pytest.mark.parametrize("scenario", SCENARIOS)
def test_penalty_lifecycle(scenario: str) -> None:
node = shutil.which("node")
assert node, "Node is required for the executable penalty lifecycle regressions"
source = Path(os.environ.get("BUILD196_RUNTIME_SOURCE", ROOT / "ui_builder/static/app.js"))
result = subprocess.run(
[node, str(ROOT / "tests/build196_penalty_lifecycle.cjs"), scenario, str(source)],
input=json.dumps({"strengths": _strengths()}, ensure_ascii=False),
text=True, capture_output=True, timeout=20,
)
assert result.returncode == 0, result.stdout + result.stderr
assert f"PASS: {scenario}" in result.stdout, "The scenario must finish its assertions"