from pathlib import Path def test_penalty_timer_prefers_shortest_and_rebalances_after_finish(): js = Path("ui_builder/static/app.js").read_text(encoding="utf-8") assert "function sortedPenaltyEntries" in js assert "Number(a.event.remainingMs || 0) - Number(b.event.remainingMs || 0)" in js assert "function rebalanceVmixPenaltyTargets" in js assert "activeHockeyVmixTimerSteps" in js assert "auto_hide_on_finish" in js assert "OverlayInput${overlay}Out" in js assert "remaining_on_side" in js assert 'penalty_display_mode' in js assert 'allEntries.slice(0, 1)' in js assert 'allTargets.slice(0, 1)' in js def test_shortcuts_can_use_match_state_and_prematch_conditions(): js = Path("ui_builder/static/app.js").read_text(encoding="utf-8") for condition in ( "home_delayed_penalty", "away_delayed_penalty", "any_delayed_penalty", "home_empty_net", "away_empty_net", "any_empty_net", "prematch_button_active", "prematch_button_inactive", ): assert condition in js assert "condition_value" in js assert 'hockeyToggleMatchFlag(button.dataset.hockeyTeamFlag)' in js def test_prematch_buttons_migrated_to_bottom_command_dock(): js = Path("ui_builder/static/app.js").read_text(encoding="utf-8") html = Path("ui_builder/static/index.html").read_text(encoding="utf-8") assert "function openHockeyPrematchButtonsEditor" in js assert "function renderHockeyQuickCommandDock" in js assert "function ensureHockeyQuickCommandWorkspace" in js assert 'filter((tab) => tab?.id !== "prematch")' in js assert 'component?.type !== "hockey_prematch_panel"' in js assert 'id="runtimeButtonDock"' in html def test_game_control_flags_are_persisted_separately_from_timers(): models = Path("hockey_data/models.py").read_text(encoding="utf-8") service = Path("hockey_data/service.py").read_text(encoding="utf-8") router = Path("hockey_data/router.py").read_text(encoding="utf-8") assert "runtime_flags_json" in models assert "def set_game_flags" in service assert '"flags": self._runtime_flags_from_row(control)' in service assert '/control/flags' in router def test_mapping_exposes_server_computed_strength_labels(): source = Path("hockey_data/mapping_context.py").read_text(encoding="utf-8") assert "def _live_control_items" in source assert '"key": f"strength.{key}"' in source assert '"state_label", "Подпись численного состава"' in source assert '"advantage_numbers", "Состав большинства"' in source assert "HockeyDataService._strength_payload" in source def test_strength_payload_uses_configured_labels_for_double_penalty(): from hockey_data.service import HockeyDataService settings = { "strength_regulation_skaters": 5, "strength_min_skaters": 3, "strength_state_labels": { "regulation": { "5x3": {"ru": "ДВОЙНОЕ БОЛЬШИНСТВО", "en": "5 on 3"}, }, }, } penalty = lambda side, remaining: { "side": side, "infraction": {"code": "TEST"}, "preset": "2", "durationMs": 120000, "remainingMs": remaining, "finished": False, } timer_state = {"penalty_board": {"penalties": [ penalty("home", 90000), penalty("home", 60000), ]}} value = HockeyDataService._strength_payload( settings, stage="regular", current_period="1", timer_state=timer_state, language="ru" ) assert value["home_skaters"] == 3 assert value["away_skaters"] == 5 assert value["state_key"] == "5x3" assert value["state_label"] == "ДВОЙНОЕ БОЛЬШИНСТВО" assert value["away_label"] == "ДВОЙНОЕ БОЛЬШИНСТВО" assert value["strength_label"] == "3×5"