v3.22.0 (review fixes): the ownership reconciliation and the import guards
The suite/script ownership invariant could break silently: a suites import with mode "replace" wiped the suites while their scripts stayed behind (suite_id pointing at gone suites - invisible in the UI), a scripts import with mode "replace" left every suite's member list dangling, and a script whose suite_id disagreed with its listing suite stayed inconsistent. - server: reconcile_scripts_to_suites() repairs the invariant - a script a suite lists adopts that suite (the member list is authoritative), a script no suite lists joins "Imported scripts"; migrate_scripts_to_suites() delegates to it (the startup migration is the same pass) and the suites import runs it after loading, so a "replace" adopts the wiped suites' scripts instead of losing them. - the scripts import refuses mode "replace" while any suite still lists scripts (400 naming the dangling references; merge is the normal path). - nits from the review: a legacy numeric `event` is no longer parsed as hex in the step summary/error check (0x0A displayed as 0x10), and an integral float memory quota (a JSON client's 200.0) is accepted. - tests: the reconciliation (missing suite, listed-but-mismatched, idempotent), the scripts-replace guard (refused/allowed), the suites-replace adoption, the float quota, the numeric-event summary. Tests: 838 frontend + 800 Python; sw cache simple-v402.
This commit is contained in:
+5
-2
@@ -7197,7 +7197,8 @@ function testStepSummary(step) {
|
||||
: 'item=' + p.item_id);
|
||||
}
|
||||
else if (step.kind === 'event') {
|
||||
const code = parseInt(p.event, 16);
|
||||
// a legacy numeric event is the code itself; the editor stores hex
|
||||
const code = (typeof p.event === 'number') ? p.event : parseInt(p.event, 16);
|
||||
s = 'EVENT ' + (EVENT_NAMES[code] || ('0x' + String(p.event || '?')));
|
||||
if (p.src) s += ' src=' + p.src;
|
||||
}
|
||||
@@ -8290,7 +8291,9 @@ function testStepFormError() {
|
||||
if (problem) return problem;
|
||||
}
|
||||
if (step.kind === 'event') {
|
||||
const code = parseInt(String((step.params || {}).event || ''), 16);
|
||||
const rawEvent = (step.params || {}).event;
|
||||
const code = (typeof rawEvent === 'number') ? rawEvent
|
||||
: parseInt(String(rawEvent || ''), 16);
|
||||
const cfg = EVENT_FORMS[code];
|
||||
if (!cfg) return t('No form for this event - use the raw Envelope action.');
|
||||
const bad = eventFormPatternError(cfg, (step.params || {}).fields || {});
|
||||
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
const CACHE = 'simple-v401';
|
||||
const CACHE = 'simple-v402';
|
||||
const URLS = [
|
||||
'index.html',
|
||||
'help.html',
|
||||
|
||||
@@ -465,12 +465,17 @@ test('the event step collects the form values, the built data and the source', (
|
||||
fakeForm({ 'test-step-kind': 'event', 'test-f-evtype': '00', 'test-f-ev-ti': 'ZZZ',
|
||||
'test-f-sw': '', 'test-f-cdata': '', 'test-f-fail': 'error' });
|
||||
assert.match(testStepFormError(), /Invalid/);
|
||||
// the summary names the event and its source
|
||||
// the summary names the event and its source; a legacy numeric event is
|
||||
// the code itself (the editor stores the hex string form)
|
||||
assert.strictEqual(testStepSummary({ type: 'action', kind: 'event',
|
||||
params: { event: '03', fields: {} } }), 'EVENT Location status');
|
||||
assert.strictEqual(testStepSummary({ type: 'action', kind: 'event',
|
||||
params: { event: '00', data: '1C0101', src: '83' } }),
|
||||
'EVENT MT call src=83');
|
||||
assert.strictEqual(testStepSummary({ type: 'action', kind: 'event',
|
||||
params: { event: 10 } }), 'EVENT ' + EVENT_NAMES[10]);
|
||||
assert.strictEqual(testStepSummary({ type: 'action', kind: 'event',
|
||||
params: { event: '0A' } }), 'EVENT ' + EVENT_NAMES[10]);
|
||||
});
|
||||
|
||||
test('the shared event-form helpers render, prefill and collect', () => {
|
||||
|
||||
Reference in New Issue
Block a user