Files
pda-overseas-uniapp/tests/relabel-pallet-work.test.mjs
T
2026-09-17 13:36:08 +08:00

94 lines
5.1 KiB
JavaScript

import test from 'node:test'
import assert from 'node:assert/strict'
import { readFile } from 'node:fs/promises'
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')
const component = new Function('ScanTargetInput', script)({})
function context() {
const value = { ...component.data(), $emit() {}, task: { items: [
{ cartonMark: 'A', relabelledPackages: 1, destinationFbaWarehouseCode: 'ONT8' },
{ cartonMark: 'B', relabelledPackages: 1, destinationFbaWarehouseCode: 'JFK8' },
{ cartonMark: 'C', relabelledPackages: 0, destinationFbaWarehouseCode: 'ONT8' },
{ cartonMark: 'OTHER', relabelledPackages: 1, destinationFbaWarehouseCode: 'ONT8' }
] } }
for (const [key, method] of Object.entries(component.methods)) value[key] = method.bind(value)
for (const [key, method] of Object.entries(component.computed)) Object.defineProperty(value, key, { get: method.bind(value) })
value.selectSource({ positionId: '1', palletCode: 'SOURCE', movablePackages: 2, cartonMarks: ['A', 'B', 'C'] })
return value
}
test('quantity batch only includes completed boxes from same inbound and destination', () => {
const value = context()
value.quantity = '1'; value.fillBatch(); assert.deepEqual(value.marks, ['A'])
value.quantity = '2'; value.fillBatch(); assert.match(value.error, /不超过/)
value.quantity = '1.5'; value.fillBatch(); assert.match(value.error, /正整数/)
value.selectedDestination = 'JFK8'; value.quantity = '1'; value.fillBatch(); assert.deepEqual(value.marks, ['B'])
})
test('submission requires exact count and scanned distinct source and target pallets', () => {
const value = context(); value.quantity = '1'; value.fillBatch()
value.source = { palletCode: 'SOURCE' }; value.sourceCode = 'source'
value.target = { palletCode: 'TARGET' }; value.targetCode = 'TARGET'
assert.equal(value.readyToBind, true)
value.toggleMark('A'); assert.equal(value.readyToBind, false)
value.toggleMark('A'); value.sourceCode = 'OTHER'; assert.equal(value.readyToBind, false)
value.sourceCode = 'SOURCE'; value.target = { palletCode: 'SOURCE' }; value.targetCode = 'SOURCE'
assert.equal(value.readyToBind, false)
})
test('quantity disassembly has no extra carton scanner', () => {
assert.doesNotMatch(source, /relabel-move-carton/)
assert.match(source, /actualSource:/)
assert.match(source, /仍归属/)
})
test('latest current-round binding is used for rebind source', () => {
const value = context()
value.task.history = ['OLD', 'NEW'].map(pallet => ({ action: 'PALLET_BIND', detail: JSON.stringify({ round: 'INITIAL', cartonMarks: ['A'], targetPallets: [pallet] }) }))
assert.deepEqual(value.currentBindings, [{ mark: 'A', pallet: 'NEW' }])
value.task.reviewedAt = 'NEW-ROUND'
assert.deepEqual(value.currentBindings, [{ mark: 'A', pallet: 'NEW' }])
value.task.history.push({ action: 'REWORK_ARCHIVE', detail: '{}' })
assert.deepEqual(value.currentBindings, [])
})
test('rescan same bound pallet does not call stock movement', async () => {
const value = context(); value.rebindSelection = { mark: 'A', pallet: 'TARGET' }; value.targetCode = 'target'
let message = ''
value.showBindingMessage = (title, content) => { message = content }
value.run = async () => assert.fail('same pallet must not move stock')
await value.submitRebind()
assert.match(message, /不会重复扣库存/)
})
test('target confirmation submits binding directly, with no second submit button', async () => {
const value = context(); value.quantity = '1'; value.fillBatch()
value.source = { palletCode: 'SOURCE' }; value.sourceCode = 'SOURCE'; value.targetCode = 'TARGET'
let binds = 0
value.resolve = async kind => { assert.equal(kind, 'target'); value.target = { palletCode: 'TARGET' } }
value.bind = async () => { binds++ }
await value.confirmTargetAndBind()
assert.equal(binds, 1)
assert.match(source, /@tap="confirmTargetAndBind"/)
assert.doesNotMatch(source, /@tap="bind"/)
})
test('missing source scan shows modal and never submits a binding', async () => {
const value = context(); value.quantity = '1'; value.fillBatch(); value.targetCode = 'TARGET'
let message = ''
value.showBindingMessage = (title, content) => { message = content }
value.bind = async () => assert.fail('must not bind without source confirmation')
value.resolve = async () => assert.fail('must validate source first')
await value.confirmTargetAndBind()
assert.match(message, /扫描并确认实际来源托盘/)
})
test('target lookup failure cannot submit binding or report success', async () => {
const value = context(); value.quantity = '1'; value.fillBatch()
value.source = { palletCode: 'SOURCE' }; value.sourceCode = 'SOURCE'; value.targetCode = 'TARGET'
value.resolve = async () => { value.error = '目标托盘不可用' }
let title = ''
value.showBindingMessage = heading => { title = heading }
value.bind = async () => assert.fail('must not bind after lookup failure')
await value.confirmTargetAndBind()
assert.equal(title, '绑定失败')
})