191 build - поправлены старые падения, проверены 3 матча и 6 агентов одновременных
This commit is contained in:
@@ -1,4 +1,6 @@
|
||||
from pathlib import Path
|
||||
import re
|
||||
import subprocess
|
||||
|
||||
from hockey_data.agent_bridge import _stable_vmix_inventory_fingerprint
|
||||
|
||||
@@ -54,13 +56,62 @@ def test_legacy_project_fingerprint_uses_title_instead_of_number():
|
||||
assert _stable_vmix_inventory_fingerprint(before) == _stable_vmix_inventory_fingerprint(after)
|
||||
|
||||
|
||||
def test_shortcut_editor_persists_key_before_number():
|
||||
def _run_functions(source, names, scenario):
|
||||
# Execute the shipped function bodies; test doubles supply only page state.
|
||||
functions = []
|
||||
for name in names:
|
||||
match = re.search(r"(?m)^ function " + re.escape(name) + r"\(", source)
|
||||
assert match, name
|
||||
following = re.search(r"(?m)^ (?:async )?function ", source[match.end():])
|
||||
assert following, name
|
||||
functions.append(source[match.start():match.end() + following.start()])
|
||||
script = "const assert = require('node:assert/strict');\n" + "\n".join(functions) + "\n" + scenario
|
||||
result = subprocess.run(["node", "-e", script], text=True, capture_output=True, timeout=10)
|
||||
assert result.returncode == 0, result.stderr
|
||||
|
||||
|
||||
def test_shortcut_editor_persists_title_and_migrates_legacy_selectors():
|
||||
app_js = (ROOT / "ui_builder" / "static" / "app.js").read_text(encoding="utf-8")
|
||||
assert 'return String(item?.key || item?.title || item?.number || "").trim();' in app_js
|
||||
assert "старый номер Input — выберите Input заново один раз" in app_js
|
||||
_run_functions(app_js, ["vmixInventoryInputs", "vmixInputRef", "vmixInputByRef"], r'''
|
||||
const score = {key: 'score-guid', number: '5', title: 'Score'};
|
||||
const other = {key: 'other-guid', number: '9', title: 'Other'};
|
||||
const state = {shortcutInventory: {inventory: {inputs: [score, other]}}};
|
||||
assert.equal(vmixInputRef(score), 'Score');
|
||||
assert.equal(vmixInputRef({key: 'only-guid', number: '5'}), '');
|
||||
for (const legacy of ['score-guid', '5']) assert.equal(vmixInputRef(vmixInputByRef(legacy)), 'Score');
|
||||
const saved = vmixInputRef(score);
|
||||
score.number = '9'; other.number = '5'; score.key = 'new-score-guid';
|
||||
assert.equal(vmixInputByRef(saved), score);
|
||||
assert.equal(vmixInputRef(vmixInputByRef(saved)), 'Score');
|
||||
assert.equal(vmixInputByRef('missing'), null);
|
||||
''')
|
||||
|
||||
|
||||
def test_mapping_links_do_not_resave_positional_number():
|
||||
def test_mapping_links_save_exact_title_and_clear_every_positional_number():
|
||||
mapping_js = (ROOT / "hockey_data" / "static" / "admin-directories.js").read_text(encoding="utf-8")
|
||||
assert 'vmix_input_number: ""' in mapping_js
|
||||
assert 'vmix_input_number: (row.vmix_input_key || row.vmix_input_title) ? ""' in mapping_js
|
||||
_run_functions(mapping_js, ["mappingInventoryInputs", "mappingFieldKind", "mappingRowMatchesInput",
|
||||
"mappingInputTitleProblem", "mappingSetLink", "collectMappingFields"], r'''
|
||||
const input = {key: 'current-guid', number: '17', title: 'Score', fields: [{name: 'Home.Text', type: 'text'}]};
|
||||
const profile = {inventory: {inputs: [input]}, fields: [{data_key:'old', vmix_input_key:'old-guid',
|
||||
vmix_input_number:'5', vmix_input_title:'Score', vmix_field:'Home.Text', rule:{enabled:true, left_key:'old'}}]};
|
||||
const state = {mappingActiveProfile:profile};
|
||||
const statuses = []; function setStatus(message){statuses.push(message);}
|
||||
mappingSetLink(profile, input, input.fields[0], {key:'score.home'});
|
||||
assert.equal(profile.fields.length, 1);
|
||||
assert.equal(profile.fields[0].vmix_input_title, 'Score');
|
||||
assert.equal(profile.fields[0].vmix_input_key, 'current-guid');
|
||||
assert.equal(profile.fields[0].vmix_input_number, '');
|
||||
assert.equal(profile.fields[0].rule.left_key, 'score.home');
|
||||
profile.fields.push({data_key:'legacy', vmix_input_key:'another-guid', vmix_input_number:'42', vmix_input_title:'Other', vmix_field:'Away.Text'});
|
||||
profile.fields.push({data_key:'orphaned-legacy', vmix_input_key:'', vmix_input_number:'7', vmix_input_title:'', vmix_field:'Legacy.Text'});
|
||||
const collected = collectMappingFields();
|
||||
assert.deepEqual(collected.map(row=>row.vmix_input_number), ['', '', '']);
|
||||
assert.deepEqual(collected.map(row=>row.vmix_input_title), ['Score', 'Other', '']);
|
||||
assert.deepEqual(collected.map(row=>row.sort_order), [0, 1, 2]);
|
||||
assert.equal(profile.fields[1].vmix_input_number, '42', 'Collecting must not mutate draft rows');
|
||||
const previous = JSON.stringify(profile.fields);
|
||||
profile.inventory.inputs.push({...input, key:'duplicate-guid', number:'18'});
|
||||
mappingSetLink(profile, input, input.fields[0], {key:'unsafe'});
|
||||
assert.equal(JSON.stringify(profile.fields), previous);
|
||||
assert.ok(statuses.length && statuses[0].includes('не уникально'));
|
||||
''')
|
||||
|
||||
Reference in New Issue
Block a user