from pathlib import Path ROOT = Path(__file__).resolve().parents[1] APP = (ROOT / "ui_builder/static/app.js").read_text(encoding="utf-8") ADMIN = (ROOT / "hockey_data/static/admin-directories.js").read_text(encoding="utf-8") def test_side_penalty_mapping_context_is_derived_from_active_penalties(): start = APP.index("async function hockeySyncPenaltySideMappingContext") end = APP.index("function penaltyTargetAssignmentKey", start) snippet = APP[start:end] assert 'sortedPenaltyEntries("home")[0]' in snippet assert 'sortedPenaltyEntries("away")[0]' in snippet for key in ( "selected_home_penalty_id", "selected_home_penalty_player_id", "selected_home_penalty_player_db_id", "selected_home_penalty_team_penalty", "selected_away_penalty_id", "selected_away_penalty_player_id", "selected_away_penalty_player_db_id", "selected_away_penalty_team_penalty", ): assert f"{key}:" in snippet assert 'fetch("/api/hockey/context/batch"' in snippet def test_penalty_context_sync_runs_when_penalty_changes_and_clears_on_finish(): assert "hockeySyncPenaltySideMappingContext().catch(() => {});" in APP assert APP.count("hockeySyncPenaltySideMappingContext({ force: true }).catch(() => {});") >= 3 def test_saved_penalty_player_keeps_external_and_database_ids(): start = APP.index("function hockeyCompactPlayer") end = APP.index("function hockeyCompactInfraction", start) snippet = APP[start:end] assert "const externalId" in snippet assert "const dbId" in snippet assert "externalId," in snippet assert "dbId," in snippet def test_mapping_admin_refreshes_live_after_runtime_context_update(): assert 'window.addEventListener("hockey:mapping-context-updated"' in ADMIN assert "await loadMappingCatalog()" in ADMIN assert "renderMapping();" in ADMIN