完成单机TEST统一入口与可靠投递回归收尾

This commit is contained in:
2026-09-29 19:48:34 +08:00
parent 64a70c9f28
commit 6c0a026cc4
89 changed files with 968 additions and 983 deletions
@@ -41,7 +41,7 @@ async function domestic(context, method, name, path, body) {
}
async function overseas(context, method, name, path, body) {
const response = await context.requestOverseas(method, path, body)
const response = await context.request(method, path, body)
const data = context.apiSuccess(MODULE, name, response, trace(response), OPTIONS)
return { response, data }
}
@@ -96,17 +96,17 @@ async function loginMerchant(context, activeCustomer) {
}
const login = await context.request('POST', '/api/auth/login', { loginId: fixture.username, password: fixture.password }, '')
const auth = context.apiSuccess(MODULE, '采购客户账号登录', login, trace(login), OPTIONS)
const overseasToken = auth?.overseasAccessToken
context.assert(MODULE, '采购客户登录返回海外Token', login, nonEmpty(overseasToken),
`customerId=${id(activeCustomer?.id) || 'missing'}, tokenPresent=${Boolean(overseasToken)}; ${trace(login)}`, OPTIONS)
return nonEmpty(overseasToken) ? overseasToken : null
const token = auth?.accessToken
context.assert(MODULE, '采购客户登录返回统一Token', login, nonEmpty(token),
`customerId=${id(activeCustomer?.id) || 'missing'}, tokenPresent=${Boolean(token)}; ${trace(login)}`, OPTIONS)
return nonEmpty(token) ? token : null
}
async function createMerchantProcurement(context, activeCustomer, overseasToken) {
async function createMerchantProcurement(context, activeCustomer, token) {
const path = '/api/merchant/v1/last-leg/overseas-procurements'
const payload = procurementPayload(context, activeCustomer)
let activeToken = overseasToken
let response = await context.requestOverseas('POST', path, payload, {}, activeToken)
let activeToken = token
let response = await context.request('POST', path, payload, activeToken, {})
// A newly approved customer is projected to the overseas region asynchronously. The
// domestic login can therefore succeed a few seconds before the overseas gateway has
// received the matching USER/TENANT/AUTHORIZATION versions. Retry only that exact
@@ -117,7 +117,7 @@ async function createMerchantProcurement(context, activeCustomer, overseasToken)
const refreshedToken = await loginMerchant(context, activeCustomer)
if (!refreshedToken) break
activeToken = refreshedToken
response = await context.requestOverseas('POST', path, payload, {}, activeToken)
response = await context.request('POST', path, payload, activeToken, {})
}
const detail = context.apiSuccess(MODULE, '创建本轮客户采购订单', response, trace(response), OPTIONS)
const value = summary(detail)
@@ -132,15 +132,14 @@ async function createMerchantProcurement(context, activeCustomer, overseasToken)
`orderNo=${id(value?.orderNo) || 'missing'}, customerId=${id(value?.customerId) || 'missing'}, status=${value?.status || 'missing'}, version=${value?.version ?? 'missing'}; ${trace(response)}`, OPTIONS)
if (!valid) return null
const replayResponse = await context.requestOverseas('POST', path, payload, {}, activeToken)
const replayResponse = await context.request('POST', path, payload, activeToken, {})
const replayDetail = context.apiSuccess(MODULE, '采购创建同幂等键同载荷精确重放', replayResponse, trace(replayResponse), OPTIONS)
const replay = summary(replayDetail)
context.assert(MODULE, '采购幂等重放复用订单且版本不漂移', replayResponse,
replay?.orderNo === value.orderNo && Number(replay?.version) === Number(value.version),
`orderNo=${id(replay?.orderNo) || 'missing'}, version=${replay?.version ?? 'missing'}; ${trace(replayResponse)}`, OPTIONS)
const mismatch = await context.requestOverseas('POST', path,
{ ...payload, productName: `${payload.productName}-DIFFERENT` }, {}, activeToken)
const mismatch = await context.request('POST', path, { ...payload, productName: `${payload.productName}-DIFFERENT` }, activeToken, {})
expectedConflict(context, '采购创建同幂等键异载荷返回冲突', mismatch)
return { resource, payload }
@@ -156,11 +155,11 @@ async function prerequisites(context) {
const activeCustomer = activeCustomers.find((item) => id(item?.id) === fixtureCustomerId)
if (!longId(fixtureCustomerId) || !activeCustomer) return blocker(context, '本轮资格客户属于 ACTIVE 候选', tenants.response,
`marker fixture 客户 ${fixtureCustomerId || 'missing'} 不在 ACTIVE 候选中,禁止借用其他客户身份`)
const overseasToken = await loginMerchant(context, activeCustomer)
if (!overseasToken) return null
const token = await loginMerchant(context, activeCustomer)
if (!token) return null
const partnerWarehouse = await createPartnerWarehouse(context)
if (!partnerWarehouse) return null
const purchase = await createMerchantProcurement(context, activeCustomer, overseasToken)
const purchase = await createMerchantProcurement(context, activeCustomer, token)
if (!purchase) return null
const customerOptions = await overseas(context, 'GET', '查询采购客户候选', `${BASE}/overseas-procurements/customer-options?limit=200`)
@@ -181,7 +180,7 @@ async function prerequisites(context) {
if (!warehouse) return blocker(context, '采购仓候选存在 ACTIVE 仓', warehouseOptions.response,
'采购仓候选为空,禁止跳过采购三态清空')
return { activeCustomer, procurementCustomer, warehouse, customerOptions, warehouseOptions,
partnerWarehouse, purchase, overseasToken }
partnerWarehouse, purchase, token }
}
function assertProcurementHistory(context, result) {
@@ -249,8 +248,7 @@ async function procurementFlow(context, prerequisite) {
&& Number(clearedSummary?.version) === Number(omittedSummary?.version) + 1,
`version=${clearedSummary?.version ?? 'missing'}, specification=${clearedSummary?.productSpecification ?? 'null'}, warehouseId=${clearedSummary?.purchaseWarehouseId ?? 'null'}; ${trace(clearedResult.response)}`, OPTIONS)
const stale = await context.requestOverseas('PATCH', path,
{ version: Number(setSummary?.version), productSpecification: 'STALE-DO-NOT-APPLY' })
const stale = await context.request('PATCH', path, { version: Number(setSummary?.version), productSpecification: 'STALE-DO-NOT-APPLY' })
expectedConflict(context, '采购旧 version 返回 A0409', stale, true)
const afterConflict = await overseas(context, 'GET', '采购冲突后零漂移回查', path)
const afterConflictSummary = summary(afterConflict.data)
@@ -278,13 +276,9 @@ async function procurementFlow(context, prerequisite) {
summary(rejectedReplay.data)?.status === 'REJECTED'
&& Number(summary(rejectedReplay.data)?.version) === Number(rejectedSummary?.version),
trace(rejectedReplay.response), OPTIONS)
const reviewHashConflict = await context.requestOverseas('POST',
query(`${BASE}/overseas-procurements/${encodeURIComponent(owned.orderNo)}/review`, { customerId }),
{ ...rejectedReplayBody, remark: 'DIFFERENT-DO-NOT-APPLY' })
const reviewHashConflict = await context.request('POST', query(`${BASE}/overseas-procurements/${encodeURIComponent(owned.orderNo)}/review`, { customerId }), { ...rejectedReplayBody, remark: 'DIFFERENT-DO-NOT-APPLY' })
expectedConflict(context, '采购审核同键异载荷返回冲突', reviewHashConflict)
const reverseReview = await context.requestOverseas('POST',
query(`${BASE}/overseas-procurements/${encodeURIComponent(owned.orderNo)}/review`, { customerId }),
{ version: Number(rejectedSummary?.version), decision: 'APPROVE',
const reverseReview = await context.request('POST', query(`${BASE}/overseas-procurements/${encodeURIComponent(owned.orderNo)}/review`, { customerId }), { version: Number(rejectedSummary?.version), decision: 'APPROVE',
idempotencyKey: `${context.marker}-procurement-review-terminal-reverse`.slice(0, 255),
remark: 'REVERSE-DO-NOT-APPLY' })
expectedConflict(context, '采购审核终态逆向返回冲突', reverseReview)
@@ -333,8 +327,7 @@ async function assertCreateIdempotency(context, base, payload, customerId, label
context.assert(MODULE, `${label}幂等重放复用订单且版本不漂移`, replay.response,
replayValue?.orderNo === value.orderNo && Number(replayValue?.version) === Number(value.version),
`orderNo=${id(replayValue?.orderNo) || 'missing'}, version=${replayValue?.version ?? 'missing'}; ${trace(replay.response)}`, OPTIONS)
const mismatch = await context.requestOverseas('POST', path,
{ ...payload, destination: `${payload.destination}-DIFFERENT` })
const mismatch = await context.request('POST', path, { ...payload, destination: `${payload.destination}-DIFFERENT` })
expectedConflict(context, `${label}创建同幂等键异载荷返回冲突`, mismatch)
return { created, value, path }
}
@@ -406,8 +399,7 @@ async function truckFlow(context, customerId) {
after?.destination === `${payload.destination}-EDIT` && Number(after?.version) === Number(before?.version) + 1
&& after?.status === 'PENDING_REVIEW',
`version=${after?.version ?? 'missing'}, destination=${after?.destination || 'missing'}; ${trace(edited.response)}`, OPTIONS)
const stale = await context.requestOverseas('PATCH', path,
{ version: Number(before?.version), destination: 'STALE-DO-NOT-APPLY' })
const stale = await context.request('PATCH', path, { version: Number(before?.version), destination: 'STALE-DO-NOT-APPLY' })
expectedConflict(context, '卡车旧 version 编辑返回 A0409', stale, true)
const afterStale = await overseas(context, 'GET', '卡车旧 version 冲突后零漂移回查', path)
const afterStaleSummary = summary(afterStale.data)
@@ -430,11 +422,9 @@ async function truckFlow(context, customerId) {
summary(reviewReplay.data)?.status === 'WAITING_INBOUND'
&& Number(summary(reviewReplay.data)?.version) === Number(forwardedSummary?.version),
trace(reviewReplay.response), OPTIONS)
const reviewMismatch = await context.requestOverseas('POST', reviewPath,
{ ...reviewBody, remark: 'DIFFERENT-DO-NOT-APPLY' })
const reviewMismatch = await context.request('POST', reviewPath, { ...reviewBody, remark: 'DIFFERENT-DO-NOT-APPLY' })
expectedConflict(context, '卡车审核同键异载荷返回冲突', reviewMismatch)
const reversed = await context.requestOverseas('POST', reviewPath,
{ version: Number(forwardedSummary?.version), decision: 'REJECT',
const reversed = await context.request('POST', reviewPath, { version: Number(forwardedSummary?.version), decision: 'REJECT',
idempotencyKey: `${context.marker}-truck-review-terminal-reverse`.slice(0, 255),
remark: 'REVERSE-DO-NOT-APPLY' })
expectedConflict(context, '卡车审核终态逆向返回冲突', reversed)
@@ -483,8 +473,7 @@ async function looseboardFlow(context, customerId) {
after?.destination === `${payload.destination}-EDIT` && Number(after?.version) === Number(before?.version) + 1
&& after?.status === 'PENDING_ACCEPTANCE',
`version=${after?.version ?? 'missing'}, destination=${after?.destination || 'missing'}; ${trace(edited.response)}`, OPTIONS)
const stale = await context.requestOverseas('PUT', path,
{ ...editable, version: Number(before?.version), destination: 'STALE-DO-NOT-APPLY' })
const stale = await context.request('PUT', path, { ...editable, version: Number(before?.version), destination: 'STALE-DO-NOT-APPLY' })
expectedConflict(context, '散板旧 version 编辑返回 A0409', stale, true)
const afterStale = await overseas(context, 'GET', '散板旧 version 冲突后零漂移回查', path)
const afterStaleSummary = summary(afterStale.data)
@@ -511,11 +500,9 @@ async function looseboardFlow(context, customerId) {
summary(forwardReplay.data)?.status === 'DISPATCHED'
&& Number(summary(forwardReplay.data)?.version) === Number(forwardedSummary?.version),
trace(forwardReplay.response), OPTIONS)
const forwardMismatch = await context.requestOverseas('PATCH', statusPath,
{ ...forwardBody, remark: 'DIFFERENT-DO-NOT-APPLY' })
const forwardMismatch = await context.request('PATCH', statusPath, { ...forwardBody, remark: 'DIFFERENT-DO-NOT-APPLY' })
expectedConflict(context, '散板状态同键异载荷返回冲突', forwardMismatch)
const reversed = await context.requestOverseas('PATCH', statusPath,
{ version: Number(forwardedSummary?.version), status: 'PENDING_ACCEPTANCE',
const reversed = await context.request('PATCH', statusPath, { version: Number(forwardedSummary?.version), status: 'PENDING_ACCEPTANCE',
idempotencyKey: `${context.marker}-looseboard-status-terminal-reverse`.slice(0, 255),
remark: 'REVERSE-DO-NOT-APPLY' })
expectedConflict(context, '散板状态逆向回退返回冲突', reversed)