2026-09-08 23:06:07 +08:00
|
|
|
import assert from 'node:assert/strict'
|
|
|
|
|
import { readFileSync } from 'node:fs'
|
|
|
|
|
import test from 'node:test'
|
2026-09-09 12:19:16 +08:00
|
|
|
import { containerWorkbenchGaps } from './phase3-container-loading.mjs'
|
2026-09-08 23:06:07 +08:00
|
|
|
|
|
|
|
|
const read = (name) => readFileSync(new URL(name, import.meta.url), 'utf8')
|
|
|
|
|
|
2026-09-09 12:19:16 +08:00
|
|
|
test('workbench DTO rejects the old flat entity and incomplete action/state projections', () => {
|
|
|
|
|
const container = { id: '71', cabinetNo: 'CB-20260909-01', version: 0 }
|
|
|
|
|
const row = { container, workbenchStage: 'WAIT_LOADING', statusSummary: {}, allowedActions: [] }
|
|
|
|
|
assert.deepEqual(containerWorkbenchGaps(row), [])
|
|
|
|
|
assert.ok(containerWorkbenchGaps(container).includes('container.id'))
|
|
|
|
|
for (const field of ['container', 'workbenchStage', 'statusSummary', 'allowedActions']) {
|
|
|
|
|
const invalid = { ...row }
|
|
|
|
|
delete invalid[field]
|
|
|
|
|
assert.ok(containerWorkbenchGaps(invalid).length > 0, `missing ${field} must fail`)
|
|
|
|
|
}
|
|
|
|
|
assert.ok(containerWorkbenchGaps({ ...row, container: { ...container, version: null } }).includes('container.version'))
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
test('Admin read routes match controller workbench endpoints and default HTTP regression exercises the page DTO', () => {
|
|
|
|
|
const controller = read('../../firstleg/src/main/java/com/baiyue/firstleg/controller/PlatformContainerController.java')
|
|
|
|
|
const admin = read('../../../apps/admin-web/src/modules/container-loading/api/platformContainerLoading.ts')
|
|
|
|
|
assert.match(controller, /@GetMapping\("\/domestic"\)/)
|
|
|
|
|
assert.match(controller, /@GetMapping\("\/domestic\/\{id\}"\)/)
|
|
|
|
|
assert.match(controller, /ApiResponse<PageResult<WorkbenchItem>>/)
|
|
|
|
|
assert.match(admin, /listContainers\([^\n]*workbench: ContainerWorkbenchKind = 'DOMESTIC'/)
|
|
|
|
|
assert.ok(admin.includes('`${containerPath}/${workbench.toLowerCase()}`'))
|
|
|
|
|
assert.ok(admin.includes('`${containerPath}/${workbench.toLowerCase()}/${encodeURIComponent(containerId)}`'))
|
|
|
|
|
const loading = read('./phase3-container-loading.mjs')
|
|
|
|
|
assert.ok(loading.includes('size=20&scope=ACTIVE&status='))
|
|
|
|
|
assert.ok(loading.includes('containerWorkbenchGaps(containerDetailResponse.body?.data)'))
|
|
|
|
|
assert.ok(loading.includes('records(page).every((item) => containerWorkbenchGaps(item).length === 0)'))
|
|
|
|
|
assert.ok(!loading.includes('value?.container || value'))
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
test('manual and coload consumers read domestic WorkbenchItem rather than the removed flat routes', () => {
|
|
|
|
|
for (const name of ['manual-loading-complete-fixture', 'manual-order-splitting-verify',
|
|
|
|
|
'manual-pda-ready-fixture', 'manual-pda-ready-verify', 'manual-preload-push-fixture', 'manual-preload-push-verify', 'coload-groups']) {
|
|
|
|
|
const source = read(`./${name}.mjs`)
|
|
|
|
|
assert.ok(source.includes("context.request('GET', `${CONTAINERS}/domestic/${"), name)
|
|
|
|
|
assert.ok(!source.includes("context.request('GET', `${CONTAINERS}/${"), name)
|
|
|
|
|
assert.match(source, /OPTIONS\)\?\.container/, name)
|
|
|
|
|
}
|
|
|
|
|
const states = read('./manual-state-loading-pda.mjs')
|
|
|
|
|
assert.ok(states.includes('`${CONTAINERS}/domestic?scope=ACTIVE&status='))
|
|
|
|
|
assert.ok(states.includes('item.container?.planStatus === status'))
|
|
|
|
|
})
|
|
|
|
|
|
2026-09-08 23:06:07 +08:00
|
|
|
test('domestic container fixtures use the current workbench detail route', () => {
|
|
|
|
|
const containerLoading = read('./phase3-container-loading.mjs')
|
2026-09-09 02:40:42 +08:00
|
|
|
assert.ok(containerLoading.includes("context.request('GET', `${DOMESTIC_CONTAINERS}/${containerId}`)"))
|
2026-09-08 23:06:07 +08:00
|
|
|
assert.ok(!containerLoading.includes("context.request('GET', `${CONTAINERS}/${containerId}`)"))
|
2026-09-09 02:40:42 +08:00
|
|
|
assert.ok(containerLoading.includes("const containerDetail = containerRecord(context.apiSuccess(MODULE, '回查货柜详情'"))
|
|
|
|
|
assert.ok(containerLoading.includes("const simulationBeforeLink = containerRecord(context.apiSuccess(MODULE, '预装确认前读取模拟柜最新版本'"))
|
|
|
|
|
assert.ok(containerLoading.includes('`${DOMESTIC_CONTAINERS}?page=1&size=50&scope=ACTIVE&keyword='))
|
|
|
|
|
assert.ok(containerLoading.includes('records(activeContainers).map(containerRecord)'))
|
2026-09-08 23:06:07 +08:00
|
|
|
|
|
|
|
|
const loading = read('./phase3-loading.mjs')
|
|
|
|
|
assert.ok(loading.includes("context.request('GET', `/api/platform/v1/containers/domestic/${containerBookingId}`)"))
|
|
|
|
|
assert.ok(!loading.includes("context.request('GET', `/api/platform/v1/containers/${containerBookingId}`)"))
|
2026-09-09 02:40:42 +08:00
|
|
|
assert.ok(loading.includes("const latestContainer = containerRecord(context.apiSuccess(MODULE, '合并前读取模拟柜最新版本'"))
|
2026-09-08 23:06:07 +08:00
|
|
|
|
|
|
|
|
const crossRegion = read('./phase4-cross-region-events.mjs')
|
|
|
|
|
const fixtureId = 'encodeURIComponent(id(phase3.containerBookingId))'
|
|
|
|
|
assert.ok(crossRegion.includes(`/api/platform/v1/containers/domestic/\${${fixtureId}}`))
|
|
|
|
|
assert.ok(!crossRegion.includes(`/api/platform/v1/containers/\${${fixtureId}}`))
|
2026-09-08 23:16:52 +08:00
|
|
|
assert.ok(crossRegion.includes('/api/platform/v1/containers/domestic?scope=HISTORY&containerNo='))
|
2026-09-08 23:14:36 +08:00
|
|
|
assert.ok(crossRegion.includes('.map((item) => item?.container).filter('))
|
2026-09-08 23:06:07 +08:00
|
|
|
})
|
2026-09-08 23:11:49 +08:00
|
|
|
|
|
|
|
|
test('service center truck fixture uses the released booking warehouse', () => {
|
|
|
|
|
const source = read('./service-center-flow.mjs')
|
|
|
|
|
assert.ok(source.includes('warehouseId: id(booking?.warehouseId)'))
|
|
|
|
|
assert.ok(!source.includes('context.createdResources?.warehouse?.id'))
|
|
|
|
|
})
|