import test from 'node:test' import assert from 'node:assert/strict' import { readFile } from 'node:fs/promises' const source = await readFile(new URL('../src/pages/relabel/relabel.vue', import.meta.url), 'utf8') const body = source.split('')[0].replace(/^\s*import .*$/gm, '').replace('export default', 'return') const component = new Function('PortalHeader', 'RelabelPalletWork', 'ScanTargetInput', 'ReturnRelabelPackWork', body)({}, {}, {}, {}) function context() { const value = { current: { reviewedAt: null, history: [], items: [{ itemId: '1', operationType: 'CARTON_AND_SKU', expectedPackages: 1, skippedPackages: 0, exceptionPackages: 0, skuProcessedPackages: 0, cartonProcessedPackages: 1, skuItems: [{ skuCode: 'OLD', newSkuCode: 'NEW', quantity: 3 }, { skuCode: 'OTHER', newSkuCode: 'NEW2', quantity: 2 }] }] }, taskTab: 'sku' } for (const name of ['skuDone', 'skuDetails', 'remaining']) value[name] = component.methods[name].bind(value) for (const name of ['visibleItems', 'pendingSkuRows']) Object.defineProperty(value, name, { get: component.computed[name].bind(value) }) return value } test('each persisted SKU hides independently; mixed carton progress is separate', () => { const value = context(); assert.equal(value.pendingSkuRows.length, 2) value.current.history.push({ action: 'SKU_SCAN', detail: JSON.stringify({ round: 'INITIAL', itemId: '1', skuIndex: 0 }) }) assert.equal(value.pendingSkuRows.length, 1); assert.equal(value.pendingSkuRows[0].sku.skuCode, 'OTHER') value.taskTab = 'carton'; assert.equal(value.visibleItems.length, 0) value.taskTab = 'sku'; value.current.reviewedAt = '2026-09-15T18:00:00'; assert.equal(value.pendingSkuRows.length, 2) value.current.items[0].skuProcessedPackages = 1; assert.equal(value.visibleItems.length, 0) }) test('normal SKU input is always visible in SKU tab and never requests the new label', () => { assert.match(source, /name="quickSku"/) assert.doesNotMatch(source, /placeholder="扫描或输入新 SKU 标签号"/) assert.match(source, /matches.length > 1/) assert.match(source, /scanRelabelSku/) }) test('return SKU follows ordinary single scan and requires explicit choice when the same SKU spans boxes', async () => { const calls = [] let value const subject = new Function('PortalHeader', 'RelabelPalletWork', 'ScanTargetInput', 'ReturnRelabelPackWork', 'scanRelabelSku', 'warehouseIdempotencyKey', 'releaseWarehouseKey', 'uni', body)( {}, {}, {}, {}, async (no, payload) => { calls.push(payload); return value.current }, () => ({ value: 'KEY', signature: 'SIG' }), () => {}, { showModal: options => options.complete() } ) value = context() Object.assign(value, { busy: false, quickSku: '', skuChoices: [], verifiedReturnCarton: '', returnCartonCode: '', async run(action, work) { await work() }, applyCurrent(task) { this.current = task }, setError(error) { throw error } }) for (const name of ['submitSku', 'commitSku']) value[name] = subject.methods[name].bind(value) value.current.relabelNo = 'RL'; value.current.version = 3 value.current.items = [{ itemId: '1', returnCartonId: 'R1', cartonMark: 'BOX-A', operationType: 'SKU_LABEL', expectedPackages: 1, relabelledPackages: 0, skippedPackages: 0, exceptionPackages: 0, skuItems: [{ skuCode: 'OLD', newSkuCode: 'NEW', quantity: 20 }] }] await value.submitSku('OLD') assert.deepEqual(calls, [{ itemId: '1', cartonMark: 'BOX-A', newSkuCode: 'NEW', quantity: 20, skuIndex: 0, oldSku: 'OLD', expectedVersion: 3, idempotencyKey: 'KEY' }]) calls.length = 0 value.current.items.push({ ...value.current.items[0], itemId: '2', returnCartonId: 'R2', cartonMark: 'BOX-B' }) await value.submitSku('OLD') assert.equal(calls.length, 0) assert.equal(value.skuChoices.length, 2) await value.commitSku(value.skuChoices[1]) assert.equal(calls.length, 1) assert.equal(calls[0].itemId, '2') assert.equal(calls[0].cartonMark, 'BOX-B') assert.doesNotMatch(source.split('