优化
This commit is contained in:
@@ -12,28 +12,22 @@ function fixture(fault) {
|
||||
const history = row => ({ recordVersion: row.cost.recordVersion, action: row.action, snapshot: copy(row.cost) })
|
||||
function save(row, action) { row.action = action; row.history.unshift(history(row)) }
|
||||
function current(row) { const { cost } = row; return copy(cost) }
|
||||
let supplier
|
||||
const context = { marker, token: 'offline-test-only', createdResources: {},
|
||||
const supplier = { id: '8', tenantId: fault === 'foreign supplier' ? '9' : '0', category: 'TRUCKING', truckingScope: 'OVERSEAS', status: fault === 'inactive supplier' ? 'INACTIVE' : 'ACTIVE' }
|
||||
vehicles.set('71', { id: '71', plateNumber: 'EXISTING-TEST', region: 'OVERSEAS', ownership: fault === 'external vehicle' ? 'EXTERNAL' : 'OWNED', status: fault === 'inactive vehicle' ? 'INACTIVE' : 'IN_SERVICE', recordVersion: 0 })
|
||||
const context = { marker, token: 'offline-test-only', createdResources: {}, options: { fixedCompanyCostResources: { supplierId: '8', vehicleId: '71' } },
|
||||
assert(_module, label, _response, condition) { assert.ok(condition, label) },
|
||||
apiSuccess(_module, label, result) { assert.equal(result?.http, 200, label); assert.equal(result?.body?.code, '200', label); return result.body.data },
|
||||
async request(method, raw, body, _token, headers) {
|
||||
calls.push({ method, raw, body: copy(body), headers: copy(headers) }); const url = new URL(raw, 'https://fixture.invalid'), path = url.pathname
|
||||
if (method === 'POST' && path === '/api/platform/v1/suppliers') { supplier = { id: '8', ...copy(body) }; return response('8') }
|
||||
if (method === 'GET' && path === '/api/platform/v1/suppliers/8') return response(supplier)
|
||||
if (method === 'GET' && path.includes('/master-data/exchange-rates/')) return response({ month: path.split('/').at(-1), status: fault === 'inactive exchange' ? 'INACTIVE' : 'ACTIVE', usdToCnyAverage: '7.123456', recordVersion: 0 })
|
||||
if (path.endsWith('/fee-pool')) return response(fault === 'customer pollution' && costs.size ? [{ poolItemId: 'LEAK', customerId: '9', amount: 27.31, feeItemName: marker }] : [])
|
||||
if (path.endsWith('/cost-entries')) return response([])
|
||||
if (path.endsWith('/customer-accounts/9/summary')) return response({ customerId: '9', currency: 'CNY', totalReceivable: 100, receivedAmount: 30, outstandingReceivable: 70,
|
||||
pendingBilling: 0, totalCost: 0, paidCost: 0, outstandingPayable: 0, asOf: new Date().toISOString() })
|
||||
if (path === '/api/platform/v1/last-leg/master-data/vehicles' && method === 'POST') {
|
||||
const row = { id: '71', ...copy(body), recordVersion: 0 }; vehicles.set(row.id, row); return response(row)
|
||||
}
|
||||
if (path.startsWith('/api/platform/v1/last-leg/master-data/vehicles/')) {
|
||||
const row = vehicles.get(path.split('/vehicles/')[1].split('/')[0]); assert.ok(row)
|
||||
if (method === 'GET') return response(row)
|
||||
assert.equal(method, 'PATCH'); assert.equal(body.status, 'INACTIVE')
|
||||
if (fault === 'cleanup failure') return response(null, 'S0503', 503)
|
||||
row.status = 'INACTIVE'; row.recordVersion++; return response(row)
|
||||
assert.equal(method, 'GET', 'shared vehicle masters must remain read-only'); return response(row)
|
||||
}
|
||||
const care = path.match(/^\/api\/platform\/v1\/last-leg\/fleet\/vehicles\/71\/records(?:\/(.*))?$/)
|
||||
if (care) {
|
||||
@@ -118,28 +112,29 @@ function fixture(fault) {
|
||||
const id = value => String(value)
|
||||
const options = { pollAttempts: 2, pollDelayMs: 0 }
|
||||
test('independent runner requires explicit service readiness and only the specified TEST profile', () => {
|
||||
const env = 'C:/Users/BY-OY/.codex/env/chongchong-global/test-acceptance.env'
|
||||
const env = 'C:/Users/BY-OY/.codex/env/chongchong-global/test/acceptance.env'
|
||||
assert.throws(() => requireReady([], [`--env-file=${env}`]), /就绪/)
|
||||
assert.throws(() => requireReady([`--ready-commit=${READY_COMMIT}`], [`--env-file=${env.replace('test-acceptance', 'dev-acceptance')}`]), /授权目录/)
|
||||
assert.ok(requireReady([`--ready-commit=${READY_COMMIT}`], [`--env-file=${env}`]).endsWith('test-acceptance.env'))
|
||||
assert.throws(() => requireReady([`--ready-commit=${READY_COMMIT}`], [`--env-file=${env.replace('/test/', '/dev/')}`]), /授权目录/)
|
||||
assert.ok(requireReady([`--ready-commit=${READY_COMMIT}`], [`--env-file=${env}`]).replaceAll('\\', '/').endsWith('/test/acceptance.env'))
|
||||
})
|
||||
|
||||
test('readiness gate accepts only the full production anchor, not old anchors, shorthand or another commit', () => {
|
||||
const profile = ['--env-file=C:/Users/BY-OY/.codex/env/chongchong-global/test-acceptance.env']
|
||||
const profile = ['--env-file=C:/Users/BY-OY/.codex/env/chongchong-global/test/acceptance.env']
|
||||
assert.equal(READY_COMMIT, '8700fc34238bc33339351c73c15f3af8de8ce517')
|
||||
for (const commit of ['a6fd0ba3', 'cb6c54ff', '8700fc34', 'd05ff1cd', `${READY_COMMIT}0`]) {
|
||||
assert.throws(() => requireReady([`--ready-commit=${commit}`], profile), /就绪/)
|
||||
}
|
||||
assert.ok(requireReady([`--ready-commit=${READY_COMMIT}`], profile).endsWith('test-acceptance.env'))
|
||||
assert.ok(requireReady([`--ready-commit=${READY_COMMIT}`], profile).replaceAll('\\', '/').endsWith('/test/acceptance.env'))
|
||||
})
|
||||
test('company cost verifier exercises CNY/USD, void/rebuild, payment replay and customer isolation without direct transport', async () => {
|
||||
const { context, calls, vehicles, records, costs } = fixture()
|
||||
await run(context, options)
|
||||
const proof = context.createdResources.fleetCompanyCostAcceptance
|
||||
assert.equal(proof.status, 'VERIFIED'); assert.equal(proof.cleanup, 'INACTIVE')
|
||||
assert.equal(proof.status, 'VERIFIED'); assert.equal(proof.cleanup, 'REUSED_UNCHANGED'); assert.equal(proof.reusedMasterData, true)
|
||||
assert.equal(proof.cases.length, 2); assert.equal(records.size, 2)
|
||||
assert.ok([...costs.values()].every(row => row.cost.status === 'PAID' && row.payments.length === 2))
|
||||
assert.ok([...vehicles.values()].every(row => row.status === 'INACTIVE'))
|
||||
assert.ok([...vehicles.values()].every(row => row.status === 'IN_SERVICE' && row.recordVersion === 0))
|
||||
assert.equal(calls.some(call => call.method !== 'GET' && /suppliers|master-data\/vehicles/.test(call.raw)), false)
|
||||
assert.ok(calls.every(call => call.raw.startsWith('/api/platform/')))
|
||||
assert.equal(calls.some(call => /cost-entries|customer-accounts|customerId=/.test(call.raw)), false, 'must not borrow another task customer for evidence')
|
||||
assert.equal(calls.some(call => call.method === 'DELETE'), false)
|
||||
@@ -149,15 +144,21 @@ test('missing independent marker blocks before any write', async () => {
|
||||
const { context, calls } = fixture(); context.marker = ''
|
||||
await assert.rejects(run(context, options), /独立marker/); assert.equal(calls.length, 0)
|
||||
})
|
||||
for (const resources of [undefined, {}, { supplierId: '8' }, { supplierId: '8', vehicleId: '0' }, { supplierId: 8, vehicleId: 71 }]) test(`missing fixed company masters stop before HTTP: ${JSON.stringify(resources)}`, async () => {
|
||||
const { context, calls } = fixture(); context.options.fixedCompanyCostResources = resources
|
||||
await assert.rejects(run(context, options), /禁止自动创建主档/)
|
||||
assert.equal(calls.length, 0)
|
||||
})
|
||||
for (const fault of ['inactive exchange', 'delivery exhausted', 'never delivered', 'wrong source vehicle', 'wrong source version', 'wrong conversion', 'premature paid',
|
||||
'duplicate payment replay', 'overpayment allowed', 'partial money drift', 'paid void allowed', 'paid source mutable', 'customer pollution', 'file outage', 'wrong file bytes', 'cleanup failure']) {
|
||||
'duplicate payment replay', 'overpayment allowed', 'partial money drift', 'paid void allowed', 'paid source mutable', 'customer pollution', 'file outage', 'wrong file bytes',
|
||||
'foreign supplier', 'inactive supplier', 'external vehicle', 'inactive vehicle']) {
|
||||
test(`company cost verifier rejects ${fault} and preserves failure evidence`, async () => {
|
||||
const { context, vehicles } = fixture(fault)
|
||||
const { context, vehicles, calls } = fixture(fault), before = copy([...vehicles.values()])
|
||||
await assert.rejects(run(context, options))
|
||||
const proof = context.createdResources.fleetCompanyCostAcceptance
|
||||
assert.equal(proof.status, 'FAILED')
|
||||
assert.ok(proof.error || proof.cleanupError)
|
||||
if (vehicles.size && fault !== 'cleanup failure') assert.ok([...vehicles.values()].every(row => row.status === 'INACTIVE'))
|
||||
if (fault === 'cleanup failure') assert.equal(proof.cleanup, 'FAILED')
|
||||
assert.deepEqual([...vehicles.values()], before)
|
||||
assert.equal(calls.some(call => call.method !== 'GET' && /suppliers|master-data\/vehicles/.test(call.raw)), false)
|
||||
})
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user