@@ -14,6 +14,7 @@ function context() {
] } }
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 . confirmBindingChoice = async ( ) => true
value . selectSource ( { positionId : '1' , palletId : '20' , palletCode : 'SOURCE' , movablePackages : 2 , cartonMarks : [ 'A' , 'B' , 'C' ] } )
return value
}
@@ -58,7 +59,7 @@ test('pallet comparison tolerates mixed API versions and canonical code formatti
test ( 'quantity disassembly has no extra carton scanner' , ( ) => {
assert . doesNotMatch ( source , /relabel-move-carton/ )
assert . match ( source , /actualSource:/ )
assert . match ( source , /仍归属 / )
assert . match ( source , /this\.message = `托盘 \$\{this\.target\.palletCode\} 已绑定` / )
} )
test ( 'source pallet list is concise and hides rows with no movable packages' , ( ) => {
@@ -70,7 +71,8 @@ test('source pallet list is concise and hides rows with no movable packages', ()
assert . deepEqual ( value . operableSourceRows . map ( row => row . palletCode ) , [ 'PALLET-1' ] )
assert . match ( source , />托盘</ )
assert . match ( source , />刷新</ )
assert . match ( source , /托盘号:\{\{ row\.palletCode \}\} · 入仓码: \{\{ row\.inbound Code \}\}/ )
assert . match ( source , /class="source-caption">托盘号<\/text><text class="source-code"> \{\{ row\.pallet Code \}\}/ )
assert . doesNotMatch ( template , /入仓码|row\.inboundCode/ )
assert . match ( source , /可拆\{\{ isReturnBulk \? '件数' : '箱数' \}\}: \{\{ row\.movablePackages \}\}/ )
assert . doesNotMatch ( template , /刷新来源托盘/ )
assert . doesNotMatch ( template , /按原入仓单拆托/ )
@@ -104,10 +106,55 @@ test('target confirmation submits binding directly, with no second submit button
value . bind = async ( ) => { binds ++ }
await value . confirmTargetAndBind ( )
assert . equal ( binds , 1 )
assert . match ( source , /@tap ="confirmTargetAndBind"/ )
assert . match ( source , /@submit ="confirmTargetAndBind"/ )
assert . doesNotMatch ( source , /@tap="bind"/ )
} )
test ( 'source scan asks before accepting a listed pallet and rejects unknown pallets' , async ( ) => {
const value = context ( )
value . sourceRows = [ { positionId : '1' , palletCode : 'SOURCE' , movablePackages : 2 } ]
value . sourceCode = 'SOURCE'
let prompts = 0
value . resolve = async ( ) => { value . source = { palletCode : 'SOURCE' } }
value . confirmBindingChoice = async ( ) => { prompts ++ ; return false }
await value . confirmSourceScan ( )
assert . equal ( value . source , null )
value . confirmBindingChoice = async ( ) => { prompts ++ ; return true }
await value . confirmSourceScan ( )
assert . equal ( value . source . palletCode , 'SOURCE' )
value . sourceCode = 'OTHER'
value . showBindingMessage = ( ) => { }
value . resolve = async ( ) => assert . fail ( 'unknown pallet must not resolve' )
await value . confirmSourceScan ( )
assert . equal ( value . source , null )
assert . equal ( prompts , 2 )
} )
test ( 'declining target confirmation does not move stock' , async ( ) => {
const value = context ( )
value . quantity = '1' ; value . source = { palletId : '20' , palletCode : 'SOURCE' } ; value . targetCode = 'TARGET'
value . resolve = async ( ) => { value . target = { palletId : '30' , palletCode : 'TARGET' } }
value . confirmBindingChoice = async ( ) => false
value . bind = async ( ) => assert . fail ( 'cancelled target must not bind' )
await value . confirmTargetAndBind ( )
assert . equal ( value . target , null )
} )
test ( 'simplified split automatically fills a batch and counts saved bindings without repeats' , async ( ) => {
const value = context ( )
value . task . items = [ 'A' , 'B' , 'C' ] . map ( cartonMark => ( { cartonMark , operationType : 'CARTON_LABEL' , expectedPackages : 1 , relabelledPackages : 1 , destinationFbaWarehouseCode : 'ONT8' } ) )
value . task . history = [ { action : 'PALLET_BIND' , detail : JSON . stringify ( { cartonMarks : [ 'A' ] , targetPallets : [ 'OLD-TARGET' ] } ) } ]
assert . equal ( value . requiredSplitPackages , 3 )
assert . equal ( value . splitPackages , 1 )
value . quantity = '1' ; value . marks = [ ] ; value . source = { palletId : '20' , palletCode : 'SOURCE' } ; value . targetCode = 'TARGET'
value . resolve = async ( ) => { value . target = { palletId : '30' , palletCode : 'TARGET' } }
value . bind = async ( ) => { assert . deepEqual ( value . marks , [ 'B' ] ) ; assert . equal ( value . readyToBind , true ) }
await value . confirmTargetAndBind ( )
assert . doesNotMatch ( template , /按箱数填入本批换标箱|选择本批新目的仓|本批确认|@tap="toggleMark/ )
value . task . history . push ( { action : 'REWORK_ARCHIVE' , detail : '{}' } )
assert . equal ( value . splitPackages , 0 )
} )
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 = ''