from pathlib import Path from types import SimpleNamespace from hockey_data.auth_bridge import HockeyUser from hockey_data.mapping_context import MappingDataService from hockey_data.models import Game, GameControlState, Tournament from tests.support import LocalTestDatabase JS = Path("ui_builder/static/app.js").read_text(encoding="utf-8") CSS = Path("ui_builder/static/styles.css").read_text(encoding="utf-8") ROUTER = Path("hockey_data/router.py").read_text(encoding="utf-8") APP = Path("app.py").read_text(encoding="utf-8") def _seed(database: LocalTestDatabase) -> None: with database.session() as session: session.add(Tournament(external_id="1437", level="khl", name_ru="Тест", season="2026/27")) session.add(Game( external_id="902918", tournament_external_id="1437", home_team_external_id="23", away_team_external_id="17", home_team_name_ru="СКА", away_team_name_ru="Динамо", status="live", )) session.add(GameControlState( game_external_id="902918", current_period="2", runtime_values_json='{"panel.stat_period.value":"2","panel.stat_period.label":"2 период","panel.last_button.id":"team_stats"}', )) def test_quick_panel_selector_is_configurable_and_sent_before_sequence(): assert "quick_panel_selectors" in JS assert "normalizeQuickPanelSelectors" in JS assert "data-quick-selector-add" in JS assert "hockeyCommitQuickPanelButtonContext" in JS click = JS.index('el.runtimeButtonDock.querySelectorAll("[data-quick-command-button]")') snippet = JS[click:click + 2600] assert "await hockeyCommitQuickPanelButtonContext(button, attachedSelectors)" in snippet assert snippet.index("await hockeyCommitQuickPanelButtonContext") < snippet.index("runShortcutSequence") assert '"/control/values"' in JS assert '@router.put("/games/{external_id}/control/values")' in ROUTER assert 'quick_panel_selectors' in APP def test_panel_runtime_values_are_available_to_mapping_and_sql(tmp_path: Path): database = LocalTestDatabase(tmp_path / "build57.sqlite") database.create_all() _seed(database) service = MappingDataService(database) # type: ignore[arg-type] admin = HockeyUser(id="1", login="admin", display_name="Admin", is_admin=True, role="admin") context, variables = service.resolve_context(admin, {"game_id": "902918", "session_token": "S1"}) assert context["panel_stat_period_value"] == "2" assert context["panel_stat_period_label"] == "2 период" assert any(item["key"] == "panel_stat_period_value" and item["value"] == "2" for item in variables) source = service.create_source(SimpleNamespace( code="panel_demo", name="Параметр", category="Тест", description="", sql_text='SELECT :panel_stat_period_value AS "period", :panel_last_button_id AS "button_id"', field_metadata={}, enabled=True, sort_order=1999, ), admin) preview = service.preview_source(source["id"], admin, {"game_id": "902918", "session_token": "S1"}) assert preview["rows"][0]["period"] == "2" assert preview["rows"][0]["button_id"] == "team_stats" catalog = service.data_catalog(admin, {"game_id": "902918", "session_token": "S1"}) values = {item["key"]: item["value"] for item in catalog["items"]} assert values["panel.stat_period.value"] == "2" assert values["panel.stat_period.label"] == "2 период" def test_play_by_play_stays_mounted_below_operator_windows(): start = JS.index("function renderStandaloneHockeyPlayByPlayWindow()") snippet = JS[start:start + 900] assert 'state.activeTab !== "main"' in snippet assert 'hockey-admin-settings-open' not in snippet assert 'hockey-navigation-open' not in snippet assert 'el.modalHost?.querySelector(".modal-backdrop")' not in snippet build57_css = CSS[CSS.rindex("/* BUILD57") :] assert "z-index: 8 !important" in build57_css assert "display: grid !important" in build57_css