v3.23.6: the event name keywords in the test-script editor

A script's `event` value may be a code (a hex byte or a number) or one of the
server's name keywords (location_status, access_tech, network_rejection,
data_connection, ... - events.py's EVENT_NAMES); the API accepts both.  The
PWA parsed every value as a hex string: the step list showed
'EVENT 0xaccess_tech' (the unparsed fallback), the editor fell back to event
03 (Location status) with the location field set, and saving then rewrote
the step to that event - silently corrupting name-authored scripts (the two
Alfa2G trigger scripts use access_tech/data_connection).

A mirrored EVENT_ALIASES map plus an eventCode() resolver (number / hex byte
/ name -> code) now feed the step summary, the editor's event block and the
event check; the summary's fallback no longer prefixes a non-numeric value
with 0x, and the editor keeps its canonical hex form on save (the same code).

Drift guard: the aliases live in frontend/tests/event_vectors.json, asserted
by the Node test (the PWA's map + resolver) and the Python test
(events.EVENT_NAMES + resolve_event).  Tests: 856 frontend + 839 Python;
sw cache simple-v419.
This commit is contained in:
2026-10-07 21:56:20 +03:00
parent 02a78fcca6
commit 9fb46b786f
9 changed files with 110 additions and 11 deletions
+21
View File
@@ -31,6 +31,9 @@ function extractFunc(src, name, asyncFn) {
eval(extractBlock('const CMD_NAMES = {', 'function cmdQualifierShort').replace(/^const /gm, 'var '));
eval(extractBlock('const EVENT_NAMES = {', 'const EVENT_FORMS = {').replace(/^const /gm, 'var '));
eval(extractBlock('const EVENT_FORMS = {', 'const PLI_QUALIFIERS = [').replace(/^const /gm, 'var '));
// the event name aliases (the server's EVENT_NAMES keywords) + the resolver
eval(extractBlock('const EVENT_ALIASES = {', 'function eventCode').replace(/^const /gm, 'var '));
eval(extractFunc(html, 'eventCode'));
// the builders' pure helpers (eventFormFieldsHtml/Values are the shared form)
eval(extractFunc(html, 'bytesToHex'));
eval(extractFunc(html, 'eventAddressTlv'));
@@ -195,6 +198,24 @@ test('testStepSummary renders actions', () => {
assert.strictEqual(
testStepSummary({ type: 'action', kind: 'status', params: { attempts: 5 } }),
'STATUS x5 (poll)');
// the event action's value may be a name keyword (the server's alias
// form), the editor's hex byte or a number - all show the event name
for (const ev of ['access_tech', '0B', '0b', 11, 0x0B]) {
assert.strictEqual(
testStepSummary({ type: 'action', kind: 'event', params: { event: ev } }),
'EVENT Access technology change (single access technology)', String(ev));
}
assert.strictEqual(
testStepSummary({ type: 'action', kind: 'event', params: { event: 'data_connection' },
check: { sw: { mode: 'mask', value: '91??' } } }),
'EVENT Data connection status change · SW ~91??');
// a value that is neither a code nor a known name is shown as-is
assert.strictEqual(
testStepSummary({ type: 'action', kind: 'event', params: { event: 'nonsense' } }),
'EVENT nonsense');
assert.strictEqual(
testStepSummary({ type: 'action', kind: 'event', params: { event: '1F' } }),
'EVENT Slices status change');
assert.strictEqual(
testStepSummary({ type: 'action', kind: 'proactive-drain',
params: { attempts: 5, respond: { result: 'ok' },