Files
baiyue-firstleg/scripts/admin-test-env-modules/looseboard-pool-preparation-contract.test.mjs
T

91 lines
5.5 KiB
JavaScript
Raw Normal View History

2026-10-22 14:37:59 +08:00
import test from 'node:test'
import assert from 'node:assert/strict'
import { prepareLooseboardPool } from './looseboard-pool-preparation.mjs'
// 模拟原车资源及容量版本;记录所有写入以验证不会创建主档或自动补发。
function fixture(fault = '', validPlan = false) {
const tripProof = { marker: 'fixture', preparation: 'VERIFIED', tripNo: 'TR-1', dispatchNo: 'DP-1', warehouseId: '42', vehicleId: '11', driverId: '12' }
const demand = { marker: 'fixture', finalStatus: 'PENDING_ACCEPTANCE' }
const trip = { ...tripProof, status: 'PLANNED', recordVersion: 1,
stops: [{ destinationKey: 'ORIGIN' }, { destinationKey: 'FBA:TEST' }] }
const plan = { planValid: validPlan, recordVersion: 1, manifestHash: 'a'.repeat(64), availableSegments: [{}],
cargo: [{ dispatchNo: 'DP-1', warehousePalletId: '71', palletNo: 'P-1', destinationKey: 'FBA:TEST' }] }
const offer = { offerNo: 'OF-1', tripNo: 'TR-1', status: 'DRAFT', recordVersion: 0, tripRecordVersion: 1 }
const calls = [], checkpoints = []; let creates = 0, publishes = 0, bindCalls = 0
const context = { marker: 'fixture', createdResources: { fleetTrips: [tripProof], phase4OverseasBusiness: { looseboard: demand } },
assert(_m, name, _r, passed) { assert.ok(passed, name) }, apiSuccess() {},
async checkpoint() { if (fault === 'disk') throw Error('disk'); checkpoints.push(structuredClone(tripProof.looseboardOffer)) },
async request(method, path, body) {
calls.push({ method, path, body })
let data
if (path.endsWith('/dispatches/DP-1')) data = { dispatchNo: 'DP-1', status: 'ACTIVE', stage: 'LOADING',
counts: { pickedPackageCount: fault === 'picked' ? 1 : 0, shippedPackageCount: 0 } }
else if (path.endsWith('/trips/TR-1')) data = { trip: { ...trip, driverId: fault === 'driver' ? '13' : '12' }, dispatches: [{ dispatchNo: 'DP-1' }] }
else if (path.endsWith('/capacity-plan')) {
if (method === 'POST') {
assert.equal(body.pallets[0].warehousePalletId, '71')
assert.equal(body.pallets[0].deliveryIndex, 1)
plan.planValid = true
}
data = structuredClone(plan)
if (fault === 'foreign cargo') data.cargo[0].dispatchNo = 'OTHER'
} else if (path.endsWith('/loading')) data = { confirmedLoad: fault === 'loaded' ? {} : null }
else if (path.endsWith('/capacity-offers') && method === 'POST') {
creates += 1
if (fault === 'network') return { http: 0 }
data = { offer: { ...offer }, replayed: creates > 1 }
if (fault === 'draft replay' && creates > 1) data.offer.offerNo = 'OF-2'
} else if (path.endsWith('/OF-1/publish')) {
publishes += 1
data = { offer: { ...offer, status: 'OPEN', capacityKnown: true, canCreateInquiry: true, canConfirm: true }, replayed: publishes > 1 }
if (fault === 'publish replay' && publishes > 1) data.offer.recordVersion = 9
} else throw Error(`Unexpected ${method} ${path}`)
return { http: 200, body: { code: '200', data: structuredClone(data) }, requestId: 'request', traceId: 'trace' }
} }
const bind = async (ctx, args) => {
bindCalls += 1
assert.equal(ctx, context); assert.equal(args.demand, demand); assert.equal(args.tripProof, tripProof)
assert.equal(args.offerNo, 'OF-1'); assert.equal(args.destinationKey, 'FBA:TEST')
assert.equal(tripProof.looseboardOffer.status, 'OPEN')
return { status: 'CONFIRMED_ORIGINAL_ORDER', tripNo: 'TR-1', offerNo: 'OF-1' }
}
return { context, args: { demand, tripProof, destinationKey: 'FBA:TEST', unitPrice: 25 }, bind, calls, checkpoints, counts: () => ({ creates, publishes, bindCalls }) }
}
for (const valid of [false, true]) test(`prepare owned pool and pass original demand to binding; existing plan=${valid}`, async () => {
const f = fixture('', valid)
await prepareLooseboardPool(f.context, f.args, f.bind)
assert.deepEqual(f.counts(), { creates: 2, publishes: 2, bindCalls: 1 })
assert.equal(f.calls.filter(c => c.method === 'POST' && c.path.endsWith('/capacity-plan')).length, valid ? 0 : 1)
assert.equal(f.args.tripProof.looseboardOffer.status, 'BOUND_ORIGINAL_DEMAND')
await assert.rejects(prepareLooseboardPool(f.context, f.args, f.bind))
assert.equal(f.calls.some(c => /\/vehicles|\/drivers|\/iam/.test(c.path)), false)
})
for (const encoded of ['0', '12', '', null, '01', '-1', '9007199254740992']) test(`pool source version uses bounded native Long encoding: ${String(encoded)}`, async () => {
const f = fixture('', true)
const request = f.context.request
f.context.request = async (method, path, body) => {
const response = await request(method, path, body)
if (path.endsWith('/capacity-plan')) response.body.data.recordVersion = encoded
return response
}
if (['0', '12'].includes(encoded)) await prepareLooseboardPool(f.context, f.args, f.bind)
else {
await assert.rejects(prepareLooseboardPool(f.context, f.args, f.bind), /容量依据/)
assert.equal(f.counts().creates, 0)
}
})
2026-10-22 14:37:59 +08:00
for (const fault of ['picked', 'driver', 'foreign cargo', 'loaded', 'network', 'draft replay', 'publish replay', 'disk']) {
test(`pool preparation fails closed on ${fault}`, async () => {
const f = fixture(fault)
await assert.rejects(prepareLooseboardPool(f.context, f.args, f.bind))
assert.equal(f.args.tripProof.looseboardOffer.status, 'FAILED')
assert.equal(f.counts().bindCalls, 0)
if (fault === 'network') assert.equal(f.counts().creates, 1)
if (fault === 'disk') assert.equal(f.calls.length, 0)
assert.equal(f.calls.some(c => /cancel|close|delete/.test(c.path)), false)
})
}