From 0613d1095e09f06ce2469b8faa0e57ea4c0c0adb Mon Sep 17 00:00:00 2001 From: ouyangxq <775153912@qq.com> Date: Tue, 1 Sep 2026 10:21:37 +0800 Subject: [PATCH] test(firstleg): resolve trucking fixtures from active catalogs --- .../truck-appointments-contract.test.mjs | 32 +++++++++++- .../truck-appointments.mjs | 50 ++++++++++++++----- 2 files changed, 68 insertions(+), 14 deletions(-) diff --git a/scripts/admin-test-env-modules/truck-appointments-contract.test.mjs b/scripts/admin-test-env-modules/truck-appointments-contract.test.mjs index 718d26d41..842bdbf67 100644 --- a/scripts/admin-test-env-modules/truck-appointments-contract.test.mjs +++ b/scripts/admin-test-env-modules/truck-appointments-contract.test.mjs @@ -2,7 +2,34 @@ import assert from 'node:assert/strict' import { readFileSync } from 'node:fs' import test from 'node:test' -import { inspectOceanBookingIdentity, platformWarehouseIdentity, truckAppointmentPayload } from './truck-appointments.mjs' +import { activeCustomerIdentity, inspectOceanBookingIdentity, platformWarehouseIdentity, truckAppointmentPayload } from './truck-appointments.mjs' + +test('booking prerequisite resolves an ACTIVE platform customer without fixture state', () => { + assert.deepEqual(activeCustomerIdentity({ id: '21', tenantName: '现有客户' }), + { customerId: '21', customerName: '现有客户' }) + assert.deepEqual(activeCustomerIdentity({ tenantId: 22, customerName: '备用客户' }), + { customerId: '22', customerName: '备用客户' }) + assert.equal(activeCustomerIdentity({ id: '23' }), null) + const source = readFileSync(new URL('truck-appointments.mjs', import.meta.url), 'utf8') + assert.match(source, /\/api\/platform\/v1\/iam\/tenants\?page=1&size=100&status=ACTIVE/) + assert.match(source, /fixtureCustomerId[\s\S]*\|\| candidates\[0\]/) +}) + +test('channel catalog accepts the formal array response shape', () => { + const source = readFileSync(new URL('truck-appointments.mjs', import.meta.url), 'utf8') + assert.match(source, /const channelRows = records\(data\(channelsResponse\)\); const channel = channelRows\[0\]/) + assert.doesNotMatch(source, /\(data\(channelsResponse\) \|\| \[\]\)\[0\]/) +}) + +test('ACTIVE platform warehouses are scanned through bounded complete pagination', () => { + const source = readFileSync(new URL('truck-appointments.mjs', import.meta.url), 'utf8') + assert.match(source, /for \(let page = 1; page <= 100; page\+\+\)/) + assert.match(source, /warehouse-admin\?tenantId=0&status=ACTIVE&page=\$\{page\}&size=100/) + assert.match(source, /const total = Number\(warehousePage\?\.total \?\? warehouseRows\.length\)/) + assert.match(source, /page \* 100 >= total/) + assert.match(source, /完整分页平台仓并解析有效海运渠道/) + assert.doesNotMatch(source, /193000000000200001|193000000000200002/) +}) test('platform warehouse scope is fixed to zero without requiring response tenantId', () => { assert.deepEqual(platformWarehouseIdentity({ warehouseId: '41', warehouseName: '宁波仓' }), @@ -10,7 +37,8 @@ test('platform warehouse scope is fixed to zero without requiring response tenan assert.deepEqual(platformWarehouseIdentity({ id: 42, warehouseName: '义乌仓' }), { warehouseId: '42', platformTenantId: '0' }) const source = readFileSync(new URL('truck-appointments.mjs', import.meta.url), 'utf8') - assert.doesNotMatch(source, /item\?\.tenantId|item\.tenantId/) + assert.match(source, /platformWarehouseIdentity\(item\)[\s\S]*platformTenantId: '0'/) + assert.doesNotMatch(source, /platformWarehouseIdentity\(item\)[^{]*\{[^}]*tenantId/) }) test('booking identity is marker scoped and contains no customer snapshot', () => { diff --git a/scripts/admin-test-env-modules/truck-appointments.mjs b/scripts/admin-test-env-modules/truck-appointments.mjs index 900ac23a6..526ced7fa 100644 --- a/scripts/admin-test-env-modules/truck-appointments.mjs +++ b/scripts/admin-test-env-modules/truck-appointments.mjs @@ -18,6 +18,12 @@ export function platformWarehouseIdentity(item) { return { warehouseId: id(item?.warehouseId || item?.id || item?.warehouse?.id), platformTenantId: '0' } } +export function activeCustomerIdentity(item) { + const customerId = id(item?.id || item?.tenantId) + const customerName = String(item?.tenantName || item?.customerName || item?.name || '').trim() + return customerId && customerName ? { customerId, customerName } : null +} + async function request(context, method, path, body, headers = {}) { try { const response = await fetch(`${context.options.gateway}${path}`, { @@ -67,19 +73,39 @@ async function activeSupplier(context, category, suffix) { } async function bookingMaster(context, suffix) { - const tenantId = id(context.createdResources?.merchantQualificationFixture?.tenantId) - const customerName = String(context.options?.customerName || `全量验收下单客户-${suffix}`).trim() - const warehousesResponse = await request(context, 'GET', '/api/platform/v1/warehouse-admin?tenantId=0&status=ACTIVE&page=1&size=100') - for (const item of records(data(warehousesResponse))) { - const { warehouseId } = platformWarehouseIdentity(item) - if (!warehouseId) continue - const channelsResponse = await request(context, 'GET', `${BOOKINGS}/channels?originWarehouseId=${warehouseId}`) - const channel = (data(channelsResponse) || [])[0] - if (channel?.channelCode) return { customerId: tenantId, customerName, warehouseId, - channelCode: channel.channelCode, channelName: channel.channelName } + const fixtureCustomerId = id(context.createdResources?.merchantQualificationFixture?.tenantId + || context.context?.customerId || context.customerId) + const customersResponse = await request(context, 'GET', '/api/platform/v1/iam/tenants?page=1&size=100&status=ACTIVE') + const candidates = records(data(customersResponse)) + const customer = activeCustomerIdentity(candidates.find((item) => + fixtureCustomerId && id(item?.id || item?.tenantId) === fixtureCustomerId) || candidates[0]) + if (!customer) { + context.addStep(MODULE, '通过正式平台客户查询解析 ACTIVE 订舱客户', customersResponse, false, + `preferredCustomerId=${fixtureCustomerId || 'missing'}`, OPTIONS) + return null } - context.addStep(MODULE, '解析具备有效海运渠道的平台仓库', warehousesResponse, false, - `platformTenantId=0, customerId=${tenantId || 'missing'}`, OPTIONS) + let lastWarehousesResponse = null + for (let page = 1; page <= 100; page++) { + const warehousesResponse = await request(context, 'GET', + `/api/platform/v1/warehouse-admin?tenantId=0&status=ACTIVE&page=${page}&size=100`) + lastWarehousesResponse = warehousesResponse + const warehousePage = data(warehousesResponse); const warehouseRows = records(warehousePage) + for (const item of warehouseRows) { + const { warehouseId } = platformWarehouseIdentity(item) + if (!warehouseId) continue + const channelsResponse = await request(context, 'GET', `${BOOKINGS}/channels?originWarehouseId=${warehouseId}`) + const channelRows = records(data(channelsResponse)); const channel = channelRows[0] + if (channel?.channelCode) { + context.addStep(MODULE, '完整分页平台仓并解析有效海运渠道', channelsResponse, true, + `warehousePage=${page}, warehouseRecords=${warehouseRows.length}, channelRecords=${channelRows.length}, warehouseId=${warehouseId}`, OPTIONS) + return { ...customer, warehouseId, channelCode: channel.channelCode, channelName: channel.channelName } + } + } + const total = Number(warehousePage?.total ?? warehouseRows.length) + if (warehouseRows.length === 0 || page * 100 >= total) break + } + context.addStep(MODULE, '解析具备有效海运渠道的平台仓库', lastWarehousesResponse, false, + `platformTenantId=0, customerId=${customer.customerId}`, OPTIONS) return null }