Files
docs/悦/PDA(海外)/tests/packing-direct-inbound.runtime.test.js
2026-09-08 14:05:30 +08:00

72 lines
4.0 KiB
JavaScript

const assert = require('node:assert/strict');
const fs = require('node:fs');
const path = require('node:path');
const applicationSource = fs.readFileSync(path.join(__dirname, '..', 'assets', 'app.js'), 'utf8')
.replace(/\s*bootstrap\(\);\s*$/, '');
const runtimeTests = String.raw`
render=()=>{};
let lastToast=null;
toast=(message,type)=>{lastToast={message,type}};
const entries=internalEntriesMarkup();
assert.ok(entries.indexOf("navigate('packing')")>=0, 'packing entry is missing');
assert.ok(entries.indexOf("navigate('packing')")<entries.indexOf("navigate('relabel')"), 'packing entry must appear before relabeling');
state.page='packing';
state.packingMessage={type:'good',text:'READY'};
const view=packingView();
assert.match(view,/id="packing-scan"/, 'packing scan input is missing');
assert.match(view,/id="packing-customer-code"[^>]*required/, 'required customer short-code input is missing');
assert.match(view,/packing-scan-card[\s\S]*?<\/section><section class="work-card packing-customer-card"[\s\S]*?id="packing-customer-code"/, 'scan and customer information must render as separate modules');
const customerModule=view.match(/<section class="work-card packing-customer-card">([\s\S]*?)<\/section>/)?.[1]||'';
assert.doesNotMatch(customerModule,/<h2>/, 'customer module must not show a duplicate customer information heading');
assert.equal((customerModule.match(/<label\b/g)||[]).length,1, 'customer module must show one field label');
assert.match(customerModule,new RegExp('<label[^>]*>'+t('customerCode')+' \\*</label>'), 'customer module must label the field as customer code');
assert.match(view,/role="status" aria-live="polite"/, 'successful scan feedback must be announced');
assert.match(view,/packing-details-table/, 'carton details table is missing');
assert.match(view,/YQ-CASE-01[\s\S]*YQ-CABLE-02[\s\S]*YQ-HOLDER-03/, 'carton detail rows are missing');
assert.match(view,/confirmPackingInbound\(\)/, 'direct inbound action is missing');
assert.doesNotMatch(view,/packing-pallet-quantity|pallet-quantity-card/, 'pallet quantity module must stay hidden');
state.packingMessage=null;
state.packingCustomerCode='CUS-01';
document.__input='YQ-CABLE-02';
handlePackingScan();
assert.equal(state.packingMessage.type,'good');
assert.match(state.packingMessage.text,/YQ-CABLE-02/);
assert.equal(document.__focused,'packing-scan', 'packing scan input must regain focus after a scan');
assert.match(packingView(),/value="CUS-01"/, 'customer short code must survive scan re-renders');
state.page='packing';
state.packingInboundDone=false;
state.packingCustomerCode=' ';
confirmPackingInbound();
assert.equal(state.packingInboundDone,false, 'empty customer short code must block inbound');
assert.equal(state.page,'packing', 'validation failure must stay on the packing page');
assert.equal(state.packingCustomerError,t('customerCodeRequired'));
assert.equal(document.__focused,'packing-customer-code', 'invalid customer short code must receive focus');
state.packingCustomerCode=' CUS-01 ';
confirmPackingInbound();
assert.equal(state.packingInboundDone,true, 'confirmation must complete direct inbound');
assert.equal(state.page,'workbench', 'confirmation must return to the order list');
assert.equal(state.packingCustomerCode,'', 'successful inbound must clear the customer short code');
assert.deepEqual(lastToast,{message:t('packingInboundDone'),type:'good'});
`;
const documentStub = {
__input: '',
__focused: '',
getElementById(id) {
if (id === 'packing-scan') return { value: this.__input, focus: () => { this.__focused = id; } };
if (id === 'packing-customer-code') return { value: '', focus: () => { this.__focused = id; } };
return null;
}
};
const run = new Function('assert', 'localStorage', 'document', 'window', applicationSource + '\n' + runtimeTests);
run(assert, { getItem: () => null, setItem: () => {} }, documentStub, { scrollTo: () => {}, requestAnimationFrame: callback => callback() });
process.stdout.write('PASS: packing entry, hidden pallet quantity, scan, and direct inbound behavior\n');