import assert from 'node:assert/strict';
import { existsSync, readFileSync } from 'node:fs';
import { fileURLToPath } from 'node:url';
import path from 'node:path';
import { test } from 'node:test';
const prototypePath = path.resolve(path.dirname(fileURLToPath(import.meta.url)), '..', '..', '官网头程下单', 'workbench.html');
const html = existsSync(prototypePath) ? readFileSync(prototypePath, 'utf8') : '';
function fn(name) {
const start = html.indexOf(`function ${name}(`);
assert.ok(start >= 0, `${name} should exist`);
const next = html.indexOf('\n function ', start + 1);
return html.slice(start, next >= 0 ? next : html.length);
}
test('sea order navigation exposes only three business entry points', () => {
const group = html.match(/([\s\S]*?)/);
assert.ok(group, 'sea order menu should exist');
assert.equal((group[1].match(/data-sea-action=/g) || []).length, 0);
const entries = [...group[1].matchAll(/data-business="(Procurement|Truck|Pallet)"[^>]*onclick="([^"]+)"/g)];
assert.equal(entries.length, 3);
for (const [type, label] of [['Procurement', '海外采购'], ['Truck', '美国本土卡'], ['Pallet', '美本土散板']]) {
const entry = entries.find(([, , onclick]) => onclick.includes(`openSeaBusiness('${type}','list'`));
assert.ok(entry, `${label} navigation entry should open its list page`);
assert.match(entry[0], new RegExp(`data-business="${type}"`));
}
});
test('three sea business list pages include add, query, and order lists', () => {
const cases = [
['sea-procurement-page', 'Procurement', '海外采购', ['订单号', '采购品类', '商品规格', '采购数量', '预算单价', '状态', '操作']],
['sea-truck-page', 'Truck', '美国本土卡', ['操作', '订单编号', '运输类型', '起运地', '目的地', '柜型', '总重量(kg)', '预算总价', '要求时间', '状态']],
['sea-pallet-page', 'Pallet', '美本土散板', ['操作', '订单编号', '运输方式', '是否打盘', '运输类型', '起运地', '目的地', '总重量(kg)', '预算总价', '要求时间', '状态']],
];
for (const [id, type, label, headers] of cases) {
const start = html.indexOf(`id="${id}"`);
assert.ok(start >= 0, `${id} should exist`);
const page = html.slice(start, html.indexOf('', start) + 10);
assert.match(page, new RegExp(label));
assert.match(page, new RegExp(`openSeaBusiness\\('${type}','new'`));
assert.match(page, new RegExp(`querySeaOrders\\('${type}'\\)`));
assert.match(page, new RegExp(`resetSeaOrders\\('${type}'\\)`));
for (const header of headers) assert.match(page, new RegExp(`
${header.replace(/[.*+?^${}()|[\]\\]/g, '\\$&')} | `));
}
const truckStart = html.indexOf('id="sea-truck-page"');
const truckPage = html.slice(truckStart, html.indexOf('', truckStart) + 10);
assert.doesNotMatch(truckPage, /联系人<\/th>| | 联系方式<\/th>/);
assert.match(html.slice(html.indexOf('data-order-form="Truck"'), html.indexOf('', html.indexOf('data-order-form="Truck"'))), /name="预算总价"/);
const palletStart = html.indexOf('id="sea-pallet-page"');
const palletPage = html.slice(palletStart, html.indexOf('', palletStart) + 10);
assert.doesNotMatch(palletPage, / | 联系人<\/th>| | 联系方式<\/th>/);
assert.match(html.slice(html.indexOf('data-order-form="Pallet"'), html.indexOf('', html.indexOf('data-order-form="Pallet"'))), /name="预算总价"/);
});
test('all sea business orders support edit and detail actions', () => {
for (const name of ['openSeaOrderEditor', 'closeSeaOrderEditor', 'saveSeaOrderEdit', 'showSeaOrderDetail']) fn(name);
assert.match(fn('renderSeaOrders'), /openSeaOrderEditor/);
assert.match(fn('renderSeaOrders'), /showSeaOrderDetail/);
assert.match(html, /id="sea-order-edit-modal"/);
assert.match(html, /id="sea-order-edit-form"/);
assert.match(fn('openSeaOrderEditor'), /data-order-form/);
assert.match(fn('saveSeaOrderEdit'), /seaOrders\[type\]/);
});
test('sea business details expose business, carrier, and progress information', () => {
const details = [
['sea-procurement-detail', ['商品信息', '订单信息', '快递信息']],
['sea-truck-detail', ['运输信息', '货物信息', '承运商信息', '运输进度']],
['sea-pallet-detail', ['运输信息', '货物信息', '承运商信息', '运输进度']],
];
for (const [id, sections] of details) {
const start = html.indexOf(`id="${id}"`);
assert.ok(start >= 0, `${id} should exist`);
const detail = html.slice(start, html.indexOf('', start) + 10);
for (const section of sections) assert.match(detail, new RegExp(section));
assert.match(detail, /data-detail-content/);
}
const procurementDetail = html.slice(html.indexOf('id="sea-procurement-detail"'), html.indexOf('', html.indexOf('id="sea-procurement-detail"')) + 10);
assert.doesNotMatch(procurementDetail, /采购进度/);
assert.doesNotMatch(procurementDetail, /承运商信息/);
assert.match(procurementDetail, /data-detail-content="预算总价"/);
for (const field of ['订单号', '采购数量', '预算单价', '订单状态', '联系人', '联系电话', '收货地址', '订单备注']) {
assert.match(procurementDetail, new RegExp(field));
}
for (const field of ['国内快递公司', '国内运单号', '海外快递公司', '海外运单号']) {
assert.match(procurementDetail, new RegExp(`data-detail-content="${field}"`));
}
});
test('sea business routing reuses existing forms and isolates order state', () => {
for (const name of ['showSeaBusinessPage', 'showSeaBusinessOrderForm', 'openSeaBusiness', 'renderSeaOrders', 'querySeaOrders', 'resetSeaOrders']) fn(name);
assert.match(html, /const\s+seaOrders\s*=\s*\{\s*Procurement:\s*\[/);
assert.match(html, /data-order-form="Procurement"/);
assert.match(html, /data-order-form="Truck"/);
assert.match(html, /data-order-form="Pallet"/);
assert.doesNotMatch(fn('openSeaBusiness'), /data-sea-action/);
assert.match(fn('openSeaBusiness'), /dash-nav-link\[data-business=/);
assert.match(fn('openOrder'), /openSeaBusiness\(type,'new'/);
assert.match(fn('querySeaOrders'), /seaOrders\[type\]/);
assert.match(html, /function\s+collectSeaOrderFields\s*\(/);
});
test('sea business controls match overseas warehouse colors', () => {
const styleStart = html.indexOf('.sea-business-page');
const styleEnd = html.indexOf('', styleStart);
const styles = html.slice(styleStart, styleEnd);
assert.match(styles, /\.sea-business-page[^{}]*\.btn-primary|\.sea-business-form-panel[^{}]*\.btn-primary/);
assert.match(styles, /#667eea/);
assert.match(styles, /#764ba2/);
assert.match(styles, /\.sea-business-page \.sea-order-table th/);
assert.match(styles, /color:\s*#667eea/);
});
|