import test from 'node:test' import assert from 'node:assert/strict' import { readFileSync } from 'node:fs' import vm from 'node:vm' function setup(confirm, saved = new Map(), scope = 'operator:warehouse') { const context = vm.createContext({ reactive: value => value, ReturnLabelConfirmation: {}, PortalHeader: {}, ScanTargetInput: {}, playSuccessSound() {}, playErrorSound() {}, confirmReturnReceipt: confirm, uni: { setStorageSync: (key, value) => saved.set(key, structuredClone(value)), getStorageSync: key => saved.get(key), removeStorageSync: key => saved.delete(key) } }) const store = readFileSync(new URL('../src/stores/warehouse-work.js', import.meta.url), 'utf8') vm.runInContext(store.replace(/^import .*$/mg, '').replace(/export /g, ''), context) const page = readFileSync(new URL('../src/pages/return-receipt/return-receipt.vue', import.meta.url), 'utf8') const script = page.match(/]*>([\s\S]*?)<\/script>/)[1] const component = vm.runInContext(script.replace(/^\s*import .*$/mg, '').replace('export default', 'globalThis.component ='), context) vm.runInContext(`restoreWarehouseWork(${JSON.stringify(scope)})`, context) const instance = Object.assign({}, component.methods, { unitType: 'PALLET', palletBoxCount: 1, canConfirm: true, busy: false, current: { returnNo: 'RT-TEST', expectedItems: [{ skuCode: 'SKU-TEST', expectedQuantity: 10, receivedQuantity: 0 }] }, selectedItems: [{ skuCode: 'SKU-TEST' }], photoFileIds: [], trackingNo: ' TRACK-TEST ', startedBy: 'SKU', palletCode: ' PLT-TEST ', palletLength: 10, palletWidth: 10, palletHeight: 10, palletWeight: 1, quantity: () => 2, boxCount: () => 1 }) Object.defineProperty(instance, 'receiptBatch', { get: () => vm.runInContext('warehouseWork.returnReceipt.pendingBatch', context) }) return instance } test('SKU lookup displays all pending order lines while retaining scanned SKU for pallet generation', () => { const source = readFileSync(new URL('../src/pages/return-receipt/return-receipt.vue', import.meta.url), 'utf8') const script = source.match(/]*>([\s\S]*?)<\/script>/)[1] const component = vm.runInNewContext(script.replace(/^\s*import .*$/mg, '').replace('export default', 'globalThis.component ='), { ReturnLabelConfirmation: {}, PortalHeader: {}, ScanTargetInput: {} }) const lines = [{ skuCode: 'SKU-A', expectedQuantity: 6 }, { skuCode: 'SKU-B', expectedQuantity: 4 }] const instance = { current: { expectedItems: lines }, selectedSku: 'SKU-A' } instance.selectedItems = component.computed.selectedItems.call(instance) assert.equal(instance.selectedItems.length, 2) assert.equal(instance.selectedItems[1].skuCode, 'SKU-B') assert.equal(component.computed.activeSkuCode.call(instance), 'SKU-A') instance.selectedSku = '' assert.equal(component.computed.activeSkuCode.call(instance), 'SKU-A') instance.selectedSku = 'SKU-FROM-PREVIOUS-ORDER' assert.equal(component.computed.activeSkuCode.call(instance), 'SKU-A') }) test('PALLET page submits the required palletCode through the actual confirmation method', async () => { const calls = [] const page = setup(async payload => { calls.push(JSON.parse(JSON.stringify(payload))); return { palletCode: payload.palletCode } }) await page.confirmReceipt() assert.equal(calls.length, 1) assert.equal(calls[0].palletCode, 'PLT-TEST') assert.equal(calls[0].unitCode, undefined) assert.deepEqual(Object.keys(calls[0]).sort(), ['height', 'idempotencyKey', 'items', 'length', 'palletCode', 'returnNo', 'startedBy', 'totalBoxCount', 'trackingNo', 'unitType', 'weight', 'width'].sort()) assert.equal(calls[0].unitType, 'PALLET') assert.equal(calls[0].totalBoxCount, 1) assert.deepEqual(Object.keys(calls[0].items[0]).sort(), ['boxCount', 'receivedQuantity', 'skuCode'].sort()) assert.equal(calls[0].returnNo, 'RT-TEST') assert.equal(calls[0].trackingNo, 'TRACK-TEST') assert.equal(calls[0].items[0].receivedQuantity, 2) assert.ok(calls[0].idempotencyKey) assert.equal(page.current, null) }) test('parcel signing allows an empty code but still rejects quantities above the remaining amount', async () => { const source = readFileSync(new URL('../src/pages/return-receipt/return-receipt.vue', import.meta.url), 'utf8') const component = vm.runInNewContext(source.match(/]*>([\s\S]*?)<\/script>/)[1].replace(/^\s*import .*$/mg, '').replace('export default', 'globalThis.component ='), { ReturnLabelConfirmation: {}, PortalHeader: {}, ScanTargetInput: {} }) const state = { current: {}, selectedItems: [{ skuCode: 'A' }], receiptQuantity: 2, unitType: 'PARCEL', boxRows: [{ items: { A: 2 } }], remaining: () => 3 } assert.equal(component.computed.canConfirm.call(state), true) state.boxRows[0].items.A = 4 assert.equal(component.computed.canConfirm.call(state), false) const calls = [] const page = setup(async payload => { calls.push(payload); return { unitType: 'PARCEL' } }) page.unitType = 'PARCEL'; page.unitCode = ''; page.trackingNo = ''; page.boxRows = [{ items: { 'SKU-TEST': 2 } }] await page.confirmReceipt() assert.equal(calls.length, 1) assert.equal(calls[0].trackingNo, undefined) assert.equal(calls[0].unitCode, undefined) assert.equal(calls[0].palletCode, undefined) }) test('parcel waybill is submitted as trackingNo and leaves unitCode for the server', async () => { const calls = [] const page = setup(async payload => { calls.push(payload); return { unitType: 'PARCEL' } }) page.unitType = 'PARCEL'; page.unitCode = ' sf561626 '; page.trackingNo = 'stale-from-pallet'; page.boxRows = [{ items: { 'SKU-TEST': 2 } }] await page.confirmReceipt() assert.equal(calls[0].trackingNo, 'sf561626') assert.equal(calls[0].unitCode, undefined) assert.equal(calls[0].palletCode, undefined) }) test('batch waybill scans stay on the single parcel waybill input', () => { const page = setup(async () => ({})) page.unitType = 'PARCEL'; page.activeTarget = 'unit'; page.palletCode = '' page.handleScan('WAYBILL-ONE') assert.equal(page.unitCode, 'WAYBILL-ONE'); assert.equal(page.palletCode, '') assert.equal(page.activeTarget, 'unit') page.handleScan('WAYBILL-CORRECTED') assert.equal(page.unitCode, 'WAYBILL-CORRECTED') }) test('parcel rows must be nonempty and summed quantities cannot exceed the order remainder', () => { const source = readFileSync(new URL('../src/pages/return-receipt/return-receipt.vue', import.meta.url), 'utf8') const component = vm.runInNewContext(source.match(/]*>([\s\S]*?)<\/script>/)[1].replace(/^\s*import .*$/mg, '').replace('export default', 'globalThis.component ='), { ReturnLabelConfirmation: {}, PortalHeader: {}, ScanTargetInput: {} }) const state = { current: {}, selectedItems: [{ skuCode: 'A' }], receiptQuantity: 4, unitType: 'PARCEL', boxRows: [{ items: { A: 2 } }, { items: { A: 2 } }], remaining: () => 3 } assert.equal(component.computed.canConfirm.call(state), false) state.remaining = () => 5 assert.equal(component.computed.canConfirm.call(state), true) state.boxRows[1].items = {} assert.equal(component.computed.canConfirm.call(state), false) }) test('one submission signs multiple mixed-SKU parcels sharing one waybill and independent labels', async () => { const calls = [] const page = setup(async request => { calls.push(JSON.parse(JSON.stringify(request))) return { unitType: 'PARCEL', labels: [{ cartonMark: `RP-${calls.length}`, printableHtml: 'label' }], fullyMatched: false } }) page.unitType = 'PARCEL'; page.unitCode = ' WAYBILL-BATCH '; page.trackingNo = 'stale'; page.selectedItems = [{ skuCode: 'SKU-TEST' }, { skuCode: 'SKU-B' }] page.boxRows = [{ items: { 'SKU-TEST': 1, 'SKU-B': 2 } }, { items: { 'SKU-TEST': 3 } }] await page.confirmReceipt() assert.equal(calls.length, 2) assert.deepEqual(calls[0].items, [{ skuCode: 'SKU-TEST', receivedQuantity: 1 }, { skuCode: 'SKU-B', receivedQuantity: 2 }]) assert.deepEqual(calls[1].items, [{ skuCode: 'SKU-TEST', receivedQuantity: 3 }]) assert.equal(calls[0].trackingNo, 'WAYBILL-BATCH'); assert.equal(calls[1].trackingNo, 'WAYBILL-BATCH') assert.notEqual(calls[0].idempotencyKey, calls[1].idempotencyKey) assert.deepEqual(Array.from(page.result.labels, row => row.cartonMark), ['RP-1', 'RP-2']) }) test('failed multi-parcel batch resumes immutable requests without re-signing a successful parcel', async () => { const saved = new Map(), calls = [] let failSecond = true const confirm = async request => { calls.push(JSON.parse(JSON.stringify(request))) if (request.items[0].receivedQuantity === 2 && failSecond) throw new Error('response lost') return { unitType: 'PARCEL', labels: [{ cartonMark: `RP-${request.items[0].receivedQuantity}`, printableHtml: 'label' }], fullyMatched: false } } const page = setup(confirm, saved) page.unitType = 'PARCEL'; page.unitCode = 'WAYBILL-BATCH'; page.boxRows = [{ items: { 'SKU-TEST': 1 } }, { items: { 'SKU-TEST': 2 } }] await page.confirmReceipt() assert.equal(page.receiptBatch.entries[0].result.labels[0].cartonMark, 'RP-1') failSecond = false const restored = setup(confirm, saved) await restored.confirmReceipt() assert.equal(calls.length, 3) assert.equal(calls[1].idempotencyKey, calls[2].idempotencyKey) assert.deepEqual(calls[1], calls[2]) assert.equal(restored.result.labels.length, 2) }) test('partial receipt continues the same order with fresh pallet measurements', async () => { const page = setup(async () => ({})) page.finishReceipt([{ fullyMatched: false }]) assert.equal(page.result.continuationReturnNo, 'RT-TEST') let reopened page.openOrderValue = async returnNo => { reopened = returnNo; page.current = { returnNo } } await page.nextReceipt() assert.equal(reopened, 'RT-TEST') assert.equal(page.result, null) assert.equal(page.palletLength, '') assert.equal(page.palletWeight, '') }) test('PALLET response failure keeps the draft and same idempotency key for retry', async () => { const calls = [] const page = setup(async payload => { calls.push(JSON.parse(JSON.stringify(payload))); throw new Error('Response lost') }) await page.confirmReceipt() assert.equal(page.current.returnNo, 'RT-TEST') assert.equal(page.busy, false) assert.equal(page.error.message, 'Response lost') await page.confirmReceipt() assert.equal(calls.length, 2) assert.equal(calls[0].idempotencyKey, calls[1].idempotencyKey) }) test('continue signing returns to SKU scanning and accepts a fresh scan', () => { const page = setup(async () => ({})) page.finishReceipt([{ fullyMatched: false }]) page.lookupCode = 'PREVIOUS-SKU' page.selectedSku = 'PREVIOUS-SKU' page.palletCheck = { palletCode: 'PLT-TEST' } page.photoFileIds = ['previous-photo'] page.busy = true page.continueScanning() assert.ok(page.result) page.busy = false page.continueScanning() assert.equal(page.result, null) assert.equal(page.current, null) assert.equal(page.candidates, null) assert.equal(page.activeTarget, 'lookup') assert.equal(page.entryMode, 'SKU') assert.equal(page.lookupCode, '') assert.equal(page.selectedSku, '') assert.equal(page.palletCheck, null) assert.equal(page.palletLength, '') assert.equal(page.photoFileIds.length, 0) let scanned page.lookup = value => { scanned = value } page.handleScan('NEXT-SKU') assert.equal(scanned, 'NEXT-SKU') assert.equal(page.lookupCode, 'NEXT-SKU') })