Files
docs/悦/货代SAAS平台后台/tests/verify-last-mile-hold-outbound.cjs
T

115 lines
5.7 KiB
JavaScript
Raw Normal View History

2026-08-12 19:11:56 +08:00
#!/usr/bin/env node
const fs = require('node:fs');
const path = require('node:path');
const vm = require('node:vm');
2026-08-21 09:20:26 +08:00
const root = path.resolve(__dirname, '..');
const manifest = JSON.parse(fs.readFileSync(path.join(root, 'prototype-src', 'manifest.json'), 'utf8'));
const html = fs.readFileSync(path.join(root, manifest.source), 'utf8');
2026-08-12 19:11:56 +08:00
const failures = [];
function expect(condition, message) { if (!condition) failures.push(message); }
function section(startMarker, endMarker) {
const start = html.indexOf(startMarker);
const end = html.indexOf(endMarker, start + startMarker.length);
return start >= 0 && end > start ? html.slice(start, end) : '';
}
function functionSource(name) {
const start = html.indexOf(`function ${name}(`);
if (start < 0) return '';
const braceStart = html.indexOf('{', start);
let depth = 0; let quote = ''; let escaped = false;
for (let index = braceStart; index < html.length; index += 1) {
const char = html[index];
if (quote) {
if (escaped) escaped = false;
else if (char === '\\') escaped = true;
else if (char === quote) quote = '';
continue;
}
if (char === "'" || char === '"' || char === '`') { quote = char; continue; }
if (char === '{') depth += 1;
if (char === '}' && --depth === 0) return html.slice(start, index + 1);
}
return '';
}
const lastMilePage = section('<div class="page" id="page-last-mile-orders">', '<!-- ==================== OVERSEAS WAREHOUSE - 尾程订单详情');
const renderList = functionSource('renderLastMileOrders');
const renderOperations = functionSource('renderLastMileOperationItems');
const renderDetail = functionSource('renderLastMileOrderDetail');
const getFirstLeg = functionSource('getLastMileFirstLegOrder');
const isDetained = functionSource('isLastMileOrderDetained');
const openOutbound = functionSource('openLastMileOutboundPlan');
const saveOutbound = functionSource('saveLastMileOutboundPlan');
expect(/>是否暂扣<\/th>/.test(lastMilePage), '尾程订单列表应显示是否暂扣列');
expect(/isLastMileOrderDetained/.test(renderList), '尾程订单列表应实时渲染暂扣状态');
expect(/是否暂扣/.test(renderDetail), '尾程订单详情应显示是否暂扣');
expect(Boolean(getFirstLeg), '缺少 getLastMileFirstLegOrder 函数');
expect(Boolean(isDetained), '缺少 isLastMileOrderDetained 函数');
expect(/isLastMileOrderDetained/.test(renderOperations) && /不能创建出库单/.test(renderOperations), '列表出库计划操作应在暂扣时禁用');
expect(/isLastMileOrderDetained/.test(openOutbound) && /不能创建出库单/.test(openOutbound), '打开出库计划应拦截暂扣订单');
expect(/isLastMileOrderDetained/.test(saveOutbound) && /不能创建出库单/.test(saveOutbound), '保存出库计划应二次拦截暂扣订单');
expect(/isDetained\s*:\s*true/.test(html), '应提供一条暂扣头程订单样例');
if (getFirstLeg && isDetained) {
try {
const context = {lastMileFirstLegSamples: [
{firstLegNo: 'H-BOOL', isDetained: true},
{firstLegNo: 'H-TEXT', detainFlag: '是'},
{firstLegNo: 'H-NUM', holdStatus: 1},
{firstLegNo: 'H-NO', isDetained: false}
]};
vm.createContext(context);
vm.runInContext(`${getFirstLeg}\n${isDetained}`, context, {timeout: 1000});
expect(context.isLastMileOrderDetained({firstLegNo: 'H-BOOL'}) === true, '应识别布尔暂扣状态');
expect(context.isLastMileOrderDetained({firstLegNo: 'H-TEXT'}) === true, '应识别“是”暂扣状态');
expect(context.isLastMileOrderDetained({firstLegNo: 'H-NUM'}) === true, '应识别数值暂扣状态');
expect(context.isLastMileOrderDetained({firstLegNo: 'H-NO'}) === false, '解除暂扣后应立即恢复');
expect(context.isLastMileOrderDetained({firstLegNo: 'UNKNOWN'}) === false, '未知头程订单应按未暂扣处理');
} catch (error) {
failures.push(`暂扣判断行为执行失败:${error.message}`);
}
}
if (openOutbound && saveOutbound && getFirstLeg && isDetained) {
try {
const order = {no:'LMO-HOLD',firstLegNo:'H-HOLD',fbaWarehouse:'FBA ONT8',cargo:[],logs:[]};
const elements = {
'lmo-outbound-date': {value:'2026-08-20'},
'lmo-outbound-fba': {value:'FBA ONT8'},
'lmo-outbound-mode': {value:'卡车派送'},
'lmo-outbound-remark': {value:'',trim(){return '';}}
};
const calls = {modal:0,toast:[],hidden:0,refresh:0};
const context = {
lastMileFirstLegSamples:[{firstLegNo:'H-HOLD',isDetained:true}],
lastMileOrderData:[order],currentLastMileActionNo:'',fbaOutboundOrderData:[],
lmoActionOrder(){this.currentLastMileActionNo=order.no;return order;},
document:{getElementById:id=>elements[id]},
showModal(){calls.modal++;},hideModal(){calls.hidden++;},
showToast(message,type){calls.toast.push({message,type});},
lmoNow:()=> '2026-08-12 10:00',refreshLastMileViews(){calls.refresh++;}
};
vm.createContext(context);
vm.runInContext(`${getFirstLeg}\n${isDetained}\n${openOutbound}\n${saveOutbound}`, context, {timeout:1000});
context.openLastMileOutboundPlan(order.no);
expect(calls.modal===0, '暂扣订单不应打开出库计划弹窗');
context.currentLastMileActionNo=order.no;
context.saveLastMileOutboundPlan();
expect(!order.outboundPlan && !order.outboundNo && context.fbaOutboundOrderData.length===0, '暂扣订单不应生成出库计划或出库单');
expect(calls.toast.some(item=>/暂扣/.test(item.message)), '暂扣拦截应显示明确提示');
} catch (error) {
failures.push(`暂扣出库拦截行为执行失败:${error.message}`);
}
}
if (failures.length) {
console.error('LAST_MILE_HOLD_OUTBOUND_CHECK_FAIL');
failures.forEach(failure => console.error(`- ${failure}`));
process.exitCode = 1;
} else {
console.log('LAST_MILE_HOLD_OUTBOUND_CHECK_PASS');
}