2026-09-20 20:40:21 +08:00
import test from 'node:test'
import assert from 'node:assert/strict'
2026-10-23 05:36:21 +08:00
import { replayCompletedCommand , completedPlanAssignmentProbe } from './phase3-loading-finalize.mjs'
2026-09-20 20:40:21 +08:00
test ( 'completed-command replay retries one connection failure and keeps its diagnostic' , async () => {
const failure = { http : 0 , raw : 'fetch failed' }
const success = { http : 200 , body : { code : '200' } }
const responses = [ failure , success ]
const diagnostics = []
let calls = 0
assert . equal ( await replayCompletedCommand ( async () => { calls ++ ; return responses . shift () }, r => diagnostics . push ( r )), success )
assert . equal ( calls , 2 )
assert . deepEqual ( diagnostics , [ failure ])
})
test ( 'business failures are never retried; a second connection failure remains failure' , async () => {
for ( const response of [{ http : 200 , body : { code : 'A0409' } }, { http : 503 }, { http : 0 }]) {
let calls = 0
const result = await replayCompletedCommand ( async () => { calls ++ ; return response }, () => {})
assert . equal ( result , response )
assert . equal ( calls , response . http === 0 ? 2 : 1 )
}
})
2026-10-23 05:36:21 +08:00
function assignmentFixture ( change = false ) {
const baseline = { status : 'COMPLETED' , version : 7 , items : [{ id : '11' , packageCount : 2 }] }
const reads = [], writes = []
const context = { marker : 'batch' , createdResources : {}, async request ( method , path ) {
reads . push ({ method , path }); return { http : 200 , body : { code : '200' , data : change ? { ... baseline , version : 8 } : structuredClone ( baseline ) } }
} }
const input = { planPath : '/plans/1' , baseline ,
body : { inboundId : '10' , inboundDetailId : '11' , packageCount : 1 , expectedVersion : 7 , operationId : 'batch-negative' } }
const send = async ( _context , method , path , body ) => {
writes . push ({ method , path , body : structuredClone ( body ) })
return writes . length === 1 ? { http : 0 , raw : 'fetch failed' , transportError : { code : 'ECONNRESET' } }
: { http : 200 , body : { code : 'A0409' } }
}
return { baseline , context , input , reads , writes , send }
}
test ( 'completed plan rejection probe checks unchanged authoritative state before exact original replay and retains first transport evidence' , async () => {
const f = assignmentFixture ()
const result = await completedPlanAssignmentProbe ( f . context , f . input , f . send )
assert . equal ( result . body . code , 'A0409' ); assert . equal ( f . writes . length , 2 )
assert . deepEqual ( f . writes [ 0 ], f . writes [ 1 ]); assert . equal ( f . reads . length , 2 )
const proof = f . context . createdResources . completedPlanAssignmentProbes [ 0 ]
assert . equal ( proof . attempts [ 0 ]. transportError . code , 'ECONNRESET' )
assert . equal ( proof . status , 'VERIFIED_REJECTION_AFTER_TRANSPORT_RECOVERY' )
})
test ( 'changed completed plan after lost response stops without any second write' , async () => {
const f = assignmentFixture ( true )
await assert . rejects ( completedPlanAssignmentProbe ( f . context , f . input , f . send ), /禁止重放/ )
assert . equal ( f . writes . length , 1 )
assert . equal ( f . context . createdResources . completedPlanAssignmentProbes [ 0 ]. status , 'UNKNOWN_RESULT_STATE_CHANGED' )
})
test ( 'completed plan rejection recovery never retries business rejection, server error or permits an ordinary active plan' , async () => {
for ( const response of [{ http : 200 , body : { code : 'A0409' } }, { http : 503 }, { http : 0 }]) {
const f = assignmentFixture (); let count = 0
await completedPlanAssignmentProbe ( f . context , f . input , async () => { count ++ ; return response })
assert . equal ( count , response . http === 0 ? 2 : 1 )
}
const f = assignmentFixture (); f . input . baseline . status = 'ACTIVE'
await assert . rejects ( completedPlanAssignmentProbe ( f . context , f . input , f . send ), /不可变命令/ )
assert . equal ( f . writes . length , 0 )
})