130 lines
8.4 KiB
JavaScript
130 lines
8.4 KiB
JavaScript
import test from 'node:test'
|
|
import assert from 'node:assert/strict'
|
|
import { readFileSync } from 'node:fs'
|
|
import { runInNewContext } from 'node:vm'
|
|
const source = readFileSync(new URL('../src/pages/warehouse-transfer/warehouse-transfer.vue',import.meta.url),'utf8')
|
|
const script = source.match(/<script>([\s\S]*?)<\/script>/)[1].replace(/^import .+$/gm,'').replace('export default','page =')
|
|
function setup() {
|
|
const storage = new Map()
|
|
const scope = { CartonCountFields:{},PortalHeader:{},ScanTargetInput:{},session:{apiBase:'LOCAL',currentUser:{id:'OP',warehouseId:'WH'}},uni:{getStorageSync:key=>storage.get(key),setStorageSync:(key,value)=>storage.set(key,JSON.parse(JSON.stringify(value))),removeStorageSync:key=>storage.delete(key)} }
|
|
runInNewContext(script,scope)
|
|
const value = scope.page.data()
|
|
for(const [key,method] of Object.entries(scope.page.methods)) value[key]=method.bind(value)
|
|
for(const [key,get] of Object.entries(scope.page.computed)) Object.defineProperty(value,key,{get:()=>get.call(value)})
|
|
value.selected={transferNo:'WT1',packageCount:1,status:'WAIT_PDA_RECEIVING',items:[{id:'I1',skuCode:'A'}],cartons:[{cartonMark:'BOX1',transferItemId:'I1',status:'EXPECTED'}]}
|
|
value.pallets=[{key:'P1',draftId:'P1',palletNo:'PALLET1',generated:true,bound:false}];value.restoreCartons();Object.assign(value.cartonBoxes[0],{length:10,width:20,height:30,weight:2});value.cartonBoxes[0].items[0].quantity=4
|
|
return {scope,value,storage}
|
|
}
|
|
test('transfer counts require valid pieces and measurements and record variance reason',()=>{
|
|
const {value}=setup();assert.equal(value.cartonCountReady,true)
|
|
value.cartonBoxes[0].items[0].quantity=0;assert.equal(value.cartonCountReady,false)
|
|
value.cartonBoxes[0].items[0].quantity=1.5;assert.equal(value.cartonCountReady,false)
|
|
value.cartonBoxes[0].items[0].quantity=4;value.cartonBoxes[0].height=0;assert.equal(value.cartonCountReady,false)
|
|
value.cartonBoxes[0].height=30;value.addExtraCarton();Object.assign(value.cartonBoxes[1],{length:10,width:20,height:30,weight:2});value.cartonBoxes[1].items[0].quantity=5
|
|
assert.equal(value.cartonCountReady,false);value.countDiscrepancyReason='多一箱';assert.equal(value.cartonCountReady,true)
|
|
assert.equal(value.cartonQuantity,9);assert.equal(value.cartonVolume,'0.012000')
|
|
})
|
|
test('network retry preserves request key and changed content uses a new request',async()=>{
|
|
const {value,scope}=setup();const requests=[]
|
|
scope.countWarehouseTransferCartons=async(no,request)=>{requests.push(request);throw new Error('offline')}
|
|
await value.confirmCartons();await value.confirmCartons()
|
|
assert.equal(requests.length,2);assert.equal(requests[0].idempotencyKey,requests[1].idempotencyKey)
|
|
value.cartonBoxes[0].items[0].quantity=8;await value.confirmCartons();assert.notEqual(requests[1].idempotencyKey,requests[2].idempotencyKey)
|
|
assert.equal(value.countingCartons,false);assert.equal(value.error.message,'offline')
|
|
})
|
|
test('draft restores additional cartons and discrepancy reason and scanning rejects foreign box',()=>{
|
|
const {value}=setup();value.addExtraCarton();value.countDiscrepancyReason='超收';value.saveCartonDraft();value.restoreCartons()
|
|
assert.equal(value.cartonBoxes.length,2);assert.equal(value.countDiscrepancyReason,'超收')
|
|
value.locateCarton('FOREIGN');assert.match(value.error.message,/不属于/)
|
|
value.locateCarton('BOX1');assert.equal(value.selectedCartonMark,'BOX1');assert.equal(value.cartonScrollTarget,'transfer-box-0')
|
|
value.selected={...value.selected,transferNo:'WT2'};value.restoreCartons();assert.equal(value.cartonBoxes.length,1)
|
|
})
|
|
test('received count gates pallet completion and saving cannot switch active order',()=>{
|
|
const {value}=setup();assert.match(value.validationMessage,/先完成全部箱子/)
|
|
value.selected.cartons[0].countedAt='2026-10-15';value.cartonBoxes[0].transferPalletId='FOREIGN';assert.match(value.validationMessage,/已清点实收箱数/)
|
|
value.countingCartons=true;value.backToCandidates();assert.equal(value.selected.transferNo,'WT1')
|
|
})
|
|
|
|
test('batch applies only selected received boxes of one SKU and preserves independent drafts',()=>{
|
|
const {value}=setup()
|
|
value.addExtraCarton();value.addExtraCarton();value.addExtraCarton()
|
|
value.cartonBoxes[2].items[0].skuCode='B'
|
|
value.cartonBoxes[3].received=false
|
|
value.selectBatchCartons(true)
|
|
assert.equal(value.batchTargetBoxes.length,2)
|
|
value.toggleBatchCarton(0)
|
|
Object.assign(value.batchBox,{length:32,width:24,height:18,weight:3.2})
|
|
value.batchBox.items[0].quantity=6
|
|
assert.equal(value.batchTotalQuantity,6)
|
|
value.applyBatchCartons()
|
|
assert.equal(value.cartonBoxes[0].items[0].quantity,4)
|
|
assert.equal(value.cartonBoxes[1].items[0].quantity,6)
|
|
assert.equal(value.cartonBoxes[2].items[0].quantity,'')
|
|
assert.equal(value.cartonBoxes[3].items[0].quantity,'')
|
|
value.batchBox.items[0].quantity=8
|
|
assert.equal(value.cartonBoxes[1].items[0].quantity,6)
|
|
value.restoreCartons()
|
|
assert.equal(value.cartonBoxes[1].items[0].quantity,6)
|
|
assert.equal(value.batchTargetBoxes.length,0)
|
|
value.changeBatchSku(1)
|
|
assert.equal(value.batchSku,'B')
|
|
assert.equal(value.batchBox.items[0].quantity,'')
|
|
})
|
|
|
|
test('batch guards invalid quantities, busy state, submitted facts and stale mixed SKU selections',()=>{
|
|
const {value}=setup();value.selectBatchCartons(true)
|
|
Object.assign(value.batchBox,{length:32,width:24,height:18,weight:3.2})
|
|
for(const quantity of [0,1.5,2147483648]){
|
|
value.batchBox.items[0].quantity=quantity;value.applyBatchCartons()
|
|
assert.equal(value.cartonBoxes[0].items[0].quantity,4)
|
|
}
|
|
value.batchBox.items[0].quantity=6;value.countingCartons=true;value.applyBatchCartons()
|
|
assert.equal(value.cartonBoxes[0].items[0].quantity,4)
|
|
value.countingCartons=false;value.cartonBoxes[0].items[0].skuCode='B'
|
|
assert.equal(value.batchTargetBoxes.length,0);value.applyBatchCartons()
|
|
assert.equal(value.cartonBoxes[0].items[0].quantity,4)
|
|
value.cartonBoxes[0].items[0].skuCode='A';value.selected.cartons[0].countedAt='now';value.applyBatchCartons()
|
|
assert.equal(value.cartonBoxes[0].items[0].quantity,4)
|
|
})
|
|
|
|
test('copy uses preceding received same SKU without sharing quantity objects or changing box identity',()=>{
|
|
const {value}=setup();value.addExtraCarton();value.addExtraCarton()
|
|
value.cartonBoxes[1].items[0].skuCode='B'
|
|
value.copyPreviousCarton(1);assert.equal(value.cartonBoxes[1].items[0].quantity,'')
|
|
const identity=value.cartonBoxes[2].localKey
|
|
value.copyPreviousCarton(2)
|
|
assert.equal(value.cartonBoxes[2].length,10)
|
|
assert.equal(value.cartonBoxes[2].items[0].quantity,4)
|
|
assert.equal(value.cartonBoxes[2].localKey,identity)
|
|
value.cartonBoxes[2].items[0].quantity=9
|
|
assert.equal(value.cartonBoxes[0].items[0].quantity,4)
|
|
value.cartonBoxes[0].received=false;assert.equal(value.previousMatchingCarton(2),undefined)
|
|
})
|
|
|
|
|
|
test('pallet totals follow actual box assignments and exclude missing boxes',()=>{
|
|
const {value}=setup();value.pallets.push({key:'P2',draftId:'P2',palletNo:'PALLET2',generated:true})
|
|
value.addExtraCarton();Object.assign(value.cartonBoxes[1],{length:40,width:20,height:10,weight:3,transferPalletId:'P2'});value.cartonBoxes[1].items[0].quantity=6
|
|
assert.equal(value.palletSummary(value.pallets[0]).cartonCount,1)
|
|
assert.equal(value.palletSummary(value.pallets[1]).volume,0.008)
|
|
assert.equal(value.totalWeight,'5.00')
|
|
value.assignCartonPallet(value.cartonBoxes[1],0)
|
|
assert.equal(value.palletSummary(value.pallets[0]).cartonCount,2)
|
|
assert.equal(value.palletSummary(value.pallets[1]).cartonCount,0)
|
|
value.cartonBoxes[1].received=false
|
|
assert.equal(value.totalWeight,'2.00')
|
|
value.cartonBoxes[0].transferPalletId='FOREIGN';assert.equal(value.cartonCountReady,false)
|
|
})
|
|
|
|
test('pallet number can be created before measurements and new boxes receive that identity',async()=>{
|
|
const {value,scope}=setup();const requests=[]
|
|
value.pallets=[{key:'NEW',generated:false,busy:false}];value.cartonBoxes[0].transferPalletId=''
|
|
const pallet={id:'CREATED',sequenceNo:1,status:'GENERATED',palletNo:'NEWPALLET'}
|
|
scope.saveWarehouseTransferPalletDraft=async(no,request)=>{requests.push(request);return {pallets:[{...pallet,status:'DRAFT'}]}}
|
|
scope.generateWarehouseTransferPallet=async()=>({pallets:[pallet]})
|
|
await value.generatePallet(value.pallets[0])
|
|
assert.equal(requests.length,1);assert.equal('lengthCm' in requests[0],false);assert.equal('grossWeightKg' in requests[0],false)
|
|
assert.equal(value.cartonBoxes[0].transferPalletId,'CREATED')
|
|
assert.equal(value.pallets[0].palletNo,'NEWPALLET')
|
|
})
|