Files
pda-overseas-uniapp/tests/relabel-pallet-measurement.test.mjs
T
2026-10-16 11:43:15 +08:00

109 lines
6.6 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import test from 'node:test'
import assert from 'node:assert/strict'
import { readFile } from 'node:fs/promises'
import { createSSRApp } from 'vue'
import { renderToString } from 'vue/server-renderer'
const source = await readFile(new URL('../src/components/RelabelPalletWork.vue', import.meta.url), 'utf8')
const script = source.split('<script>')[1].split('</script>')[0].replace(/^import .*$/gm, '').replace('export default', 'return')
function setup() {
const calls = []
const component = new Function('ScanTargetInput', 'measureRelabelPallet', 'warehouseIdempotencyKey', 'releaseWarehouseKey', 'bindRelabelPallet', script)(
{}, async payload => { calls.push(payload); return [{ palletCode: payload.palletCode, volumeCbm: 0.25, grossWeightKg: payload.grossWeightKg }] },
() => ({ value: 'stable-key', signature: 'signature' }), () => {}, async payload => calls.push(payload))
const value = { ...component.data(), task: { relabelNo: 'RL-1' }, $emit() {} }
for (const [key, method] of Object.entries(component.methods)) value[key] = method.bind(value)
return { component, value, calls }
}
test('pallet measurement submits actual dimensions, weight and current stock version and refreshes results', async () => {
const { value, calls } = setup()
await value.saveMeasurement({ palletCode: 'NEW', stockVersion: 'position:version:count', lengthCm: '100', widthCm: '50', heightCm: '50', grossWeightKg: '40' })
assert.deepEqual(calls, [{ relabelNo: 'RL-1', palletCode: 'NEW', stockVersion: 'position:version:count', lengthCm: 100, widthCm: 50, heightCm: 50, grossWeightKg: 40, idempotencyKey: 'stable-key' }])
assert.equal(value.measurements[0].volumeCbm, 0.25)
assert.equal(value.busy, false)
await value.saveMeasurement({ palletCode: 'NEW', lengthCm: 0, widthCm: 50, heightCm: 50, grossWeightKg: 40 })
assert.equal(calls.length, 1)
assert.match(value.error, /有效/)
})
test('only whole physical pallet quantities offer original pallet reuse', () => {
const { component } = setup()
const canRetain = component.computed.canRetainOriginal
const ctx = { source: { totalPackages: 10 }, selectedSource: {}, plannedPackages: 10, isReturnBulk: false, unboundSourceMode: false }
assert.equal(canRetain.call(ctx), true)
ctx.plannedPackages = 4
assert.equal(canRetain.call(ctx), false)
ctx.plannedPackages = 10;ctx.isReturnBulk = true
assert.equal(canRetain.call(ctx), false)
})
async function renderMeasurements(measurements) {
const { component } = setup()
const template = source.slice(source.indexOf('<template>') + 10, source.indexOf('<script>')).trim().replace(/<\/template>$/, '')
return renderToString(createSSRApp({ ...component, template,
components: { ScanTargetInput: { template: '<view />' } },
props: undefined,
data() { return { ...component.data(), task: { relabelNo: 'RL-1', items: [], history: [] }, measurements } }
}))
}
test('unchanged source renders real grouped box specs and totals without zero pallet dimension inputs', async () => {
const html = await renderMeasurements([
{ palletCode: 'FIRST', packages: 2, inherited: true, lengthCm: null, widthCm: null, heightCm: null,
grossWeightKg: 5, volumeCbm: 0.3, sourceCartonSpecs: [{ lengthCm: 60, widthCm: 50, heightCm: 50, grossWeightKg: 2.5, cartons: 2 }] },
{ palletCode: 'SECOND', packages: 3, inherited: true, lengthCm: null, widthCm: null, heightCm: null,
grossWeightKg: 9.7, volumeCbm: 0.31, sourceCartonSpecs: [
{ lengthCm: 60, widthCm: 50, heightCm: 50, grossWeightKg: 2.5, cartons: 1 },
{ lengthCm: 50, widthCm: 40, heightCm: 40, grossWeightKg: 3.6, cartons: 2 }] }
])
assert.match(html, /60 × 50 × 50 cm · 2.5 kg\/箱 · 2 箱/)
assert.match(html, /50 × 40 × 40 cm · 3.6 kg\/箱 · 2 箱/)
assert.match(html, /来源汇总:0.31 m³ · 9.7 kg/)
assert.match(html, /未测整托长宽高/)
assert.equal((html.match(/class="measurement-inputs"/g) || []).length, 0)
assert.doesNotMatch(html, /确认本托实测/)
})
test('changed pallets and explicit packaging changes still render final pallet measurement inputs', async () => {
for (const pallet of [{ inherited: false }, { inherited: true, remeasuring: true }]) {
const html = await renderMeasurements([{ ...pallet, palletCode: 'P', packages: 1 }])
assert.match(html, /class="measurement-inputs"/)
assert.match(html, /确认本托实测/)
assert.match(html, /长 cm/)
}
})
test('box aggregated pallets render current totals and no manual pallet measurement even after moving', async () => {
const html = await renderMeasurements([{ palletCode: 'NEW', packages: 1, inherited: true, cartonAggregated: true,
grossWeightKg: 3.6, volumeCbm: 0.08, sourceCartonSpecs: [{lengthCm:50,widthCm:40,heightCm:40,grossWeightKg:3.6,cartons:1}] }])
assert.match(html, /移出扣减、移入增加/)
assert.match(html, /0.08 m³ · 3.6 kg/)
assert.doesNotMatch(html, /确认本托实测|重新测量|measurement-inputs/)
})
test('mixed box selection is required and submits exact measured source box with binding', async () => {
const { value, calls } = setup()
Object.assign(value, { readyToBind:true, requiresMeasuredBoxChoice:true, marks:['CUSTOMER'],
source:{palletCode:'OLD',palletVersion:1}, target:{palletCode:'NEW',palletVersion:1},
selectedSource:{positionId:'1',positionVersion:1},quantity:'1', loadSources:async()=>{}, showBindingMessage(){} })
await value.bind()
assert.equal(calls.length,0)
assert.match(value.error,/请选择/)
value.measuredSelections={CUSTOMER:'SMALL1'}
await value.bind()
assert.deepEqual(calls[0].measuredCartons,[{cartonMark:'CUSTOMER',sourceCartonMark:'SMALL1'}])
})
test('measured box picker excludes a box selected for another item', () => {
const { value } = setup()
Object.assign(value,{marks:['X','Y'],measuredSelections:{X:'A'},measuredBoxChoices:[
{cartonMark:'A',lengthCm:60,widthCm:50,heightCm:50,grossWeightKg:2.5},
{cartonMark:'B',lengthCm:50,widthCm:40,heightCm:40,grossWeightKg:3.6}]})
assert.deepEqual(value.measuredBoxOptions('Y').map(box=>box.cartonMark),['B'])
assert.equal(value.measuredBoxOptions('X').length,2)
})
test('entering split quantity prepares measured box choices before target binding', () => {
const { value } = setup()
Object.assign(value,{measuredBoxChoices:[{cartonMark:'A'}],eligibleItems:[{cartonMark:'X'}],
selectedSource:{movablePackages:1},measuredSelections:{OLD:'A'},fillBatch(){this.marks=['X']}})
value.prepareMeasuredBatch({detail:{value:'1'}})
assert.deepEqual(value.marks,['X'])
assert.deepEqual(value.measuredSelections,{})
value.prepareMeasuredBatch({detail:{value:'0'}})
assert.deepEqual(value.marks,[])
})