124 lines
5.4 KiB
Python
124 lines
5.4 KiB
Python
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
|