This commit is contained in:
2026-08-19 15:08:39 +03:00
parent 478557f3ad
commit a03c54dbe8
5148 changed files with 31553313 additions and 0 deletions

View File

@@ -0,0 +1,123 @@
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