87 lines
5.0 KiB
JavaScript
87 lines
5.0 KiB
JavaScript
import test from 'node:test'
|
|
import assert from 'node:assert/strict'
|
|
import { readFile } from 'node:fs/promises'
|
|
import { fileURLToPath } from 'node:url'
|
|
import { parseArguments } from '../admin-test-env-acceptance.mjs'
|
|
|
|
const source = await readFile(fileURLToPath(new URL('./phase5-overseas-fulfillment.mjs', import.meta.url)), 'utf8')
|
|
const entry = await readFile(fileURLToPath(new URL('../admin-test-env-acceptance.mjs', import.meta.url)), 'utf8')
|
|
|
|
test('phase-five fulfillment is a registered default HTTP module after the real phase-four dispatch fixture', () => {
|
|
assert.match(entry, /CONFIGURED_MODULES[^\n]*'phase4-overseas-dispatch', 'phase5-overseas-fulfillment'/)
|
|
assert.match(entry, /'phase5-overseas-fulfillment', \['phase4-overseas-dispatch'\]/)
|
|
const modules = parseArguments(['--modules', 'phase5-overseas-fulfillment']).modules
|
|
for (const prerequisite of ['merchant-qualification-fixture', 'phase3-loading', 'phase3-loading-finalize',
|
|
'phase4-overseas-pda', 'phase4-overseas-pda-operations', 'phase4-overseas-dispatch']) {
|
|
assert.ok(modules.indexOf(prerequisite) >= 0
|
|
&& modules.indexOf(prerequisite) < modules.indexOf('phase5-overseas-fulfillment'), prerequisite)
|
|
}
|
|
})
|
|
|
|
test('phase-five module covers dispatch edit, transfer, PDA pick/depart and delivery state', () => {
|
|
for (const token of [
|
|
"const DISPATCH_BASE = '/api/platform/v1/last-leg/dispatches'",
|
|
"const PDA_DISPATCH_BASE = '/api/pda/v1/last-leg/dispatches'",
|
|
'query(MERCHANT_DELIVERY_BASE, { dispatchNo })', '/items/${encodeURIComponent(id(item.dispatchItemId))}/pick',
|
|
'/complete`', '/depart`', '/outbound-orders/${encodeURIComponent(outboundNo)}',
|
|
'/delivery-orders/${encodeURIComponent(deliveryNo)}/status',
|
|
]) assert.ok(source.includes(token), token)
|
|
assert.match(source, /WAIT_OUTBOUND/)
|
|
assert.match(source, /WAIT_DELIVERY/)
|
|
assert.match(source, /READY_TO_DEPART/)
|
|
assert.match(source, /OUTBOUNDED/)
|
|
assert.match(source, /DELIVERING/)
|
|
assert.match(source, /expectedVersion: deliveryVersion/)
|
|
assert.match(source, /status: 'DELIVERED', expectedVersion: completeVersion/)
|
|
})
|
|
|
|
test('phase-five module proves the client delivery create, list and nested detail contract', () => {
|
|
assert.match(source, /const MERCHANT_DELIVERY_BASE = '\/api\/merchant\/v1\/last-leg\/delivery-orders'/)
|
|
assert.match(source, /loginMerchant\(context, customerId\)/)
|
|
assert.match(source, /context\.options\?\.merchantUsername/)
|
|
assert.match(source, /\/api\/merchant\/v1\/iam\/tenant\/profile/)
|
|
assert.match(source, /id\(profile\?\.id\) === customerId/)
|
|
assert.match(source, /客户创建派送并原子转出库单/)
|
|
assert.match(source, /deliveryMethod: 'TRUCK_PALLET'/)
|
|
assert.match(source, /fees: \[\{ feeType: 'DELIVERY_FEE', feeName: '派送费', direction: 'RECEIVABLE',\s*currency: 'USD', amount: 10/)
|
|
assert.match(source, /客户分页回查自身派送单/)
|
|
assert.match(source, /客户读取自身派送详情/)
|
|
assert.match(source, /merchantDetail\.data\?\.order\?\.deliveryNo/)
|
|
assert.match(source, /merchantDetail\.data\?\.skus/)
|
|
assert.match(source, /merchantDetail\.data\?\.fees/)
|
|
assert.match(source, /merchantDetail\.data\?\.operations/)
|
|
})
|
|
|
|
test('phase-five module proves completion, customer visit, manual exception and delivery return', () => {
|
|
for (const token of [
|
|
'/delivery-orders/${encodeURIComponent(deliveryNo)}/complete',
|
|
'/customer-visits/${encodeURIComponent(visitId)}',
|
|
"visitResult: 'SATISFIED'", '/exception-orders',
|
|
'/return-inbound-options', '/mark-return', "returnDirection: 'OVERSEAS_WAREHOUSE'",
|
|
'returnSources', 'outboundPalletItemId', 'inventoryPositionId',
|
|
'value.returnSources.some', 'returnInbound?.deliveryNo === deliveryNo',
|
|
"idempotencyKey: key(context, 'DELIVERY-RETURN')", '派送退回同键同载荷重放',
|
|
'RETURN_PENDING_WITH_COMPLETED_VISIT',
|
|
]) assert.ok(source.includes(token), token)
|
|
assert.match(source, /manualExceptionNo/)
|
|
assert.match(source, /returnExceptionNo/)
|
|
})
|
|
|
|
test('phase-five module uses marker-owned fixtures and always disables its temporary PDA identity', () => {
|
|
assert.match(source, /dispatch\?\.marker !== context\.marker/)
|
|
assert.match(source, /receiving\?\.marker !== context\.marker/)
|
|
assert.match(source, /resolvePickerAccess\(context\)/)
|
|
assert.match(source, /createPicker\(context, 5, warehouseId, access\)/)
|
|
assert.match(source, /finally \{[\s\S]*disablePicker\(context, picker, 5\)[\s\S]*picker\.token = null/)
|
|
assert.doesNotMatch(source, /8\.163\.|password\s*:\s*['"`]/)
|
|
})
|
|
|
|
test('phase-five writes carry idempotency and record deployment blockers instead of passing empty fixtures', () => {
|
|
assert.match(source, /idempotencyKey: key\(context, 'TRANSFER'\)/)
|
|
assert.match(source, /idempotencyKey: key\(context, 'DISPATCH-PICK'/)
|
|
assert.match(source, /idempotencyKey: key\(context, 'DISPATCH-COMPLETE'\)/)
|
|
assert.match(source, /idempotencyKey: key\(context, 'DISPATCH-DEPART'\)/)
|
|
assert.match(source, /addCoverageGap\(MODULE, SCENARIO/)
|
|
assert.match(source, /deploymentBlocker: true/)
|
|
})
|