147 lines
6.2 KiB
JavaScript
147 lines
6.2 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 tests = [];
|
|
const runtimeTests = String.raw`
|
|
render=()=>{};
|
|
showModal=(message,onConfirm)=>{globalThis.__lastModal={message,onConfirm}};
|
|
closeModal=()=>{};
|
|
toast=()=>{};
|
|
|
|
function test(name,fn){tests.push({name,fn})}
|
|
|
|
test('consolidation ignores dropship pallet lookup and clears type inputs',()=>{
|
|
state.palletOrderType='dropship';
|
|
state.fbaPalletLabels=['D4444-TC-001'];
|
|
state.dropshipPalletLabel='D2222-TC-001';
|
|
state.palletTypeMessage={type:'error',text:'stale'};
|
|
state.fbaPalletMessage={type:'error',text:'stale'};
|
|
state.dropshipScanMessage={type:'error',text:'stale'};
|
|
startConsolidation();
|
|
assert.deepEqual(state.fbaPalletLabels,[]);
|
|
assert.equal(state.dropshipPalletLabel,'');
|
|
assert.equal(state.palletTypeMessage,null);
|
|
assert.equal(state.fbaPalletMessage,null);
|
|
assert.equal(state.dropshipScanMessage,null);
|
|
|
|
state.pallet={id:'DRAFT',mode:'consolidate',planId:null,targetPallets:null,destinationCode:'',destinationAddress:'',items:[]};
|
|
document.__input='D2222-TC-001';
|
|
handlePalletScan();
|
|
assert.equal(state.pallet.items.length,0,'consolidation must not import an existing pallet');
|
|
assert.equal(state.dropshipPalletLabel,'');
|
|
});
|
|
|
|
test('starting and selecting jobs reset type-specific inputs',()=>{
|
|
state.palletMode='palletize';
|
|
state.selectedPlanId='INB-260819-026';
|
|
state.fbaPalletLabels=['D4444-TC-001'];
|
|
state.dropshipPalletLabel='D2222-TC-001';
|
|
state.fbaPalletMessage={type:'error',text:'stale'};
|
|
state.dropshipScanMessage={type:'error',text:'stale'};
|
|
startPallet();
|
|
assert.deepEqual(state.fbaPalletLabels,[]);
|
|
assert.equal(state.dropshipPalletLabel,'');
|
|
assert.equal(state.fbaPalletMessage,null);
|
|
assert.equal(state.dropshipScanMessage,null);
|
|
|
|
state.fbaPalletLabels=['D4444-TC-002'];
|
|
state.dropshipPalletLabel='D2222-TC-001';
|
|
selectPallet('D4444-TC-003','INB-260819-026');
|
|
assert.deepEqual(state.fbaPalletLabels,[]);
|
|
assert.equal(state.dropshipPalletLabel,'');
|
|
|
|
state.fbaPalletLabels=['D4444-TC-004'];
|
|
state.dropshipPalletLabel='D2222-TC-001';
|
|
document.__input='BX-88401-01';
|
|
handlePalletTopScan();
|
|
assert.deepEqual(state.fbaPalletLabels,[]);
|
|
assert.equal(state.dropshipPalletLabel,'');
|
|
|
|
state.fbaPalletLabels=['D4444-TC-005'];
|
|
state.dropshipPalletLabel='D2222-TC-001';
|
|
startNewConsolidation();
|
|
assert.deepEqual(state.fbaPalletLabels,[]);
|
|
assert.equal(state.dropshipPalletLabel,'');
|
|
|
|
state.fbaPalletLabels=['D4444-TC-006'];
|
|
state.dropshipPalletLabel='D2222-TC-001';
|
|
reconsolidatePallet('D2222-TC-019');
|
|
assert.deepEqual(state.fbaPalletLabels,[]);
|
|
assert.equal(state.dropshipPalletLabel,'');
|
|
});
|
|
|
|
test('FBA selector disables occupied labels and every label for persisted pallets',()=>{
|
|
state.palletOrderType='fba';
|
|
state.pallet={id:'',mode:'palletize',planId:'INB-260819-018',items:[],persisted:false};
|
|
let markup=fbaPalletLabelSelector(plans[0]);
|
|
assert.match(markup,/D2222-TC-001[\s\S]*?<\/button>/);
|
|
const occupiedButton=markup.match(/<button[^>]*>[\s\S]*?D2222-TC-001[\s\S]*?<\/button>/)?.[0]||'';
|
|
assert.match(occupiedButton,/disabled/);
|
|
|
|
state.pallet.persisted=true;
|
|
markup=fbaPalletLabelSelector(plans[0]);
|
|
const buttons=[...markup.matchAll(/<button[^>]*class="fba-pallet-choice[^>]*>/g)].map(match=>match[0]);
|
|
assert.ok(buttons.length>1);
|
|
assert.ok(buttons.every(button=>button.includes('disabled')));
|
|
});
|
|
|
|
test('FBA and dropship validation messages render in their owning modules',()=>{
|
|
state.palletMode='palletize';
|
|
state.selectedPlanId='INB-260819-026';
|
|
state.pallet={id:'',mode:'palletize',planId:'INB-260819-026',destinationCode:'',destinationAddress:'',items:[]};
|
|
state.fbaPalletMessage={type:'error',text:'FBA_MESSAGE'};
|
|
const selector=fbaPalletLabelSelector(plans[2]);
|
|
assert.match(selector,/fba-pallet-selector[\s\S]*FBA_MESSAGE/);
|
|
|
|
state.palletOrderType='dropship';
|
|
state.fbaPalletMessage=null;
|
|
state.dropshipScanMessage={type:'error',text:'DROPSHIP_MESSAGE'};
|
|
const view=palletView();
|
|
const scanStart=view.indexOf('pallet-type-scan');
|
|
const scanEnd=view.indexOf('</section>',scanStart);
|
|
assert.ok(scanStart>=0 && view.slice(scanStart,scanEnd).includes('DROPSHIP_MESSAGE'));
|
|
});
|
|
|
|
test('FBA submission materializes every available selected label exactly once',()=>{
|
|
const plan=plans[2];
|
|
const originalPallets=state.pallets.map(pallet=>JSON.parse(JSON.stringify(pallet)));
|
|
const originalReceived=plan.receivedPallets;
|
|
const source=cargo.find(item=>item.id==='C-004');
|
|
source.palletNo='';
|
|
state.pallets=originalPallets;
|
|
state.selectedPlanId=plan.id;
|
|
state.palletMode='palletize';
|
|
state.palletOrderType='fba';
|
|
state.fbaPalletLabels=['D4444-TC-001','D4444-TC-002'];
|
|
state.pallet={id:'',mode:'palletize',planId:plan.id,targetPallets:plan.expectedPallets,destinationCode:source.destinationCode,destinationAddress:source.destinationAddress,items:[{...source}]};
|
|
submitPallet();
|
|
|
|
const created=state.pallets.filter(pallet=>['D4444-TC-001','D4444-TC-002'].includes(pallet.id));
|
|
assert.equal(created.length,2);
|
|
assert.equal(new Set(created.map(pallet=>pallet.id)).size,2);
|
|
assert.equal(created.reduce((count,pallet)=>count+pallet.items.length,0),1,'cargo must be linked once across the selected pallets');
|
|
assert.equal(source.palletNo,'D4444-TC-001');
|
|
assert.equal(plan.receivedPallets,Math.min(plan.expectedPallets,originalReceived+2));
|
|
});
|
|
|
|
for(const entry of tests){
|
|
try{entry.fn();process.stdout.write('PASS: '+entry.name+'\n')}
|
|
catch(error){process.stderr.write('FAIL: '+entry.name+'\n'+error.stack+'\n');globalThis.__failed=(globalThis.__failed||0)+1}
|
|
}
|
|
if(globalThis.__failed)throw new Error(globalThis.__failed+' runtime behavior test(s) failed');
|
|
`;
|
|
|
|
const documentStub = {
|
|
__input: '',
|
|
getElementById(id) {
|
|
if (id === 'pallet-scan' || id === 'pallet-top-scan') return { value: this.__input };
|
|
return null;
|
|
}
|
|
};
|
|
|
|
const run = new Function('assert', 'tests', 'localStorage', 'document', 'window', applicationSource + '\n' + runtimeTests);
|
|
run(assert, tests, { getItem: () => null, setItem: () => {} }, documentStub, { scrollTo: () => {} });
|