修复一个偶发的问题

This commit is contained in:
andy committed 2026-09-14 18:24:25 +08:00
1 parent 8d55e930a2
commit 0282c30a2a
20 files changed
+440 -39

No files matched your search

+36 -2
View File
@@ -15,10 +15,11 @@ const adapter = readFileSync(new URL('../chrome-extension/ltjt-order-assistant/l
teamSummaryRequery = async (operation, subpage) => subpage;
assistant.preflightLifecycleOperation = preflightLifecycleOperation;`);
function fixture({ occupied = 1, rows = occupied + 2, onSelection = () => {}, onValidate = () => {}, sort = false, onPost = () => {} } = {}) {
function fixture({ occupied = 1, rows = occupied + 2, onSelection = () => {}, onValidate = () => {}, sort = false, onPost = () => {}, linkageDelays = [], onLinkageTick = () => {} } = {}) {
let now = 10000;
let posts = 0;
let selections = 0;
let linkageTicks = 0;
let savedForm;
const form = { elements: [], id: 'InfoForm1', isConnected: true };
const fields = new Map();
@@ -69,7 +70,11 @@ function fixture({ occupied = 1, rows = occupied + 2, onSelection = () => {}, on
return savedForm.elements.find((control) => control.name === name) || null;
} }, text: 'LW-TEST-HOTEL', response: { ok: true, status: 200 } });
const sandbox = { window, document, location, Event: window.Event, URL, URLSearchParams, TextEncoder,
Date: class extends Date { static now() { return now; } }, setTimeout(callback, ms) { now += ms; callback(); } };
Date: class extends Date { static now() { return now; } }, setTimeout(callback, ms) {
now += selections ? linkageDelays[linkageTicks] ?? ms : ms;
if (selections) onLinkageTick(fields, ++linkageTicks);
callback();
} };
window.setTimeout = sandbox.setTimeout;
vm.runInNewContext(inpage, sandbox);
vm.runInNewContext(adapter, sandbox);
@@ -101,6 +106,35 @@ test('hotel create binds the first empty row through preflight, native linkage,
}
});
test('6/12-room hotel create recovers after delayed sampling, with only one native selection and POST', async () => {
for (const roomCount of [6, 12]) for (const linkageDelays of [[], [6000]]) {
const f = fixture({ linkageDelays });
f.operation.data.arrangement.room_count = roomCount;
const result = await f.api.liveSubmitLifecycleOperation(f.operation);
assert.equal(result.status, 'lifecycle_completed', JSON.stringify(result));
assert.equal(f.fields.get('jianshu1').value, String(roomCount));
assert.equal(f.posts(), 1); assert.equal(f.selections(), 1);
assert.equal(result.preflight.arrangement_linkage.elapsed_ms, linkageDelays.length ? 7500 : 1500);
assert.equal(result.preflight.arrangement_linkage.ready, true);
}
});
test('unstable or persistently delayed hotel linkage records diagnostics and never saves', async () => {
const changing = fixture({ onLinkageTick(fields, tick) { fields.get('jine1').value = String(tick); } });
const paused = fixture({ linkageDelays: Array(6).fill(6000) });
for (const [f, reason] of [[changing, 'fields_changing'], [paused, 'sampling_delayed']]) {
const result = await f.api.liveSubmitLifecycleOperation(f.operation);
assert.equal(result.status, 'lifecycle_apply_blocked', JSON.stringify(result));
assert.equal(result.write_attempted, false); assert.equal(result.no_erp_write, true);
assert.equal(f.posts(), 0); assert.equal(f.selections(), 1);
assert.equal(f.fields.get('zt1').value, '', 'do not continue filling after failed observation');
assert.equal(result.preflight.arrangement_linkage.reason, reason);
assert.ok(result.blockers.includes('arrangement_create_linked_fields_not_stable'));
assert.ok(result.blockers.some(value => value.startsWith(`arrangement_linkage_wait:${reason}:`)));
assert.equal(JSON.stringify(result.preflight.arrangement_linkage).includes('测试新酒店'), false);
}
});
test('hotel create matches the new record after ERP sorts rows and uses persisted evidence on read-only reconciliation', async () => {
const f = fixture({ sort: true });
const result = await f.api.liveSubmitLifecycleOperation(f.operation);