test: stabilize preload push replay assertions
This commit is contained in:
@@ -1,3 +1,5 @@
|
||||
import { diffPushPreloadStability, projectPushPreloadStability } from './push-preload-stability.mjs'
|
||||
|
||||
const MODULE = 'phase3-loading'
|
||||
const OPTIONS = { scenario: 'phase3-split-preload-loading', deploymentBlocker: true }
|
||||
const MERCHANT_USERNAME = process.env.MERCHANT_TEST_USERNAME || 'merchant_admin'
|
||||
@@ -5,6 +7,9 @@ const MERCHANT_PASSWORD = process.env.MERCHANT_TEST_PASSWORD || 'ChangeMe123!'
|
||||
|
||||
function id(value) { return value == null ? '' : String(value) }
|
||||
function codeOf(response) { return response?.body?.code == null ? 'missing' : String(response.body.code) }
|
||||
function responseEvidence(response) {
|
||||
return `HTTP=${response?.http ?? 'missing'}, code=${codeOf(response)}, requestId=${response?.requestId || 'missing'}, traceId=${response?.traceId || 'missing'}`
|
||||
}
|
||||
function failure(response) {
|
||||
return [400, 401, 403, 404, 409, 503].includes(response?.http)
|
||||
|| (response?.http === 200 && codeOf(response) !== '200')
|
||||
@@ -205,6 +210,13 @@ export async function run(context) {
|
||||
&& Number(link?.allocatedPackageCount) === 1,
|
||||
`linkId=${id(link?.id) || 'missing'}, preloadPlanId=${id(link?.preloadPlanId) || 'missing'}`, OPTIONS)
|
||||
if (!link?.id) return
|
||||
const postPushPlanResponse = await context.request('GET', `${smartLoadingBase}/plans/${loadingPlanId}`)
|
||||
const postPushPlan = context.apiSuccess(MODULE, '首次 push 后读取事务完成态柜次计划', postPushPlanResponse, '', OPTIONS)
|
||||
context.assert(MODULE, '事务完成态计划版本与 bridge 一致且保持 EDITING', postPushPlanResponse,
|
||||
postPushPlan?.status === 'EDITING' && Number(postPushPlan?.version) === Number(link?.loadingPlanVersion)
|
||||
&& Number(postPushPlan?.version) > Number(assignedLoadingPlan.version),
|
||||
`pushResponseVersion=${pushedLoadingPlan?.version ?? 'missing'}, persistedVersion=${postPushPlan?.version ?? 'missing'}, bridgeVersion=${link?.loadingPlanVersion ?? 'missing'}`, OPTIONS)
|
||||
if (postPushPlan?.status !== 'EDITING' || !Number.isInteger(Number(postPushPlan?.version))) return
|
||||
const missingContainerTaskResponse = await context.request('GET',
|
||||
`${pdaBase}/tasks?loadingPlanId=${encodeURIComponent(loadingPlanId)}&warehouseId=${encodeURIComponent(warehouseId)}`)
|
||||
const missingContainerTaskAbsent = missingContainerTaskResponse.http === 200 && codeOf(missingContainerTaskResponse) === 'A0404'
|
||||
@@ -213,8 +225,8 @@ export async function run(context) {
|
||||
`HTTP=${missingContainerTaskResponse.http}, code=${codeOf(missingContainerTaskResponse)}, requestId=${missingContainerTaskResponse.requestId || 'missing'}, traceId=${missingContainerTaskResponse.traceId || 'missing'}`, OPTIONS)
|
||||
if (!missingContainerTaskAbsent) return
|
||||
|
||||
const replayBaseline = JSON.stringify({
|
||||
plan: pushedLoadingPlan, detail: pushedDetail, links: pushedLinks,
|
||||
const replayBaseline = projectPushPreloadStability({
|
||||
plan: postPushPlan, detail: pushedDetail, links: pushedLinks,
|
||||
task: { http: missingContainerTaskResponse.http, code: codeOf(missingContainerTaskResponse) },
|
||||
})
|
||||
const pushReplayResponse = await request(context, 'POST', pushRequest.path, pushRequest.body, pushRequest.headers)
|
||||
@@ -228,16 +240,17 @@ export async function run(context) {
|
||||
const replayLinks = context.apiSuccess(MODULE, '重放后回查 bridge', replayLinksResponse, '', OPTIONS)
|
||||
const replayTaskResponse = await context.request('GET',
|
||||
`${pdaBase}/tasks?loadingPlanId=${encodeURIComponent(loadingPlanId)}&warehouseId=${encodeURIComponent(warehouseId)}`)
|
||||
const replaySnapshot = JSON.stringify({
|
||||
const replaySnapshot = projectPushPreloadStability({
|
||||
plan: replayPlan, detail: replayDetail, links: replayLinks,
|
||||
task: { http: replayTaskResponse.http, code: codeOf(replayTaskResponse) },
|
||||
})
|
||||
const replayDiff = diffPushPreloadStability(replayBaseline, replaySnapshot)
|
||||
context.assert(MODULE, 'push exact replay 对计划版本历史关联和任务零漂移', pushReplayResponse,
|
||||
replayBaseline === replaySnapshot && codeOf(replayTaskResponse) === 'A0404',
|
||||
`baselineBytes=${replayBaseline.length}, replayBytes=${replaySnapshot.length}`, OPTIONS)
|
||||
replayDiff.length === 0 && codeOf(replayTaskResponse) === 'A0404',
|
||||
`changed=${replayDiff.join('|') || 'none'}; replayTask=${responseEvidence(replayTaskResponse)}`, OPTIONS)
|
||||
|
||||
const sameKeyDifferentBody = await request(context, 'POST', pushRequest.path,
|
||||
{ expectedVersion: Number(pushedLoadingPlan.version) }, pushRequest.headers)
|
||||
{ expectedVersion: Number(postPushPlan.version) }, pushRequest.headers)
|
||||
context.addStep(MODULE, 'push 同 key 异参返回冲突', sameKeyDifferentBody,
|
||||
failure(sameKeyDifferentBody), `HTTP=${sameKeyDifferentBody.http}, code=${codeOf(sameKeyDifferentBody)}`, OPTIONS)
|
||||
const newKeyDuplicate = await request(context, 'POST', pushRequest.path, pushRequest.body,
|
||||
@@ -254,19 +267,20 @@ export async function run(context) {
|
||||
const rejectedLinks = context.apiSuccess(MODULE, '非法 push 后回查 bridge', rejectedLinksResponse, '', OPTIONS)
|
||||
const rejectedTaskResponse = await context.request('GET',
|
||||
`${pdaBase}/tasks?loadingPlanId=${encodeURIComponent(loadingPlanId)}&warehouseId=${encodeURIComponent(warehouseId)}`)
|
||||
const rejectedSnapshot = JSON.stringify({
|
||||
const rejectedSnapshot = projectPushPreloadStability({
|
||||
plan: rejectedPlan, detail: rejectedDetail, links: rejectedLinks,
|
||||
task: { http: rejectedTaskResponse.http, code: codeOf(rejectedTaskResponse) },
|
||||
})
|
||||
const rejectedDiff = diffPushPreloadStability(replayBaseline, rejectedSnapshot)
|
||||
context.assert(MODULE, '两类非法 push 后计划版本历史关联和任务仍零漂移', rejectedTaskResponse,
|
||||
failure(sameKeyDifferentBody) && failure(newKeyDuplicate)
|
||||
&& replayBaseline === rejectedSnapshot && codeOf(rejectedTaskResponse) === 'A0404',
|
||||
`baselineBytes=${replayBaseline.length}, rejectedBytes=${rejectedSnapshot.length}`, OPTIONS)
|
||||
if (replayBaseline !== rejectedSnapshot || codeOf(rejectedTaskResponse) !== 'A0404') return
|
||||
&& rejectedDiff.length === 0 && codeOf(rejectedTaskResponse) === 'A0404',
|
||||
`changed=${rejectedDiff.join('|') || 'none'}; sameKey=${responseEvidence(sameKeyDifferentBody)}; newKey=${responseEvidence(newKeyDuplicate)}; task=${responseEvidence(rejectedTaskResponse)}`, OPTIONS)
|
||||
if (rejectedDiff.length !== 0 || codeOf(rejectedTaskResponse) !== 'A0404') return
|
||||
|
||||
const transportResponse = await request(context, 'PATCH',
|
||||
`/api/platform/v1/first-leg/loading-plans/${loadingPlanId}/transport?warehouseId=${encodeURIComponent(warehouseId)}`, {
|
||||
containerNo, voyageNo: `P3V-${suffix}`, expectedVersion: Number(pushedLoadingPlan.version),
|
||||
containerNo, voyageNo: `P3V-${suffix}`, expectedVersion: Number(postPushPlan.version),
|
||||
operationReason: `${context.marker}-bind-container-no`,
|
||||
}, { 'Idempotency-Key': `${context.marker}-preload-transport`.slice(0, 128) })
|
||||
const transported = context.apiSuccess(MODULE, '预装 EDITING 清单绑定真实柜号', transportResponse, '', OPTIONS)
|
||||
|
||||
Reference in New Issue
Block a user