test(order): add isolated dependency failure and recovery verification
This commit is contained in:
@@ -2,7 +2,54 @@ import assert from 'node:assert/strict'
|
||||
import { readFileSync } from 'node:fs'
|
||||
import test from 'node:test'
|
||||
|
||||
import { fixtureInboundCode, orderPersistenceFacts, requestedOrderDestinationType, freezeOrderCommand, verifyPlatformDraftEdit, verifyPlatformSubmitCancel } from './orders.mjs'
|
||||
import { fixtureInboundCode, orderPersistenceFacts, requestedOrderDestinationType, freezeOrderCommand, verifyPlatformDraftEdit, verifyPlatformSubmitCancel,
|
||||
buildOrderDependencyFaultPlan, assertOrderDependencyFaultObservation } from './orders.mjs'
|
||||
|
||||
function dependencyFixture() {
|
||||
const detail = id => ({order:{id,orderNo:`FL${id}`,tenantId:'20',status:'DRAFT',version:4},
|
||||
cargoes:[{skuNo:'current'}],parties:[],internalNotes:[],statusHistory:[]})
|
||||
return {marker:'CURRENT-RUN',customerId:'20',registeredCustomerId:'20',merchant:detail('101'),platform:detail('102')}
|
||||
}
|
||||
function dependencyObservation(plan, fixture, dependency, role) {
|
||||
const phase=plan.phases.find(row=>row.dependency===dependency),command=plan.commands[role]
|
||||
const snapshot={detail:structuredClone(fixture[role]),task:null,inbounds:[],inboundPageComplete:true}
|
||||
return {request:{method:command.method,path:command.path,body:structuredClone(command.body),headers:{...command.headers,'X-Request-Id':`${dependency}-${role}`}},
|
||||
response:{http:200,body:{code:'S0503',message:phase.expectedMessages[0]}},before:snapshot,after:structuredClone(snapshot),
|
||||
proxyRecords:[{requestId:`${dependency}-${role}`,method:'GET',path:phase.targetPath,matched:true,responseStatus:503,forwarded:false,internalTokenPresent:true}]}
|
||||
}
|
||||
test('dependency plan binds two new-customer drafts and only named Order upstream properties; it performs no runtime actions',()=>{
|
||||
const fixture=dependencyFixture(),plan=buildOrderDependencyFaultPlan(fixture)
|
||||
assert.equal(plan.runtimeChangesExecuted,false)
|
||||
assert.deepEqual(plan.phases.map(row=>row.urlProperty),['baiyue.clients.iam.url','baiyue.clients.finance.url'])
|
||||
assert.equal(plan.commands.merchant.body.expectedVersion,4)
|
||||
fixture.merchant.order.version=9
|
||||
assert.equal(plan.commands.merchant.body.expectedVersion,4)
|
||||
assert.ok(Object.isFrozen(plan.commands.merchant.body))
|
||||
for(const change of [f=>f.customerId='0',f=>f.registeredCustomerId='21',f=>f.platform.order.id='101',f=>f.merchant.order.status='SUBMITTED',f=>delete f.merchant.cargoes]) {
|
||||
const value=dependencyFixture();change(value);assert.throws(()=>buildOrderDependencyFaultPlan(value))
|
||||
}
|
||||
})
|
||||
test('all four dependency-role observations require matching authenticated 503 injection and actual Order S0503 with zero drift',()=>{
|
||||
const fixture=dependencyFixture(),plan=buildOrderDependencyFaultPlan(fixture)
|
||||
for(const dependency of ['IAM','FINANCE'])for(const role of ['merchant','platform']) {
|
||||
const evidence=dependencyObservation(plan,fixture,dependency,role)
|
||||
assert.equal(assertOrderDependencyFaultObservation(plan,dependency,role,evidence).verified,true)
|
||||
const wrapped=structuredClone(evidence)
|
||||
wrapped.response.body.message=plan.phases.find(row=>row.dependency===dependency).expectedMessages[1]
|
||||
assert.equal(assertOrderDependencyFaultObservation(plan,dependency,role,wrapped).verified,true)
|
||||
for(const mutate of [
|
||||
value=>value.response.http=503,value=>value.response.body.code='A0403',value=>value.response.body.message='资格未审核',
|
||||
value=>value.request.body.expectedVersion=5,value=>value.request.headers['Idempotency-Key']='new-key',
|
||||
value=>value.proxyRecords=[],value=>value.proxyRecords[0].internalTokenPresent=false,value=>value.proxyRecords[0].forwarded=true,
|
||||
value=>value.proxyRecords[0].path+='/other',value=>value.proxyRecords[0].requestId='other-request',
|
||||
value=>value.proxyRecords.push({...value.proxyRecords[0],path:'/internal/iam/tenants/21/order-eligibility'}),
|
||||
value=>value.after.detail.order.version++,value=>value.after.detail.statusHistory.push({id:'unexpected'}),
|
||||
value=>value.after.task={orderId:plan.commands[role].orderId,tenantId:'20',id:'unexpected'},
|
||||
value=>value.after.inbounds.push({tenantId:'20',orderNo:plan.commands[role].orderNo,id:'unexpected'}),
|
||||
value=>value.after.inboundPageComplete=false,
|
||||
]) { const changed=structuredClone(evidence);mutate(changed);assert.throws(()=>assertOrderDependencyFaultObservation(plan,dependency,role,changed)) }
|
||||
}
|
||||
})
|
||||
|
||||
function platformLifecycleFixture(fault = '', faultAction = 'submit') {
|
||||
const drafts = new Map(), memo = new Map(), calls = []
|
||||
|
||||
Reference in New Issue
Block a user