from pathlib import Path from hockey_data.config import DEFAULT_PERIOD_STATUS_LABELS from hockey_data.service import HockeyDataService def test_period_status_has_bilingual_multi_format_settings_and_mapping_fields(): config = Path("hockey_data/config.py").read_text(encoding="utf-8") router = Path("hockey_data/router.py").read_text(encoding="utf-8") admin = Path("hockey_data/static/admin-directories.js").read_text(encoding="utf-8") mapping = Path("hockey_data/mapping_context.py").read_text(encoding="utf-8") js = Path("ui_builder/static/app.js").read_text(encoding="utf-8") assert "DEFAULT_PERIOD_STATUS_LABELS" in config assert 'period_status_labels: dict[str, Any] | None = None' in router assert "Статус периода для Mapping" in admin assert "period.compact" in admin assert "period.short" in admin assert "period.long" in admin for key in ( '"key": f"period.{key}"', 'f"period.{lang}.{fmt}"', '"category": "Матч · Период"', ): assert key in mapping assert "period_status" in js assert "hockeyStrengthMappingSignature" in js def test_period_status_numbered_overtime_formats_custom_n(): settings = { "period_status_labels": { **DEFAULT_PERIOD_STATUS_LABELS, "ot_numbered": { "compact": {"ru": "ОТ{n}", "en": "OT{n}"}, "short": {"ru": "Овертайм {n}", "en": "Overtime {n}"}, "long": {"ru": "{n}-й овертайм", "en": "Overtime number {n}"}, }, } } payload = HockeyDataService._period_status_payload(settings, current_period="ot3", language="ru") assert payload["key"] == "ot3" assert payload["lookup_key"] == "ot_numbered" assert payload["number"] == 3 assert payload["compact"] == "ОТ3" assert payload["short"] == "Овертайм 3" assert payload["formats"]["long"]["en"] == "Overtime number 3" def test_active_tab_is_mapping_context_and_shortcut_condition(): mapping = Path("hockey_data/mapping_context.py").read_text(encoding="utf-8") manager = Path("ui_builder/manager.py").read_text(encoding="utf-8") js = Path("ui_builder/static/app.js").read_text(encoding="utf-8") bridge = Path("hockey_data/agent_bridge.py").read_text(encoding="utf-8") assert '"key": "active_tab"' in mapping assert '"active_tab", "inactive_tab"' in manager assert '["active_tab", "Открыта выбранная вкладка"]' in js assert 'case "active_tab"' in js assert 'values: { active_tab: activeTab }' in js assert 'emitVirtualInteraction(PROJECT_TABS_ACTION_ID, "tab_change"' in js assert '"/api/hockey/context/batch"' in bridge def test_prematch_supports_groups_labels_and_drag_reordering(): manager = Path("ui_builder/manager.py").read_text(encoding="utf-8") app_py = Path("app.py").read_text(encoding="utf-8") js = Path("ui_builder/static/app.js").read_text(encoding="utf-8") css = Path("ui_builder/static/styles.css").read_text(encoding="utf-8") assert '"prematch_groups": []' in manager assert '"group_id"' in manager assert '"sort_order"' in manager assert 'groups = payload.get("prematch_groups", [])' in app_py assert "normalizePrematchGroups" in js assert 'draggable="true"' in js assert 'data-prematch-group-label' in js assert 'data-prematch-drop-group' in js assert '.prematch-editor-group' in css def test_penalty_preview_selection_persists_identifiers_before_trigger(): mapping = Path("hockey_data/mapping_context.py").read_text(encoding="utf-8") js = Path("ui_builder/static/app.js").read_text(encoding="utf-8") for key in ( "selected_penalty_id", "selected_penalty_player_id", "selected_penalty_team_id", "selected_penalty_infraction_id", "selected_penalty_preset_id", "selected_penalty_side", "selected_penalty_event_time", "selected_penalty_status", "selected_penalty_remaining_ms", "selected_penalty_duration_ms", ): assert key in mapping assert key in js assert 'selected_event_id: detail.penalty_id' in js assert 'emitInteraction(component, "penalty_selected", detail)' in js assert 'penalty_selected — удаление выбрано для подсмотра' in js # Mapping context request is intentionally before the trigger emit in the async path. function_body = js[js.index("async function hockeySelectPenaltyForPreview"):js.index("function hockeyPenaltyCard")] assert function_body.index('fetch("/api/hockey/context/batch"') < function_body.rindex('emitInteraction(component, "penalty_selected", detail)') def test_vmix_step_can_use_alternate_input_while_scoreboard_is_live(): manager = Path("ui_builder/manager.py").read_text(encoding="utf-8") js = Path("ui_builder/static/app.js").read_text(encoding="utf-8") for key in ( "use_scoreboard_alternate", "scoreboard_alternate_input", "scoreboard_alternate_selected_name", "is_scoreboard_sequence", ): assert key in manager assert key in js assert "function hockeyScoreboardIsLive()" in js assert "step.use_scoreboard_alternate && hockeyScoreboardIsLive()" in js assert "другой Input, если верхний счёт уже в эфире" in js assert "этот сценарий — верхний счёт" in js