Files
baiyue-firstleg/scripts/admin-test-env-modules/finance-full-fixtures-contract.test.mjs
T
2026-08-12 10:59:39 +08:00

116 lines
6.4 KiB
JavaScript

import test from 'node:test'
import assert from 'node:assert/strict'
import fs from 'node:fs'
import path from 'node:path'
import { fileURLToPath } from 'node:url'
import { run } from './finance-full-fixtures.mjs'
const here = path.dirname(fileURLToPath(import.meta.url))
const source = fs.readFileSync(path.join(here, 'finance-full-fixtures.mjs'), 'utf8')
test('finance fixture module is independently exported and marker isolated', () => {
assert.match(source, /export async function run\(context\)/)
assert.match(source, /context\.marker = `\$\{originalMarker\}-\$\{suffix\}`/)
assert.match(source, /createdResources\.financeFullFixtures/)
})
test('fixture covers weight, volume, manual order, and container allocation contracts', () => {
for (const basis of ['WEIGHT_KG', 'VOLUME_CBM', 'MANUAL_ORDER_FEE', 'CONTAINER_SHARED']) assert.match(source, new RegExp(basis))
assert.match(source, /request\(context, 'POST', '\/api\/platform\/finance\/v1\/cost-entries'/)
assert.match(source, /no-marker-owned-container-snapshot/)
})
test('fee writes use verified Firstleg paths and do not fabricate historical IDs', () => {
assert.match(source, /\/api\/platform\/v1\/inbounds\/.*fee-details\?accountId=/)
assert.match(source, /\/api\/platform\/v1\/loading-plans\/.*fee-details\?accountId=/)
assert.match(source, /sourceType: detail\?\.sourceType \|\| 'MANUAL'/)
assert.match(source, /created\?\.marker === context\.marker/)
assert.match(source, /\/fees`/)
assert.match(source, /chargeUnit === 'KG'/)
assert.match(source, /chargeUnit === 'CBM'/)
})
test('shared fixture source names the finance full acceptance contract', () => {
for (const field of ['marker', 'customerId', 'orders', 'feeSources', 'container', 'allocations', 'supplier', 'voucherFileId', 'deploymentBlocker']) assert.match(source, new RegExp(`\\b${field}\\b`))
for (const field of ['feeSourceId', 'sourceType', 'direction', 'currency', 'amount', 'businessDate', 'billingBasis']) {
assert.match(source, new RegExp(field))
}
})
function fakeContext(overrides = {}) {
const steps = []
const context = {
marker: 'FIN-BEHAVIOR', token: 'test-token', options: { gateway: 'http://invalid.local' },
steps, scenarios: [], createdResources: {}, context: {},
addStep(module, name, response, passed, evidence, options = {}) {
steps.push({ module, name, response, passed, evidence, deploymentBlocker: Boolean(options.deploymentBlocker && !passed) })
},
assert(module, name, response, passed, evidence, options) { this.addStep(module, name, response, passed, evidence, options) },
addCoverageGap(module, name, coverage, evidence, code) { this.addStep(module, name, null, false, `${code}: ${evidence}`, { deploymentBlocker: true }) },
apiSuccess(module, name, response) { this.addStep(module, name, response, true, 'fake'); return response?.body?.data },
async request() { throw new Error('behavior test must use hooks') },
financeFixtureHooks: {}, ...overrides,
}
return context
}
function hookSet({ missing = false } = {}) {
let automaticIndex = 0
return {
loadPricingEvidence: async () => ({ activeVersionIds: ['PRICE-1'] }),
createOrder: async (context, suffix) => ({ marker: `${context.marker}-${suffix}`, tenantId: '701',
orderId: `O-${suffix}`, orderNo: `NO-${suffix}`, waybillId: suffix === 'AUTO1' ? 'WB-1' : null, inboundId: `I-${suffix}` }),
measureOrder: async (context, resource) => ({ ...resource, measurementId: `M-${resource.orderId}`, actualWeightKg: 12.5, totalVolumeCbm: 0.072 }),
loadFeeItem: async (context, direction) => ({ id: direction === 'PAYABLE' ? '902' : '901', status: 'ACTIVE' }),
loadSupplier: async () => missing ? null : ({ id: 'PARTNER-1', partnerName: '往来单位一', status: 'ACTIVE' }),
uploadVoucher: async () => missing ? null : 'VOUCHER-1',
calculateAutomaticFee: async (context, resource) => {
automaticIndex += 1
const weight = automaticIndex % 2 === 1
return { feeSourceId: `F-${automaticIndex}`, orderId: resource.orderId, inboundId: resource.inboundId,
sourceType: 'FBA_PRICING', direction: 'RECEIVABLE', currency: 'CNY', amount: 100 + automaticIndex,
businessDate: weight ? '2026-08-10' : '2026-08-11', billingBasis: weight ? 'WEIGHT_KG' : 'VOLUME_CBM',
chargeUnit: weight ? 'KG' : 'CBM', chargeableQuantity: automaticIndex,
actualWeightKg: 54.4, actualVolumeCbm: 0.748 }
},
createManualFee: async (context, resource, item, direction, amount, basis, businessDate) => ({
feeSourceId: 'F-MANUAL', orderId: resource.orderId, inboundId: resource.inboundId, sourceType: 'MANUAL',
direction, currency: 'CNY', amount, businessDate, billingBasis: basis,
}),
}
}
test('run behavior emits consumer shape, both billing bases, distinct dates, supplier and voucher', async () => {
const context = fakeContext()
context.financeFixtureHooks = hookSet()
await run(context)
const fixture = context.createdResources.financeFullFixtures
assert.equal(fixture.customerId, '701')
assert.equal(fixture.orders.length, 5)
assert.equal(fixture.orders[0].orderNo, 'NO-AUTO1')
assert.equal(fixture.orders[0].waybillId, 'WB-1')
assert.equal(fixture.orders[0].actualWeightKg, 12.5)
assert.equal(fixture.orders[0].totalVolumeCbm, 0.072)
assert.deepEqual(new Set(fixture.feeSources.map((item) => item.billingBasis).filter((value) => value !== 'MANUAL_ORDER_FEE')),
new Set(['WEIGHT_KG', 'VOLUME_CBM']))
assert.ok(new Set(fixture.feeSources.map((item) => item.businessDate)).size >= 2)
assert.equal(fixture.supplier.supplierId, 'PARTNER-1')
assert.equal(fixture.supplier.supplierName, '往来单位一')
assert.equal(fixture.voucherFileId, 'VOUCHER-1')
assert.ok(Array.isArray(fixture.allocations))
})
test('run behavior preserves null IDs and deployment blockers when supplier, voucher and container are unavailable', async () => {
const context = fakeContext()
context.financeFixtureHooks = hookSet({ missing: true })
await run(context)
const fixture = context.createdResources.financeFullFixtures
assert.equal(fixture.supplier, null)
assert.equal(fixture.voucherFileId, null)
assert.deepEqual(fixture.container, { containerBookingId: null, containerNo: null })
assert.deepEqual(fixture.allocations, [])
assert.ok(fixture.deploymentBlocker.length >= 3)
assert.ok(context.steps.some((step) => step.deploymentBlocker && step.name.includes('往来单位')))
assert.ok(context.steps.some((step) => step.deploymentBlocker && step.name.includes('voucherFileId')))
})