优化
This commit is contained in:
@@ -1,3 +1,4 @@
|
||||
import { exportWorkbook } from './download-center-fixture.mjs'
|
||||
import assert from 'node:assert/strict'
|
||||
import { readFileSync } from 'node:fs'
|
||||
import test from 'node:test'
|
||||
@@ -104,12 +105,20 @@ function fakeContext({ softAssertions = false, refreshEmpty = false, careLeak =
|
||||
coverageGaps.push({ module, scenario, name, reason, category, ...metadata })
|
||||
},
|
||||
async request(...args) {
|
||||
if (args[1].startsWith('/api/platform/v1/files/export-tasks')) {
|
||||
calls.push({ gateway: 'domestic', method: args[0], path: args[1], body: args[2] })
|
||||
return ok({ id: args[2]?.exportType || args[1].split('/').at(-1), status: args[0] === 'POST' ? 'PENDING' : 'SUCCEEDED' })
|
||||
}
|
||||
const route = /\/(?:last-leg|overseas-warehouse-resources)(?:\/|\?|$)/.test(String(args[1]));
|
||||
const handler = route ? async function(method,path,body,token = 'admin-overseas-token',extraHeaders = {}) {
|
||||
calls.push({ gateway: 'overseas', method, path, body, extraHeaders, tokenKind: token === 'deny-overseas-token' ? 'denied' : 'admin' })
|
||||
assert.notEqual(method, 'DELETE')
|
||||
if (token === 'deny-overseas-token') return forbidden()
|
||||
if (path.includes('/fleet/vehicles/')) {
|
||||
if (method === 'POST' && path.endsWith('/records/finance-status')) {
|
||||
return ok(body.recordNos.map(recordNo => ({ recordNo, status: processingMarksPaid ? 'PAID' : 'UNLINKED',
|
||||
sourceVersion: null, submittedRecordVersion: null, finance: null })))
|
||||
}
|
||||
const url = new URL(path, 'https://fixture.invalid'), parts = url.pathname.split('/records'), owner = parts[0].split('/').at(-1)
|
||||
const suffix = parts[1], record = careRows.get(suffix.split('/')[1])
|
||||
if (record && owner !== record.vehicleId && !careLeak) return { http: 200, body: { code: 'A0404' } }
|
||||
@@ -117,7 +126,7 @@ function fakeContext({ softAssertions = false, refreshEmpty = false, careLeak =
|
||||
const prior = [...careRows.values()].find(value => value.key === body.idempotencyKey && value.vehicleId === owner)
|
||||
if (prior) return ok(structuredClone(prior))
|
||||
const created = { recordNo: `VR-${careRows.size + 1}`, vehicleId: owner, details: structuredClone(body.details), files: [], recordVersion: 0, key: body.idempotencyKey,
|
||||
paymentStatus: ['REPAIR', 'RESCUE'].includes(body.details.recordType) ? 'UNLINKED' : null }
|
||||
paymentStatus: null }
|
||||
careRows.set(created.recordNo, created); careHistory.set(created.recordNo, [{ snapshot: structuredClone(created) }]); return ok(structuredClone(created))
|
||||
}
|
||||
if (method === 'GET' && !suffix) {
|
||||
@@ -130,7 +139,6 @@ function fakeContext({ softAssertions = false, refreshEmpty = false, careLeak =
|
||||
if (method === 'PUT') {
|
||||
if (Number(body.recordVersion) !== record.recordVersion) return conflict()
|
||||
record.details = structuredClone(body.details); record.recordVersion++
|
||||
if (processingMarksPaid && record.details.incident?.processingStatus === 'COMPLETED') record.paymentStatus = 'PAID'
|
||||
careHistory.get(record.recordNo).unshift({ reason: body.reason, snapshot: structuredClone(record) }); return ok(structuredClone(record))
|
||||
}
|
||||
}
|
||||
@@ -286,13 +294,20 @@ function fakeContext({ softAssertions = false, refreshEmpty = false, careLeak =
|
||||
calls.push({ gateway: 'overseas-binary', method, path })
|
||||
assert.equal(method, 'GET')
|
||||
if (path.includes('/fleet/vehicles/')) return { http: 200, contentType: 'image/png', bytes: Buffer.from('iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAQAAAC1HAwCAAAAC0lEQVR42mP8/x8AAwMCAO+aH1kAAAAASUVORK5CYII=', 'base64') }
|
||||
assert.match(path, /\/(?:overseas-quotes|exchange-rates|vehicles)\/export\?/)
|
||||
let csv = ''
|
||||
if (path.includes('/overseas-quotes/')) csv = `报价ID,报价名称,合作仓编码,合作仓名称,报价方,币种,生效开始,生效结束,版本号,状态,更新时间\r\n${state.quote.summary.id},${state.quote.summary.name},${state.quote.summary.warehouseCode},${state.quote.summary.warehouseName},${state.quote.summary.providerName},USD,2098-01-01,2098-12-31,V1,ACTIVE,2026-08-21\r\n`
|
||||
else if (path.includes('/exchange-rates/')) csv = `月份,基准币种,报价币种,月平均汇率,状态,更新人,更新时间\r\n${state.exchange.month},USD,CNY,${state.exchange.usdToCnyAverage},${state.exchange.status},admin,2026-08-21\r\n`
|
||||
else csv = `车牌号,车型,油耗(L/100km),当前公里码(km),司机或外派单位,联系电话,区域,车辆归属,状态,最大托位,最大载重(kg),可用容积(m³),更新时间\r\n${state.vehicle.plateNumber},${state.vehicle.model},18.75,101,Carrier,123,OVERSEAS,OWNED,${state.vehicle.status},${state.vehicle.maxPalletSpaces},${state.vehicle.maxLoadKg},${state.vehicle.maxVolumeCbm},2026-08-21\r\n`
|
||||
return { method, path, http: 200, body: null, bytes: new TextEncoder().encode(`\uFEFF${csv}`),
|
||||
contentType: 'text/csv;charset=UTF-8', requestId: 'req-csv' }
|
||||
assert.match(path, /files\/export-tasks\/[^/]+\/download$/)
|
||||
let headers, values
|
||||
if (path.includes('OVERSEAS_QUOTE_LIST')) {
|
||||
headers = ['报价名称', '合作仓编码', '合作仓名称', '报价方']
|
||||
values = [state.quote.summary.name, state.quote.summary.warehouseCode, state.quote.summary.warehouseName, state.quote.summary.providerName]
|
||||
} else if (path.includes('MONTHLY_EXCHANGE_RATE_LIST')) {
|
||||
headers = ['月份', '月平均汇率', '状态']
|
||||
values = [state.exchange.month, state.exchange.usdToCnyAverage, state.exchange.status]
|
||||
} else {
|
||||
headers = ['车牌号', '最大托位', '最大载重(kg)', '可用容积(m³)', '状态']
|
||||
values = [state.vehicle.plateNumber, state.vehicle.maxPalletSpaces, state.vehicle.maxLoadKg, state.vehicle.maxVolumeCbm, state.vehicle.status]
|
||||
}
|
||||
return { method, path, http: 200, bytes: exportWorkbook(headers, values),
|
||||
contentType: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet' }
|
||||
},
|
||||
}
|
||||
return { context, state }
|
||||
@@ -304,20 +319,20 @@ test('静态锁定统一Gateway主数据生命周期、CSV与安全边界', () =
|
||||
assert.match(source, /context\.request\('POST'/)
|
||||
assert.match(source, /context\.request\('PUT'/)
|
||||
assert.match(source, /context\.request\('PATCH'/)
|
||||
assert.match(source, /context\.requestBinary\('GET'/)
|
||||
assert.match(source, /verifyDownloadCenterExport\(context/)
|
||||
assert.match(source, /context\.expectConflict/)
|
||||
assert.match(source, /warehouse-options\?refresh=true/)
|
||||
assert.match(source, /空候选不负缓存30分钟/)
|
||||
assert.match(source, /30分钟正缓存与刷新快照一致/)
|
||||
assert.match(source, /无quote:list权限访问海外报价被拒绝/)
|
||||
assert.match(source, /表头与marker内容/)
|
||||
assert.match(source, /verifyDownloadCenterExport/)
|
||||
assert.match(source, /finally\s*\{/)
|
||||
assert.match(source, /context\.createdResources\.phase4OverseasMasterData/)
|
||||
assert.doesNotMatch(source, /context\.addCoverageGap/)
|
||||
assert.match(source, /2090 \+ Math\.floor/)
|
||||
assert.doesNotMatch(source, /\/internal\/|overseas-partners|https?:\/\/|fetch\(|process\.env|request(?:Overseas)?\('DELETE'/)
|
||||
for (const endpoint of ['overseas-quotes/warehouse-options', 'overseas-quotes/export',
|
||||
'exchange-rates/export', 'vehicles/export']) assert.ok(source.includes(endpoint))
|
||||
for (const endpoint of ['overseas-quotes/warehouse-options', 'OVERSEAS_QUOTE_LIST',
|
||||
'MONTHLY_EXCHANGE_RATE_LIST', 'VEHICLE_LIST']) assert.ok(source.includes(endpoint))
|
||||
assert.doesNotMatch(controllerSource, /Idempotency-Key|IdempotencyKey/)
|
||||
assert.doesNotMatch(source, /Idempotency-Key/)
|
||||
})
|
||||
@@ -334,7 +349,7 @@ test('API dropping updated vehicle capacity fails even with a correct CSV and cl
|
||||
}
|
||||
await run(context)
|
||||
assert.equal(context.steps.find(step => step.name === '车辆编辑保持三项实际容量')?.passed, false)
|
||||
assert.equal(context.steps.find(step => step.name === '导出marker车辆CSV表头与marker内容')?.passed, true)
|
||||
assert.equal(context.steps.find(step => step.name === 'VEHICLE_LIST表头与marker内容')?.passed, true)
|
||||
assert.equal(context.createdResources.phase4OverseasMasterData.vehicle.finalStatus, 'INACTIVE')
|
||||
})
|
||||
|
||||
@@ -358,7 +373,7 @@ test('marker资源完成创建、详情、编辑、冲突、状态、CSV并全
|
||||
assert.equal(state.role.status, 'DISABLED')
|
||||
assert.equal(state.user.status, 'DISABLED')
|
||||
assert.equal(state.optionReads, 4)
|
||||
assert.equal(context.calls.filter((call) => call.gateway === 'overseas-binary' && call.path.includes('/export?')).length, 3)
|
||||
assert.equal(context.calls.filter((call) => call.gateway === 'overseas-binary' && call.path.includes('/export-tasks/') && call.path.endsWith('/download')).length, 3)
|
||||
assert.equal(resource.vehicle.care.status, 'VERIFIED')
|
||||
assert.equal(state.spareVehicle.status, 'INACTIVE')
|
||||
assert.equal(context.calls.filter((call) => call.method === 'DELETE').length, 0)
|
||||
@@ -395,7 +410,22 @@ test('事件处理完成被错误映射为已付款时,真实验收编排必
|
||||
const { context } = fakeContext({ softAssertions: true, processingMarksPaid: true })
|
||||
await run(context)
|
||||
assert.equal(context.createdResources.phase4OverseasMasterData.vehicle.care.status, 'CHECKING')
|
||||
assert.ok(context.steps.some(step => step.name === '处理完成保持独立的费用及付款事实' && !step.passed && step.deploymentBlocker))
|
||||
assert.ok(context.steps.some(step => step.name === '处理完成未自动提交财务或标记付款' && !step.passed && step.deploymentBlocker))
|
||||
})
|
||||
|
||||
test('UNLINKED付款响应夹带财务单据或提交版本仍阻断,不忽略独立查询证据', async () => {
|
||||
for (const facts of [{ submittedRecordVersion: 1 }, { finance: { costNo: 'COST-UNEXPECTED' } }]) {
|
||||
const { context } = fakeContext({ softAssertions: true })
|
||||
const request = context.request.bind(context)
|
||||
context.request = async (...args) => {
|
||||
const response = await request(...args)
|
||||
if (args[1].endsWith('/records/finance-status')) Object.assign(response.body.data[0], facts)
|
||||
return response
|
||||
}
|
||||
await run(context)
|
||||
assert.equal(context.createdResources.phase4OverseasMasterData.vehicle.care.status, 'CHECKING')
|
||||
assert.ok(context.steps.some(step => step.name === '处理完成未自动提交财务或标记付款' && !step.passed && step.deploymentBlocker))
|
||||
}
|
||||
})
|
||||
|
||||
test('refresh后仍为空时报价前置明确deployment blocker且不产生coverageGap假PASS', async () => {
|
||||
|
||||
Reference in New Issue
Block a user