Files
baiyue-firstleg/scripts/fleet-test-env-acceptance.test.mjs
T

185 lines
13 KiB
JavaScript

import test from 'node:test'
import assert from 'node:assert/strict'
import { mkdtempSync, mkdirSync, readFileSync, existsSync, rmSync } from 'node:fs'
import { tmpdir } from 'node:os'
import { join, dirname, resolve } from 'node:path'
import { parseFleetArguments, fleetExecutionPlan, runFleetAcceptance, reviewedFullCheckpoint, verifyFleetTerminalState } from './fleet-test-env-acceptance.mjs'
test('fleet entry defaults to a no-side-effect plan and requires explicit TEST and unique run ID', () => {
const p = parseFleetArguments([])
assert.equal(p.execute, false); assert.equal(fleetExecutionPlan(p).execution, 'PLAN')
for (const args of [['--execute'], ['--execute', '--run-id', 'new'], ['--execute', '--environment', 'prod', '--run-id', 'new'],
['--execute', '--environment', 'TEST', '--run-id', '../old'], ['--plan', '--execute'], ['--force'], ['--run-id', 'a', '--run-id', 'b']]) {
assert.throws(() => parseFleetArguments(args))
}
assert.equal(parseFleetArguments(['--execute', '--environment', 'TEST', '--run-id', 'new']).execute, true)
})
async function executeFixture(failProducer = false) {
const temporary = mkdtempSync(join(tmpdir(), 'fleet-entry-contract-'))
const root = join(temporary, 'chongchong-global', 'baiyue-firstleg'); mkdirSync(root, { recursive: true })
const calls = [], secrets = 'never-print-this-secret'
const env = { CHONGCHONG_ENV: 'test', CHONGCHONG_ADMIN_API_BASE_URL: 'https://test.invalid', CHONGCHONG_ADMIN_USERNAME: 'fixture-admin',
CHONGCHONG_ADMIN_PASSWORD: secrets, ADMIN_PDA_USERNAME: 'fixture-pda', ADMIN_PDA_PASSWORD: secrets }
const config = parseFleetArguments(['--execute', '--environment', 'TEST', '--run-id', 'fixture'])
const createContext = options => ({ options, context: {}, createdResources: {}, steps: [], modules: [], coverageGaps: [], token: secrets,
async executeModule(name, handler) {
try { await handler(); this.modules.push({ name, success: true }) }
catch { this.modules.push({ name, success: false }); this.steps.push({ name: 'producer failed', passed: false }) }
},
async run() {
await this.executeModule('producer', async () => { calls.push('producer'); if (failProducer) throw Error('fixture failure') })
await this.executeModule('phase4-overseas-dispatch', async () => { calls.push('dispatch'); this.createdResources.current = { accessToken: secrets } })
return { success: true, steps: this.steps, modules: this.modules, createdResources: this.createdResources, summary: { failed: 0 } }
},
})
try {
const options = { root, env, createContext, readers: { async preflight() { calls.push('preflight') }, async readReceiving() { throw Error('not used') } },
scenario: async context => { calls.push('fleet'); context.createdResources.fleetAcceptance = { status: 'HTTP_CHAIN_VERIFIED_WITH_ACK_GAP' } } }
const result = await runFleetAcceptance(config, options)
const report = JSON.parse(readFileSync(result.report, 'utf8'))
assert.ok(!readFileSync(result.report, 'utf8').includes(secrets))
assert.equal(existsSync(join(root, 'reports/.fleet-acceptance.lock')), false)
const oldReport = readFileSync(result.report, 'utf8')
const repeated = await runFleetAcceptance(config, options)
assert.equal(repeated.success, false)
assert.equal(readFileSync(result.report, 'utf8'), oldReport, 'existing run is never overwritten or resumed')
return { result, report, calls }
} finally {
assert.equal(dirname(resolve(temporary)), resolve(tmpdir()))
assert.ok(resolve(temporary).startsWith(join(resolve(tmpdir()), 'fleet-entry-contract-')))
rmSync(temporary, { recursive: true, force: true })
}
}
test('fresh entry runs dedicated fleet scenario after prerequisites without altering the default F40 chain', async () => {
const { result, report, calls } = await executeFixture()
assert.equal(result.success, true)
assert.deepEqual(calls, ['preflight', 'producer', 'dispatch', 'fleet'])
assert.equal(report.fleetGoalComplete, false)
assert.equal(report.createdResources.current.accessToken, '[REDACTED]')
})
test('failed prerequisite stops before further fixture creation and retains the failed report', async () => {
const { result, report, calls } = await executeFixture(true)
assert.equal(result.success, false)
assert.deepEqual(calls, ['preflight', 'producer'])
assert.equal(report.fatal, 'Producer stopped: producer')
})
test('environment mismatch rejects before invoking any readers or contexts', async () => {
let touched = false
await assert.rejects(() => runFleetAcceptance({ execute: true, environment: 'TEST', runId: 'new' }, {
env: { CHONGCHONG_ENV: 'production' }, readers: { preflight() { touched = true } },
}), /TEST/)
assert.equal(touched, false)
})
test('reviewed resume requires explicit paired checkpoint options', () => {
assert.throws(() => parseFleetArguments(['--resume-report', 'reports/old/report.json']))
assert.throws(() => parseFleetArguments(['--resume-report', 'reports/old/report.json', '--resume-stage', 'PICK_EACH_DISPATCH']))
const c = parseFleetArguments(['--execute', '--environment', 'TEST', '--run-id', 'reviewed', '--resume-report', 'reports/old/report.json', '--resume-stage', 'FULL_COVERAGE'])
assert.equal(c.resumeStage, 'FULL_COVERAGE')
})
test('checkpoint guard forbids repeating commands whose write outcome may be unknown', () => {
const report = { success: false, createdResources: {
fleetAcceptance: { marker: 'M', stage: 'FULL_COVERAGE', status: 'CHECKING', tripNo: 'T', originalDispatch: { dispatchNo: 'D' } },
fleetTrips: [{ tripNo: 'T', dispatchNo: 'D' }],
fleetFeeCoverageCases: [{ mode: 'FULL', marker: 'M', dispatchNo: 'D', proof: { status: 'CHECKING', requests: [{ method: 'GET' }] } }],
} }
assert.equal(reviewedFullCheckpoint(report).marker, 'M')
const mutated = structuredClone(report)
mutated.createdResources.fleetFeeCoverageCases[0].proof.requests.push({ method: 'POST' })
assert.throws(() => reviewedFullCheckpoint(mutated), /unknown outcomes/)
mutated.createdResources.fleetFeeCoverageCases[0].proof.requests.pop()
mutated.createdResources.fleetFeeCoverageCases[0].proof.outboundNo = 'OUT-1'
assert.throws(() => reviewedFullCheckpoint(mutated), /unknown outcomes/)
assert.throws(() => reviewedFullCheckpoint(mutated, 'FULL_COVERAGE_PERSISTED'), /exact successful command/)
Object.assign(mutated.createdResources.fleetFeeCoverageCases[0].proof, { deliveryNos: ['DEL-1'], confirmationRequest: { idempotencyKey: 'original-key' } })
mutated.createdResources.fleetFeeCoverageCases[0].proof.requests.push({ label: '正式保存本次原费用服务覆盖并转派送', method: 'POST', http: 200, code: '200' })
assert.equal(reviewedFullCheckpoint(mutated, 'FULL_COVERAGE_PERSISTED').persisted, true)
})
test('receipt-ready reconciliation cannot repeat a receipt that has already started', () => {
const report = { success: false, steps: [{ name: '创建海外PDA仓库操作员71', code: 'A0409', message: '手机号已存在' }], createdResources: {
fleetAcceptance: { marker: 'M', stage: 'RESERVATIONS', status: 'CHECKING', tripNo: 'T' },
fleetTrips: [{ tripNo: 'T', dispatchNo: 'D2', reservation: { status: 'VERIFIED' } }],
fleetFeeCoverageCases: [{ mode: 'FULL', proof: { status: 'VERIFIED' } }, { mode: 'PARTIAL', dispatchNo: 'D2', proof: { status: 'VERIFIED' } }],
} }
assert.equal(reviewedFullCheckpoint(report, 'EXTERNAL_RECEIPT_READY').receiptReady, true)
report.createdResources.fleetTrips[0].externalReceipt = { status: 'CHECKING' }
assert.throws(() => reviewedFullCheckpoint(report, 'EXTERNAL_RECEIPT_READY'), /no receipt writes/)
})
test('palletized checkpoint requires a saved successful command, owned operator, and no later confirmation', () => {
const report = { success: false, createdResources: {
fleetAcceptance: { marker: 'M', stage: 'EXTERNAL_RECEIPT', status: 'CHECKING', tripNo: 'T', picker: { membershipId: '71' }, pickerMarker: 'M-PDA' },
fleetTrips: [{ tripNo: 'T', dispatchNo: 'D2', reservation: { status: 'VERIFIED' }, externalReceipt: { status: 'CHECKING',
warehousePalletId: 'P1', palletizeRequest: { idempotencyKey: 'original' }, requests: [
{ label: 'PDA正式完成外接收货及库存入账', method: 'POST', http: 200, code: '200' },
] } }],
fleetFeeCoverageCases: [{ mode: 'FULL', proof: { status: 'VERIFIED' } }, { mode: 'PARTIAL', dispatchNo: 'D2', proof: { status: 'VERIFIED' } }],
} }
assert.equal(reviewedFullCheckpoint(report, 'EXTERNAL_PALLETIZED').palletized, true)
assert.throws(() => reviewedFullCheckpoint(report, 'EXTERNAL_RECEIPT_CONFIRMED'), /exact successful PDA command/)
const confirmed = structuredClone(report)
confirmed.createdResources.fleetTrips[0].externalReceipt.receiptRequest = { idempotencyKey: 'confirm-original' }
assert.throws(() => reviewedFullCheckpoint(confirmed, 'EXTERNAL_RECEIPT_CONFIRMED'), /exact successful PDA command/)
confirmed.createdResources.fleetTrips[0].externalReceipt.requests.push({ label: '运营按实际1托位和新单价30确认实收', method: 'POST', http: 200, code: '200' })
assert.equal(reviewedFullCheckpoint(confirmed, 'EXTERNAL_RECEIPT_CONFIRMED').receiptConfirmed, true)
assert.throws(() => reviewedFullCheckpoint(confirmed, 'EXTERNAL_PALLETIZED'), /exact successful PDA command/)
for (const mutate of [
r => { r.fleetTrips[0].externalReceipt.requests[0].code = 'A0409' },
r => { delete r.fleetTrips[0].externalReceipt.palletizeRequest.idempotencyKey },
r => { delete r.fleetAcceptance.picker },
r => { r.fleetTrips[0].externalReceipt.receiptRequest = { idempotencyKey: 'later' } },
r => { r.fleetTrips[0].externalDispatch = { status: 'CHECKING' } },
]) {
const invalid = structuredClone(report); mutate(invalid.createdResources)
assert.throws(() => reviewedFullCheckpoint(invalid, 'EXTERNAL_PALLETIZED'), /exact successful PDA command/)
}
})
function terminalFixture(fault = '') {
const finalTrip = { status: 'COMPLETED', completedAt: '2026-10-02T22:01:00Z', recordVersion: '30', vehicleRelease: { endLocation: 'ONT8' }, driverRelease: { endLocation: 'ONT8' } }
const closure = { status: 'CARGO_COMPLETED_AND_RESOURCES_RELEASED', finalTrip, probes: [{ tripNo: 'PROBE' }] }
const trip = { tripNo: 'T', closure, externalReceipt: { status: 'VERIFIED' }, reassignment: { status: 'VERIFIED' }, externalDispatch: { status: 'VERIFIED', dispatchNo: 'EXT', deliveryNo: 'DEL-EXT' } }
const proof = { marker: 'M', tripNo: 'T', customerId: '92', stage: 'RECEIPTS_AND_RESOURCE_RELEASE', closure,
receipts: ['DEL-OWN', 'DEL-EXT'].map(deliveryNo => ({ deliveryNo, signedAt: '2026-10-02T22:00:00' })),
departure: { shippedPackages: 6 }, finance: { status: 'CONSUMER_PERSISTED', source: { sourceFeeId: 'F1', sourceVersion: 1 } } }
const resources = { fleetAcceptance: proof, fleetTrips: [trip], fleetFeeCoverageCases: [{ mode: 'PARTIAL', dispatchNo: 'OWN', proof: { deliveryNos: ['DEL-OWN'] } }] }
const calls = []
const context = { createdResources: resources, assert() {}, async request(method, path) {
calls.push({ method, path }); assert.equal(method, 'GET')
let data
if (path.endsWith('/trips/T')) data = { trip: finalTrip, dispatches: ['OWN', 'EXT'].map(dispatchNo => ({ dispatchNo })) }
else if (path.endsWith('/trips/PROBE')) data = { trip: { status: 'CANCELLED' } }
else if (path.includes('/dispatches/')) { const number = path.split('/').at(-1), count = number === 'OWN' ? 5 : 1
data = { dispatchNo: number, status: 'DEPARTED', packageCount: count, pickedPackageCount: count, shippedPackageCount: fault === 'quantity' ? 0 : count } }
else if (path.includes('/delivery-orders/')) data = { order: { deliveryNo: path.split('/').at(-1).split('?')[0], status: fault === 'unsigned' ? 'WAIT_DELIVERY' : 'DELIVERED', signedAt: '2026-10-02T22:00:00' } }
else if (path.includes('/fee-pool?')) data = [{ customerId: '92', sourceId: 'F1', sourceVersion: fault === 'wrong-fee-version' ? 2 : 1, amount: 30, currency: 'CNY', sourceType: 'OVERSEAS_DELIVERY_FEE' }]
else throw Error('unexpected path')
return { http: 200, body: { code: '200', data: structuredClone(data) }, requestId: 'r', traceId: 't' }
} }
return { context, calls, report: { success: false, createdResources: resources, steps: [{ name: '本次车次货物结案及车辆司机释放完成', passed: false }] } }
}
test('terminal reconciliation reads actual completion, every dispatch/delivery and exact fee without replaying writes', async () => {
const f = terminalFixture()
assert.equal(reviewedFullCheckpoint(f.report, 'TERMINAL_READONLY').terminal, true)
const result = await verifyFleetTerminalState(f.context)
assert.equal(result.terminalReadback.status, 'VERIFIED')
assert.equal(f.calls.length, 7)
assert.ok(f.calls.every(row => row.method === 'GET'))
const invalid = terminalFixture().report
invalid.steps.push({ name: '真实业务失败', passed: false })
assert.throws(() => reviewedFullCheckpoint(invalid, 'TERMINAL_READONLY'), /known aggregate assertion/)
})
for (const fault of ['quantity', 'unsigned', 'wrong-fee-version']) test(`terminal readback rejects ${fault}`, async () => {
const f = terminalFixture(fault)
await assert.rejects(() => verifyFleetTerminalState(f.context))
assert.equal(f.context.createdResources.fleetAcceptance.terminalReadback.status, 'CHECKING')
})