Merge remote-tracking branch 'origin/test' into dev

# Conflicts:
#	scripts/admin-test-env-modules/phase4-overseas-pda.mjs
#	scripts/agents-index-contract.ps1
This commit is contained in:
2026-09-02 15:21:20 +08:00
33 changed files with 147 additions and 171 deletions
@@ -195,12 +195,16 @@ export async function run(context, matrix = context.createdResources.manualState
await verify(context, OCEAN_BASE, status, resourceId)
}
const releasedOcean = matrix.pages.oceanBookings.fixtures.RELEASED
if (!releasedOcean.id || !releasedOcean.warehouseId) {
throw new Error('RELEASED 订舱缺少拖车所需的仓库归属')
}
matrix.pages.truckAppointments = { requiredStatuses: TRUCK_STATUSES, fixtures: {} }
for (const [index, status] of TRUCK_STATUSES.entries()) {
const released = await buildOcean(context, template, 'RELEASED', index + 100)
const releasedOcean = {
id: id(released?.oceanBooking?.id),
warehouseId: id(released?.oceanBooking?.warehouseId),
}
if (!releasedOcean.id || !releasedOcean.warehouseId) {
throw new Error(`拖车状态样本 ${index} 缺少独立 RELEASED 订舱`)
}
const value = await buildTruck(context, releasedOcean, status, index)
const resourceId = id(value?.id)
matrix.pages.truckAppointments.fixtures[status] = { id: resourceId, status: value?.status, detailPath: `/truck-appointments/${resourceId}` }
@@ -43,7 +43,7 @@ async function loginMerchant(context) {
const password = account?.password || process.env.MERCHANT_TEST_PASSWORD || ''
if (!username || !password) throw new Error('缺少客户登录凭据')
const response = await context.request('POST', '/api/auth/login', {
username, password,
loginId: username, password,
}, '')
const token = success(response) ? response.body?.data?.accessToken : null
if (!token) throw new Error(`本轮客户登录失败: requestId=${response?.requestId || 'missing'}, traceId=${response?.traceId || 'missing'}`)
@@ -134,6 +134,16 @@ function routes(context, merchantToken) {
export async function prepare(context) {
const outerMarker = context.marker
const isolatedResourceKeys = ['phase3Loading', 'phase3LoadingCompletedProducer', 'orchestrationFixtures']
const isolatedResourceSnapshot = new Map(isolatedResourceKeys.map((name) => [name, {
present: Object.hasOwn(context.createdResources, name), value: context.createdResources[name],
}]))
const restoreIsolatedResources = () => {
for (const [name, snapshot] of isolatedResourceSnapshot) {
if (snapshot.present) context.createdResources[name] = snapshot.value
else delete context.createdResources[name]
}
}
const restore = await context.preparePhase3LoadingFixture('-CUSTOMS-MIXED', false, {
primary: 'BUY_DECLARATION', incremental: 'TAX_REFUND',
})
@@ -154,6 +164,7 @@ export async function prepare(context) {
if (!source?.loadingPlanId || !source?.containerBookingId || source?.finalStatus !== 'LOADED') {
context.marker = outerMarker
restore()
restoreIsolatedResources()
throw new Error(`混合柜未进入LOADED: planId=${id(source?.loadingPlanId) || 'missing'}, status=${source?.finalStatus || 'missing'}`)
}
const platform = await context.request('GET', `${PLATFORM}/${encodeURIComponent(id(source.loadingPlanId))}`)
@@ -169,6 +180,7 @@ export async function prepare(context) {
if (!buy.length || !refund.length) {
context.marker = outerMarker
restore()
restoreIsolatedResources()
throw new Error(`正式装柜API未形成混合柜: buy=${buy.length}, tax=${refund.length}`)
}
const merchantToken = await loginMerchant(context)
@@ -208,5 +220,6 @@ export async function prepare(context) {
delete context.context.phase3ContainerCustomsRoutes
context.marker = outerMarker
restore()
restoreIsolatedResources()
}
}
@@ -48,6 +48,8 @@ test('outbound-created query supports automated or manual carrier then reaches P
assert.match(pda, /convertReceivingContainers\(context, producers\)/)
assert.match(pda, /last-leg\/orders\/container-summaries/)
assert.match(pda, /last-leg\/inbound-plans\/convert-container/)
assert.match(pda, /Number\(summary\?\.missingInboundCodeCount\) === 0/)
assert.doesNotMatch(pda, /summary\?\.eligible/)
assert.match(pda, /item\?\.shippingReady === true/)
assert.match(pda, /nonBlank\(item\?\.carrierScheduleQueryId\)/)
assert.match(pda, /targetCorrelated/)