test: align manual booking list dependencies
This commit is contained in:
@@ -34,6 +34,11 @@ test('does not mutate historical fixtures or remove retained records', () => {
|
||||
assert.match(source, /context\.marker = originalMarker/)
|
||||
})
|
||||
|
||||
test('fails closed when invoked outside the manual matrix wrapper', () => {
|
||||
assert.match(source, /if \(!matrix\?\.pages\)/)
|
||||
assert.match(source, /missing=manualStateMatrix\.pages/)
|
||||
})
|
||||
|
||||
test('covers simplified clearance and customs actions through public multipart upload and complete APIs', () => {
|
||||
assert.match(source, /new FormData\(\)/)
|
||||
assert.match(source, /form\.append\('file'/)
|
||||
|
||||
@@ -318,6 +318,11 @@ async function completeSimpleDocuments(context, chain, matrix) {
|
||||
}
|
||||
|
||||
export async function run(context, matrix = context.createdResources.manualStateMatrix) {
|
||||
if (!matrix?.pages) {
|
||||
context.addStep(MODULE, '人工装柜状态模块由人工矩阵统一编排', null, false,
|
||||
'missing=manualStateMatrix.pages;请通过 manual-state-matrix 入口执行', OPTIONS)
|
||||
return
|
||||
}
|
||||
matrix.pages.containerLoading = { requiredStatuses: CONTAINER_STATUSES,
|
||||
requiredActions: ['clearance'], fixtures: {}, actions: {} }
|
||||
matrix.pages.preloadPlans = { requiredStatuses: PRELOAD_STATUSES, fixtures: {} }
|
||||
|
||||
@@ -18,6 +18,7 @@ test('focused matrix execution injects real container lifecycle prerequisites an
|
||||
'merchant-qualification-fixture',
|
||||
'phase3-container-loading',
|
||||
'phase3-loading',
|
||||
'ocean-bookings',
|
||||
'phase3-customs',
|
||||
'phase3-loading-finalize',
|
||||
'manual-state-matrix',
|
||||
@@ -28,6 +29,22 @@ test('focused matrix execution injects real container lifecycle prerequisites an
|
||||
]).modules, expected)
|
||||
})
|
||||
|
||||
test('focused splitting and manual groups resolve producers before consumers without duplicate internal runs', () => {
|
||||
const expected = [
|
||||
'merchant-qualification-fixture',
|
||||
'phase3-container-loading',
|
||||
'phase3-loading',
|
||||
'phase3-order-splitting',
|
||||
'ocean-bookings',
|
||||
'phase3-customs',
|
||||
'phase3-loading-finalize',
|
||||
'manual-state-matrix',
|
||||
]
|
||||
assert.deepEqual(normalizeModuleOrder([
|
||||
'phase3-order-splitting', 'manual-state-loading-pda', 'manual-state-matrix',
|
||||
]), expected)
|
||||
})
|
||||
|
||||
test('matrix delegates bounded groups and asserts every declared status has a retained id', () => {
|
||||
for (const group of ['order-inbound-status-fixtures', 'manual-state-loading-pda',
|
||||
'manual-state-ocean-trucking']) assert.match(source, new RegExp(group))
|
||||
|
||||
@@ -4,13 +4,19 @@ import test from 'node:test'
|
||||
|
||||
const source = readFileSync(new URL('./manual-state-ocean-trucking.mjs', import.meta.url), 'utf8')
|
||||
|
||||
test('retains every ocean booking and truck appointment list status through real APIs', () => {
|
||||
test('retains only public ocean booking list states while hidden states stay detail-only', () => {
|
||||
assert.match(source, /const OCEAN_BASE = ['"]\/api\/platform\/v1\/ocean-bookings['"]/)
|
||||
assert.doesNotMatch(source, /\/api\/platform\/v1\/first-leg\/ocean-bookings/)
|
||||
for (const status of ['DRAFT','SUBMITTED','CONFIRMED','RELEASED','FAILED','CHANGE_PENDING','CANCELLED',
|
||||
'PENDING_DISPATCH','DISPATCHED','PICKUP_IN_PROGRESS','ARRIVED_WAREHOUSE','LOADING','DEPARTED',
|
||||
'COMPLETED','RESCHEDULED','EXCEPTION']) assert.match(source, new RegExp(`['"]${status}['"]`))
|
||||
assert.match(source, /change-request/)
|
||||
assert.match(source, /const OCEAN_LIST_STATUSES = \['CONFIRMED', 'CHANGE_PENDING', 'RELEASED', 'CANCELLED'\]/)
|
||||
assert.match(source, /const OCEAN_HIDDEN_STATUSES = \['DRAFT', 'SUBMITTED', 'FAILED'\]/)
|
||||
assert.match(source, /hiddenFixtures/)
|
||||
assert.match(source, /code\(listResponse\) === 'A0400'/)
|
||||
assert.match(source, /后台样本仅通过详情契约验证/)
|
||||
assert.doesNotMatch(source, /code\(listResponse\) !== 'A0400'\) return/)
|
||||
const draftPayload = source.slice(source.indexOf('function oceanPayload'), source.indexOf('async function createOcean'))
|
||||
for (const field of ['billOfLadingNo', 'vesselName', 'voyageNo', 'estimatedSailingAt', 'estimatedArrivalAt']) {
|
||||
assert.doesNotMatch(draftPayload, new RegExp(`${field}:`))
|
||||
|
||||
@@ -2,6 +2,8 @@ const MODULE = 'manual-state-ocean-trucking'
|
||||
const OPTIONS = { scenario: 'manual-ocean-trucking-state-matrix', deploymentBlocker: true }
|
||||
const OCEAN_BASE = '/api/platform/v1/ocean-bookings'
|
||||
const TRUCK_BASE = '/api/platform/v1/truck-appointments'
|
||||
const OCEAN_LIST_STATUSES = ['CONFIRMED', 'CHANGE_PENDING', 'RELEASED', 'CANCELLED']
|
||||
const OCEAN_HIDDEN_STATUSES = ['DRAFT', 'SUBMITTED', 'FAILED']
|
||||
const OCEAN_STATUSES = ['DRAFT', 'SUBMITTED', 'CONFIRMED', 'RELEASED', 'FAILED', 'CHANGE_PENDING', 'CANCELLED']
|
||||
const TRUCK_STATUSES = ['DRAFT', 'PENDING_DISPATCH', 'DISPATCHED', 'PICKUP_IN_PROGRESS', 'ARRIVED_WAREHOUSE',
|
||||
'LOADING', 'DEPARTED', 'COMPLETED', 'RESCHEDULED', 'EXCEPTION', 'CANCELLED']
|
||||
@@ -128,6 +130,19 @@ async function verify(context, base, status, resourceId) {
|
||||
`status=${status}, id=${resourceId}`, OPTIONS)
|
||||
}
|
||||
|
||||
async function verifyHiddenOcean(context, status, resourceId) {
|
||||
const listResponse = await context.request('GET', `${OCEAN_BASE}?page=1&size=100&status=${status}`)
|
||||
context.assert(MODULE, `${status} 不进入正式订舱列表筛选`, listResponse,
|
||||
listResponse?.http === 200 && code(listResponse) === 'A0400',
|
||||
`HTTP=${listResponse?.http ?? 'missing'}, code=${code(listResponse)}, id=${resourceId}`, OPTIONS)
|
||||
|
||||
const detailResponse = await context.request('GET', `${OCEAN_BASE}/${resourceId}`)
|
||||
const detail = context.apiSuccess(MODULE, `${status} 后台样本仅通过详情契约验证`, detailResponse, '', OPTIONS)
|
||||
context.assert(MODULE, `${status} 后台详情身份与状态正确`, detailResponse,
|
||||
id(detail?.oceanBooking?.id) === resourceId && detail?.oceanBooking?.status === status,
|
||||
`id=${id(detail?.oceanBooking?.id) || 'missing'}, actual=${detail?.oceanBooking?.status || 'missing'}`, OPTIONS)
|
||||
}
|
||||
|
||||
export async function run(context, matrix = context.createdResources.manualStateMatrix) {
|
||||
const sourceOceanId = id(context.createdResources?.oceanBooking?.id)
|
||||
if (!sourceOceanId) throw new Error('缺少现有订舱生命周期模块生成的模板资源')
|
||||
@@ -136,17 +151,26 @@ export async function run(context, matrix = context.createdResources.manualState
|
||||
if (!template?.oceanBooking || !template?.parties?.length || !template?.containerRequirements?.length) {
|
||||
throw new Error('订舱模板缺少渠道、仓库、参与方或箱型需求')
|
||||
}
|
||||
matrix.pages.oceanBookings = { requiredStatuses: OCEAN_STATUSES, fixtures: {} }
|
||||
matrix.pages.oceanBookings = { requiredStatuses: OCEAN_LIST_STATUSES, fixtures: {}, hiddenFixtures: {} }
|
||||
for (const [index, status] of OCEAN_STATUSES.entries()) {
|
||||
const value = await buildOcean(context, template, status, index)
|
||||
const resourceId = id(value?.oceanBooking?.id); const actual = value?.oceanBooking?.status
|
||||
matrix.pages.oceanBookings.fixtures[status] = {
|
||||
id: resourceId, status: actual, detailPath: `/ocean-bookings/${resourceId}`,
|
||||
context.assert(MODULE, `订舱保留 ${status}`, null, resourceId && actual === status,
|
||||
`id=${resourceId || 'missing'}, actual=${actual || 'missing'}`, OPTIONS)
|
||||
if (!resourceId || actual !== status) continue
|
||||
const fixtureValue = {
|
||||
id: resourceId, status: actual,
|
||||
customerId: id(value?.oceanBooking?.customerId), customerName: value?.oceanBooking?.customerName,
|
||||
warehouseId: id(value?.oceanBooking?.warehouseId),
|
||||
}
|
||||
context.assert(MODULE, `订舱保留 ${status}`, null, resourceId && actual === status,
|
||||
`id=${resourceId || 'missing'}, actual=${actual || 'missing'}`, OPTIONS)
|
||||
if (OCEAN_HIDDEN_STATUSES.includes(status)) {
|
||||
matrix.pages.oceanBookings.hiddenFixtures[status] = fixtureValue
|
||||
await verifyHiddenOcean(context, status, resourceId)
|
||||
continue
|
||||
}
|
||||
matrix.pages.oceanBookings.fixtures[status] = {
|
||||
...fixtureValue, detailPath: `/ocean-bookings/${resourceId}`,
|
||||
}
|
||||
await verify(context, OCEAN_BASE, status, resourceId)
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user