execl问题修复
This commit is contained in:
@@ -1374,7 +1374,7 @@ test('passenger explicit server success is terminal without a post-save row requ
|
||||
assert.doesNotMatch(passengerBranch, /passengerRequery|verifyLifecycleOperation/);
|
||||
assert.doesNotMatch(background, /attemptAutomaticPassengerReconciliation/);
|
||||
assert.match(background, /名单已取得 ERP 明确成功响应,按业务规则确认录入成功/);
|
||||
assert.match(platformApp, /REQUIRED_EXTENSION_VERSION = '0\.5\.172'/);
|
||||
assert.match(platformApp, /REQUIRED_EXTENSION_VERSION = '0\.5\.173'/);
|
||||
});
|
||||
|
||||
test('uncertain lifecycle writes can only converge through a read-only plugin requery', async () => {
|
||||
@@ -1584,7 +1584,7 @@ test('lifecycle execution keeps the MV3 worker alive until the durable task sett
|
||||
assert.match(background, /arrangement_resource_candidate_data_missing/);
|
||||
});
|
||||
|
||||
test('extension 0.5.172 keeps reload dormant unless its durable execution state is fully idle', async () => {
|
||||
test('extension 0.5.173 keeps reload dormant unless its durable execution state is fully idle', async () => {
|
||||
const [background, bridge] = await Promise.all([
|
||||
readFile(new URL('../chrome-extension/ltjt-order-assistant/background.js', import.meta.url), 'utf8'),
|
||||
readFile(new URL('../chrome-extension/ltjt-order-assistant/business-bridge.js', import.meta.url), 'utf8')
|
||||
@@ -2023,7 +2023,7 @@ test('delete guard distinguishes independent, shared child, and shared parent ro
|
||||
for (const operation of operations) assert.equal(plans.validateOperation(operation).ok, true, plans.validateOperation(operation).blockers.join('; '));
|
||||
|
||||
const mapping = JSON.parse(await readFile(new URL('../mappings/lifecycle.mapping.json', import.meta.url), 'utf8'));
|
||||
assert.equal(mapping.current_extension_version, '0.5.172');
|
||||
assert.equal(mapping.current_extension_version, '0.5.173');
|
||||
assert.equal(
|
||||
mapping.updates.order_update_independent.field_mapped_pending_live_validation['pax.child_no_bed'],
|
||||
'ertrenshu'
|
||||
@@ -2407,10 +2407,10 @@ test('schema and browser adapters contain the v2 safety fields and no confirm ov
|
||||
assert.match(inpage, /`ys_danweiid\$\{index\}`, resolvedCustomerId/);
|
||||
assert.doesNotMatch(inpage, /product_customer_source_region|sourceRegionCheck|source_reference/);
|
||||
assert.doesNotMatch(teamBatchInpage, /product_customer_source_region|sourceRegionCheck/);
|
||||
assert.equal(extensionManifest.version, '0.5.172');
|
||||
assert.match(inpage, /version: '0\.5\.172'/);
|
||||
assert.match(teamBatchInpage, /version: '0\.5\.172'/);
|
||||
assert.match(platformApp, /REQUIRED_EXTENSION_VERSION = '0\.5\.172'/);
|
||||
assert.equal(extensionManifest.version, '0.5.173');
|
||||
assert.match(inpage, /version: '0\.5\.173'/);
|
||||
assert.match(teamBatchInpage, /version: '0\.5\.173'/);
|
||||
assert.match(platformApp, /REQUIRED_EXTENSION_VERSION = '0\.5\.173'/);
|
||||
assert.match(inpage, /function strictIsoDate\(value\)/);
|
||||
assert.match(inpage, /const startDate = strictIsoDate\(controlCanonicalValue\(form, 'riqi0'\)\)/);
|
||||
assert.match(inpage, /const endDate = strictIsoDate\(controlCanonicalValue\(form, 'riqis0'\)\)/);
|
||||
|
||||
82
tools/passenger-tsv.test.mjs
Normal file
82
tools/passenger-tsv.test.mjs
Normal file
@@ -0,0 +1,82 @@
|
||||
import assert from 'node:assert/strict';
|
||||
import { readFile } from 'node:fs/promises';
|
||||
import { createRequire } from 'node:module';
|
||||
import test from 'node:test';
|
||||
import vm from 'node:vm';
|
||||
import { validateProgramOperation } from '../LianSyn-platform/external-agent-client.mjs';
|
||||
|
||||
const require = createRequire(import.meta.url);
|
||||
const plans = require('../chrome-extension/ltjt-order-assistant/operation-plans.js');
|
||||
const headers = plans.PASSENGER_HEADERS.join('\t');
|
||||
const row = (sequence, phone = '13800000001', remark = '') => [
|
||||
sequence, `合成游客${sequence}`, 'SYNTHETIC GUEST', '男', '1990-01-01', '合成城市',
|
||||
'护照', `TEST-PASS-${sequence}`, '合成城市', '2025-01-01', '2035-01-01', phone, remark
|
||||
].join('\t');
|
||||
const operation = (text, rowCount = 1, kind = 'independent_order') => ({
|
||||
action: 'passenger_list_import', order_nature: 'formal', submit_mode: 'dry_run',
|
||||
data: {
|
||||
existing_refs: { kind, identifier: 'SYNTH-ORDER-001' },
|
||||
passenger_list: { operation: 'import', row_count: rowCount, text }
|
||||
}
|
||||
});
|
||||
|
||||
test('passenger TSV keeps trailing empty columns through server and plugin dispatch', () => {
|
||||
for (const kind of ['independent_order', 'shared_child_order']) {
|
||||
for (const phone of ['13800000001', '']) {
|
||||
const text = [headers, ...Array.from({ length: 19 }, (_, i) => row(i + 1, phone))].join('\n');
|
||||
for (const input of [text, `\r\n${text.replace(/\n/g, '\r\n')}\r\n\r\n`]) {
|
||||
for (const mode of ['import', 'full_replace']) {
|
||||
const candidate = operation(input, 19, kind);
|
||||
Object.assign(candidate.data.passenger_list, mode === 'full_replace'
|
||||
? { operation: mode, confirmed: true } : { operation: mode });
|
||||
assert.deepEqual(validateProgramOperation(candidate), []);
|
||||
assert.deepEqual(plans.validateDispatchOperation(candidate).blockers, []);
|
||||
assert.equal(plans.buildPassengerTsv(candidate.data.passenger_list), text);
|
||||
assert.equal(candidate.data.passenger_list.text, input);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
test('passenger TSV still rejects missing or surplus columns and keeps leader validation', () => {
|
||||
for (const malformed of [row(1).slice(0, -1), `${row(1)}\t`]) {
|
||||
const candidate = operation(`${headers}\n${malformed}`);
|
||||
assert.match(validateProgramOperation(candidate).join('\n'), /完整 13 列/);
|
||||
assert.match(plans.validateDispatchOperation(candidate).blockers.join('\n'), /13 列/);
|
||||
}
|
||||
const candidate = operation(`${headers}\n${row(1, '13800000001', '领队')}\n${row(2, '')}`, 2);
|
||||
assert.match(validateProgramOperation(candidate).join('\n'), /leader_contact/);
|
||||
assert.match(plans.validateDispatchOperation(candidate).blockers.join('\n'), /leader_contact/);
|
||||
candidate.data.passenger_list.leader_contact = { sequence: 1, name: '合成游客1', phone: '13800000001' };
|
||||
assert.deepEqual(validateProgramOperation(candidate), []);
|
||||
assert.deepEqual(plans.validateDispatchOperation(candidate).blockers, []);
|
||||
candidate.data.passenger_list.leader_contact.phone = '13800000002';
|
||||
assert.match(validateProgramOperation(candidate).join('\n'), /完全一致/);
|
||||
assert.match(plans.validateDispatchOperation(candidate).blockers.join('\n'), /完全一致/);
|
||||
});
|
||||
|
||||
test('passenger merge accepts empty final fields without repairing malformed column counts', async () => {
|
||||
const source = await readFile(new URL('../chrome-extension/ltjt-order-assistant/lifecycle-adapters.js', import.meta.url), 'utf8');
|
||||
const sandbox = { window: { LTJTOrderAssistant: {} } };
|
||||
vm.runInNewContext(source, sandbox);
|
||||
const merge = sandbox.window.LTJTOrderAssistant.planPassengerMerge;
|
||||
const blankRows = Array.from({ length: 19 }, (_, i) => Object.fromEntries(plans.PASSENGER_HEADERS.map(header => [
|
||||
header, header === '序号' ? i + 1 : header === '证件类型' ? '护照' : ''
|
||||
])));
|
||||
for (const phone of ['13800000001', '']) {
|
||||
const text = [headers, ...Array.from({ length: 19 }, (_, i) => row(i + 1, phone))].join('\n');
|
||||
for (const input of [text, `\r\n${text.replace(/\n/g, '\r\n')}\r\n`]) {
|
||||
const result = merge(blankRows, { operation: 'first_import', row_count: 19, text: input }, 19);
|
||||
assert.deepEqual([...result.blockers], []);
|
||||
assert.equal(result.merged_tsv, text);
|
||||
assert.equal(result.input_rows[18]['电话'], phone);
|
||||
assert.equal(result.input_rows[18]['备注'], '');
|
||||
assert.equal(result.changed_sequences.length, 19);
|
||||
}
|
||||
}
|
||||
for (const malformed of [row(1).slice(0, -1), `${row(1)}\t`]) {
|
||||
const result = merge(blankRows, { operation: 'first_import', row_count: 1, text: `${headers}\n${malformed}` }, 19);
|
||||
assert.ok(result.blockers.includes('passenger_input_row_columns_incomplete'));
|
||||
}
|
||||
});
|
||||
Reference in New Issue
Block a user