test: confirm plans before PDA acceptance

This commit is contained in:
2026-08-15 17:40:01 +08:00
parent 05921eca13
commit 28daf15082
6 changed files with 172 additions and 8 deletions
@@ -2,7 +2,19 @@ const MODULE = 'phase3-loading-model-bridge'
const OPTIONS = { scenario: 'parallel-loading-models', deploymentBlocker: true }
function id(value) { return value == null ? '' : String(value) }
function codeOf(response) { return response?.body?.code == null ? 'missing' : String(response.body.code) }
function failure(response) { return [400, 401, 403, 404, 409, 503].includes(response?.http) || (response?.http === 200 && codeOf(response) !== '200') }
export function stableLinkSnapshot(value) {
return {
id: id(value?.id), tenantId: id(value?.tenantId), inboundId: id(value?.inboundId),
preloadPlanId: id(value?.preloadPlanId), preloadStatus: id(value?.preloadStatus),
preloadVersion: Number(value?.preloadVersion), loadingPlanId: id(value?.loadingPlanId),
containerBookingId: id(value?.containerBookingId), containerNo: id(value?.containerNo),
loadingPlanStatus: id(value?.loadingPlanStatus), loadingPlanVersion: Number(value?.loadingPlanVersion),
allocatedPackageCount: Number(value?.allocatedPackageCount), linkedAt: id(value?.linkedAt),
}
}
function sameStableLink(left, right) {
return JSON.stringify(stableLinkSnapshot(left)) === JSON.stringify(stableLinkSnapshot(right))
}
async function request(context, method, path, body, headers = {}) {
try {
const response = await fetch(`${context.options.gateway}${path}`, { method,
@@ -37,10 +49,25 @@ export async function run(context) {
context.assert(MODULE, '柜次侧反查到同一预装计划', planResponse,
Array.isArray(planLinks) && planLinks.some((item) => id(item.inboundId) === inboundId
&& id(item.preloadPlanId) === id(fixture.preloadPlanId)), `links=${planLinks?.length ?? 'n/a'}`, OPTIONS)
const forged = await request(context, 'POST',
const pairReplay = await request(context, 'POST',
`/api/platform/v1/inbounds/${inboundId}/preload/loading-plans/${loadingPlanId}?tenantId=${encodeURIComponent(tenantId)}`,
{ expectedPreloadVersion: 0, expectedLoadingPlanVersion: 0 },
{ 'Idempotency-Key': `${context.marker}-bridge-bind`.slice(0, 128) })
context.addStep(MODULE, '桥接同幂等键不同版本请求拒绝且不产生部分更新', forged, failure(forged),
`HTTP=${forged.http}, code=${codeOf(forged)}`, OPTIONS)
const replayedLink = pairReplay?.body?.data
context.addStep(MODULE, '已由推送建立的同一桥接 pair 重放返回原关联', pairReplay,
pairReplay.http === 200 && codeOf(pairReplay) === '200' && sameStableLink(replayedLink, link),
`HTTP=${pairReplay.http}, code=${codeOf(pairReplay)}, linkId=${id(replayedLink?.id) || 'missing'}`, OPTIONS)
const afterInboundResponse = await request(context, 'GET', inboundPath)
const afterInboundLinks = context.apiSuccess(MODULE, '桥接 pair 重放后回查入库侧关联', afterInboundResponse, '', OPTIONS)
const afterInboundLink = Array.isArray(afterInboundLinks)
? afterInboundLinks.find((item) => id(item.loadingPlanId) === loadingPlanId) : null
const afterPlanResponse = await request(context, 'GET', `/api/platform/v1/first-leg/smart-loading/plans/${loadingPlanId}/preloads`)
const afterPlanLinks = context.apiSuccess(MODULE, '桥接 pair 重放后回查柜次侧关联', afterPlanResponse, '', OPTIONS)
const afterPlanLink = Array.isArray(afterPlanLinks)
? afterPlanLinks.find((item) => id(item.inboundId) === inboundId) : null
context.assert(MODULE, '桥接 pair 重放不改关联身份、状态或双侧版本', afterPlanResponse,
sameStableLink(afterInboundLink, link) && sameStableLink(afterPlanLink, link),
`linkId=${id(link?.id)}, preloadVersion=${link?.preloadVersion}, loadingPlanVersion=${link?.loadingPlanVersion}`,
OPTIONS)
}