возможно исправил ошибку таймера с vMix
This commit is contained in:
@@ -34,7 +34,7 @@ def test_build100_frontend_shortcut_edges_and_pending_press_are_guarded() -> Non
|
||||
assert 'if (!state.pendingShortcutSequenceRuns.has(sequence.id))' in APP_JS
|
||||
assert 'one stale/broken title must not prevent the remaining title' in APP_JS
|
||||
assert 'requestTimeoutMs = Math.min(60000' in APP_JS
|
||||
assert 'BUILD_VERSION = "2026.08.24.3"' in APP
|
||||
assert 'BUILD_VERSION = "2026.08.24.4"' in APP
|
||||
|
||||
|
||||
def test_build100_interactive_shortcut_is_single_command_acked_and_continues_after_failure(tmp_path: Path) -> None:
|
||||
|
||||
58
tests/test_build101_simple_timer_runtime.py
Normal file
58
tests/test_build101_simple_timer_runtime.py
Normal file
@@ -0,0 +1,58 @@
|
||||
from pathlib import Path
|
||||
|
||||
ROOT = Path(__file__).resolve().parents[1]
|
||||
APP_JS = (ROOT / "ui_builder/static/app.js").read_text(encoding="utf-8")
|
||||
APP = (ROOT / "app.py").read_text(encoding="utf-8")
|
||||
|
||||
|
||||
def _block(start: str, end: str) -> str:
|
||||
return APP_JS.split(start, 1)[1].split(end, 1)[0]
|
||||
|
||||
|
||||
def test_timer_transport_is_independent_from_generic_vmix_queue():
|
||||
block = _block("function sendRuntimeVmixTimerSequence", "function splitVmixInputs")
|
||||
assert 'fetch("/api/hockey/vmix/sequence"' in block
|
||||
assert 'keepalive: true' in block
|
||||
assert 'state.vmixCommandQueue' not in block
|
||||
assert 'sequence_id' not in block.split('body: JSON.stringify({', 1)[1]
|
||||
assert 'Runtime continues locally' in block
|
||||
|
||||
|
||||
def test_timer_start_stop_protocol_is_minimal():
|
||||
helper = _block("function vmixCountdownSyncCommands", "function buildShortcutRuntimeContext")
|
||||
assert 'if (action === "stop" || action === "pause")' in helper
|
||||
stop_branch = helper.split('if (action === "stop" || action === "pause")', 1)[1].split('return [', 1)[1].split('];', 1)[0]
|
||||
assert stop_branch.index('Function: "StopCountdown"') < stop_branch.index('Function: "SetCountdown"')
|
||||
start_branch = helper.rsplit('return [', 1)[1]
|
||||
assert start_branch.index('Function: "SetCountdown"') < start_branch.index('Function: "StartCountdown"')
|
||||
assert 'SuspendCountdown' not in helper
|
||||
assert 'PauseCountdown' not in helper
|
||||
|
||||
|
||||
def test_combined_hockey_timer_shortcut_never_waits_for_agent():
|
||||
block = APP_JS.split('case "hockey_vmix_timers_start":', 1)[1].split('case "delay":', 1)[0]
|
||||
assert 'sendRuntimeVmixTimerSequence(commands);' in block
|
||||
assert 'await sendRuntimeVmixSequence(commands' not in block
|
||||
assert 'fire-and-forget' in block
|
||||
# Local state changes remain ahead of any vMix transport.
|
||||
assert block.index('if (step.start_web_game)') < block.index('if (commands.length) sendRuntimeVmixTimerSequence(commands);')
|
||||
|
||||
|
||||
def test_main_and_penalty_resync_do_not_use_generic_queue():
|
||||
game = _block("async function syncActiveVmixGameCountdown", "function penaltyMirrorKey")
|
||||
penalty = _block("async function rebalanceVmixPenaltyTargets", "function finishActionMatchesSource")
|
||||
assert 'sendRuntimeVmixTimerSequence(commands);' in game
|
||||
assert 'await sendRuntimeVmixSequence(commands)' not in game
|
||||
assert 'sendRuntimeVmixTimerSequence(commands);' in penalty
|
||||
assert 'await sendRuntimeVmixSequence(commands)' not in penalty
|
||||
|
||||
|
||||
def test_busy_shortcut_can_toggle_timer_without_waiting_for_title_ack():
|
||||
block = _block("function shortcutSequenceTimerControlSteps", "function handleConfiguredShortcutCombo")
|
||||
assert 'runShortcutTimerControlsWhileBusy(sequence, meta)' in block
|
||||
assert 'timer controls are never queued behind title/Agent ACK traffic' in block
|
||||
assert '["timer_command", "hockey_vmix_timers_start"]' in block
|
||||
|
||||
|
||||
def test_build101_runtime_version():
|
||||
assert 'BUILD_VERSION = "2026.08.24.4"' in APP
|
||||
@@ -32,15 +32,16 @@ def test_main_countdown_start_pause_stop_all_hard_sync_web_value():
|
||||
assert 'vmixCountdownSyncCommands(input, selectedName, valueProvider, "stop")' in block
|
||||
helper = _block("function vmixCountdownSyncCommands", "function buildShortcutRuntimeContext")
|
||||
start_branch = helper.rsplit("return [", 1)[1]
|
||||
assert start_branch.index('Function: "SuspendCountdown"') < start_branch.index('Function: "SetCountdown"')
|
||||
assert 'Function: "SuspendCountdown"' not in start_branch
|
||||
assert start_branch.index('Function: "SetCountdown"') < start_branch.index('Function: "StartCountdown"')
|
||||
|
||||
|
||||
def test_penalty_pause_freezes_before_reseed_and_start_reseeds_before_run():
|
||||
block = _block("async function rebalanceVmixPenaltyTargets", "function finishActionMatchesSource")
|
||||
assert 'stopCommands.push({ Function: "SuspendCountdown"' in block
|
||||
assert 'stopCommands.push({ Function: "StopCountdown"' in block
|
||||
assert 'setCommands.push({ Function: "SetCountdown"' in block
|
||||
assert 'runCommands.push({ Function: "StartCountdown"' in block
|
||||
assert 'sendRuntimeVmixTimerSequence(commands)' in block
|
||||
assert "prepared/paused penalty" in block
|
||||
|
||||
|
||||
|
||||
@@ -22,27 +22,31 @@ def test_vmix_queue_resolves_countdown_values_at_actual_send_time():
|
||||
assert 'const clean = (rawCommands || []).map(compactVmixCommand)' in sender
|
||||
|
||||
|
||||
def test_countdown_start_is_deterministic_suspend_set_start():
|
||||
def test_countdown_start_is_simple_set_start():
|
||||
helper = _block("function vmixCountdownSyncCommands", "function buildShortcutRuntimeContext")
|
||||
start_branch = helper.split('return [', 3)[-1]
|
||||
assert start_branch.index('Function: "SuspendCountdown"') < start_branch.index('Function: "SetCountdown"')
|
||||
assert 'Function: "SuspendCountdown"' not in start_branch
|
||||
assert start_branch.index('Function: "SetCountdown"') < start_branch.index('Function: "StartCountdown"')
|
||||
assert 'Value: currentValue' in helper
|
||||
|
||||
|
||||
def test_pause_uses_suspend_not_toggle_pausecountdown():
|
||||
def test_pause_and_stop_use_stop_then_set():
|
||||
helper = _block("function vmixCountdownSyncCommands", "function buildShortcutRuntimeContext")
|
||||
pause = helper.split('if (action === "pause")', 1)[1].split('return [', 1)[1].split('];', 1)[0]
|
||||
assert 'Function: "SuspendCountdown"' in pause
|
||||
assert 'Function: "PauseCountdown"' not in pause
|
||||
assert pause.index('Function: "SuspendCountdown"') < pause.index('Function: "SetCountdown"')
|
||||
branch = helper.split('if (action === "stop" || action === "pause")', 1)[1].split('return [', 1)[1].split('];', 1)[0]
|
||||
assert 'Function: "StopCountdown"' in branch
|
||||
assert 'Function: "SetCountdown"' in branch
|
||||
assert branch.index('Function: "StopCountdown"') < branch.index('Function: "SetCountdown"')
|
||||
assert 'Function: "SuspendCountdown"' not in branch
|
||||
assert 'Function: "PauseCountdown"' not in branch
|
||||
|
||||
|
||||
def test_penalty_rebalance_hard_syncs_running_countdown_and_pauses_stably():
|
||||
block = _block("async function rebalanceVmixPenaltyTargets", "function finishActionMatchesSource")
|
||||
assert 'stopCommands.push({ Function: "SuspendCountdown"' in block
|
||||
assert 'stopCommands.push({ Function: "StopCountdown"' in block
|
||||
assert 'Value: () => vmixCountdownValue(entry.event.remainingMs)' in block
|
||||
assert 'runCommands.push({ Function: "StartCountdown"' in block
|
||||
assert 'sendRuntimeVmixTimerSequence(commands)' in block
|
||||
assert 'Function: "SuspendCountdown"' not in block
|
||||
assert 'Function: "PauseCountdown"' not in block
|
||||
|
||||
|
||||
@@ -64,4 +68,4 @@ def test_fixed_pin_1993_replaces_daily_login(tmp_path, monkeypatch):
|
||||
|
||||
|
||||
def test_build98_runtime_version():
|
||||
assert 'BUILD_VERSION = "2026.08.24.1"' in APP
|
||||
assert 'BUILD_VERSION = "2026.08.24.4"' in APP
|
||||
|
||||
@@ -106,7 +106,8 @@ def test_shortcut_editor_layout_fixes_add_step_buttons_and_fullscreen_modal() ->
|
||||
|
||||
def test_hockey_timer_shortcut_supports_native_countdown_and_legacy_text_mirror() -> None:
|
||||
app_js = Path("ui_builder/static/app.js").read_text(encoding="utf-8")
|
||||
assert 'Function: "SuspendCountdown"' in app_js
|
||||
assert 'Function: "StopCountdown"' in app_js
|
||||
assert 'Function: "SuspendCountdown"' not in app_js
|
||||
assert 'Function: "StopCountdown"' in app_js
|
||||
assert 'hockey_timer_command' in app_js
|
||||
assert 'game_vmix_mode' in app_js
|
||||
@@ -252,7 +253,8 @@ def test_build90_native_countdown_avoids_per_second_transport() -> None:
|
||||
app_js = Path("ui_builder/static/app.js").read_text(encoding="utf-8")
|
||||
assert 'game_vmix_mode !== "countdown"' in app_js
|
||||
assert 'const countdownMode = step.penalty_vmix_mode === "countdown"' in app_js
|
||||
assert 'Function: "SuspendCountdown"' in app_js
|
||||
assert 'Function: "StopCountdown"' in app_js
|
||||
assert 'Function: "SuspendCountdown"' not in app_js
|
||||
assert 'Function: "StopCountdown"' in app_js
|
||||
assert 'signal: controller.signal' in app_js
|
||||
assert 'vmixCommandQueue: Promise.resolve()' in app_js
|
||||
|
||||
Reference in New Issue
Block a user