import assert from 'node:assert/strict' import { readFileSync } from 'node:fs' import test from 'node:test' import { runInNewContext } from 'node:vm' import ts from 'typescript' const storeSource = readFileSync(new URL('./firstLegOrders.ts', import.meta.url), 'utf8') const apiSource = readFileSync(new URL('../api/firstLeg.ts', import.meta.url), 'utf8') const unifiedApiSource = readFileSync(new URL('../api/unifiedOrders.ts', import.meta.url), 'utf8') test('saves optional express tracking, trims it, and omits it for other pickup methods', () => { const functions = storeSource.slice(storeSource.indexOf('function apiTransport('), storeSource.indexOf('function prepareDraftForSave(')) const javascript = ts.transpileModule(functions, { compilerOptions: { target: ts.ScriptTarget.ES2022 } }).outputText const save = runInNewContext(`${javascript}; savePayload`) const draft = { pickupMethod: 'SELF_EXPRESS', trackingNumber: ' SF123456789 ', destinationCountryCode: 'US', destinationType: 'OVERSEAS', items: [] } const warehouse = { id: '1', name: '收货仓' } assert.equal(save(draft, warehouse, '客户').expressTrackingNo, 'SF123456789') for (const trackingNumber of ['', ' ']) { assert.equal(save({ ...draft, trackingNumber }, warehouse, '客户').expressTrackingNo, undefined) } for (const pickupMethod of ['SELF_TRUCK', 'PICKUP']) { assert.equal(save({ ...draft, pickupMethod }, warehouse, '客户').expressTrackingNo, undefined) } }) test('detail fetches authoritative progress on direct entry and refresh, and clears stale progress on failure', async () => { const functionSource = storeSource.slice(storeSource.indexOf(' async function loadDetail('), storeSource.indexOf(' async function loadWarehouseDetail(')) const progressSource = readFileSync(new URL('../utils/orderProgress.ts', import.meta.url), 'utf8') const validationSource = progressSource.slice(progressSource.indexOf('export function requireOrderProgress(')).replace('export ', '') const javascript = ts.transpileModule(`${validationSource}\n${functionSource}`, { compilerOptions: { target: ts.ScriptTarget.ES2022 } }).outputText const id = '2110663764278312961' const orderProgress = { value: {} } let calls = 0 let response = { progress: { orderId: id, stage: 'scheduled', partial: true } } const loadDetail = runInNewContext(`${javascript}; loadDetail`, { orderProgress, warehouses: { value: [] }, getMerchantUnifiedOrder: async requested => { assert.equal(requested, id); calls++; return response }, mapUnifiedOrderDetail: detail => ({ id, detail }), upsertOrder: order => order, }) await loadDetail(id) assert.equal(orderProgress.value[id].stage, 'scheduled') assert.equal(orderProgress.value[id].partial, true) response = { progress: { orderId: id, stage: 'delivering', partial: false } } await loadDetail(id) assert.equal(calls, 2) assert.equal(orderProgress.value[id].stage, 'delivering') response = { progress: { orderId: 'another-order', stage: 'delivered', partial: false } } await assert.rejects(loadDetail(id), /订单履约进度不完整/) assert.equal(orderProgress.value[id], undefined) }) test('renders estimated sailing from the current API without substituting actual departure', () => { const mapper = storeSource.slice(storeSource.indexOf('function businessSummary('), storeSource.indexOf('\nconst unifiedActionLabels')) const javascript = ts.transpileModule(mapper, { compilerOptions: { target: ts.ScriptTarget.ES2022 } }).outputText const map = runInNewContext(`${javascript}; businessSummary`) const transport = { vesselName: 'REASSIGNED', voyageNo: 'V02', estimatedSailingAt: '2026-10-07T08:00:00', actualSailingAt: '2026-10-08T09:00:00', effectiveSailingAt: '2026-10-08T09:00:00', effectiveSailingAtEstimated: false, estimatedPortArrivalAt: '2026-10-27T08:00:00', actualPortArrivalAt: null, } const mapped = map({ transport }) assert.equal(mapped.estimatedSailingAt, transport.estimatedSailingAt) assert.equal(mapped.estimatedPortArrivalAt, transport.estimatedPortArrivalAt) assert.equal(mapped.vesselName, 'REASSIGNED') assert.equal(mapped.voyageNo, 'V02') assert.equal(map().estimatedSailingAt, '') assert.equal(map({ transport: null }).estimatedPortArrivalAt, '') }) test('maps the current workbench row without loading detail rows', () => { assert.match(storeSource, /result\.page\.records\.map\(item => mapUnifiedOrderRow\(item, warehouses\.value\)\)/) assert.match(storeSource, /version: summary\.orderVersion/) assert.doesNotMatch(storeSource, /function mapFirstLegOrderRow/) }) test('declares the documented merchant warehouse and first-leg endpoints', () => { assert.match(apiSource, /url: '\/merchant\/v1\/warehouses'/) assert.match(apiSource, /url: '\/merchant\/v1\/orders\/first-leg'/) assert.match(apiSource, /url: '\/merchant\/v1\/orders\/first-leg\/inbound-code-policy'/) assert.match(apiSource, /url: '\/merchant\/v1\/orders\/first-leg\/batch'/) assert.match(apiSource, /url: '\/merchant\/v1\/orders\/first-leg\/addresses'/) assert.match(apiSource, /`\/merchant\/v1\/orders\/first-leg\/addresses\/\$\{id\}`/) assert.doesNotMatch(apiSource, /merchant\/v1\/order-addresses/) assert.match(apiSource, /url: '\/merchant\/v1\/orders\/first-leg\/batch-imports\/template'/) assert.match(apiSource, /url: '\/merchant\/v1\/orders\/first-leg\/batch-imports'/) assert.match(apiSource, /`\/merchant\/v1\/files\/order-batch-imports\/\$\{encodeURIComponent\(batchNo\)\}\/error-reports\/\$\{encodeURIComponent\(String\(fileId\)\)\}`/) assert.match(apiSource, /params: \{ mode \}/) assert.match(apiSource, /data\.append\('file', file\)/) assert.match(apiSource, /`\/merchant\/v1\/orders\/first-leg\/\$\{id\}`/) assert.match(apiSource, /`\/merchant\/v1\/orders\/first-leg\/\$\{id\}\/submit`/) assert.match(apiSource, /`\/merchant\/v1\/warehouses\/\$\{id\}`/) assert.match(apiSource, /url: '\/merchant\/v1\/first-leg\/pricing\/channels'/) assert.match(apiSource, /params: \{ originWarehouseId \}/) assert.match(apiSource, /url: '\/merchant\/v1\/first-leg\/pricing\/estimate'/) assert.match(apiSource, /`\/merchant\/v1\/first-leg\/inbounds\/\$\{encodeURIComponent\(String\(inboundId\)\)\}\/carton-label-pdf`/) assert.match(apiSource, /`\/merchant\/v1\/first-leg\/orders\/\$\{encodeURIComponent\(String\(orderId\)\)\}\/carton-label-pdf`/) assert.match(apiSource, /url: '\/merchant\/v1\/first-leg\/orders\/carton-label-pdf'/) assert.match(apiSource, /data: orderIds\.map\(String\)/) assert.doesNotMatch(apiSource, /`\/merchant\/v1\/inbounds\/\$\{encodeURIComponent\(String\(inboundId\)\)\}\/carton-label-pdf`/) assert.match(apiSource, /signature === '%PDF-'/) assert.match(apiSource, /throw new ApiError\('箱唛服务未返回有效的 PDF 文件', 'INVALID_PDF'\)/) }) test('maps transport and status fields instead of treating container mode as transport mode', () => { assert.match(storeSource, /order\.transportMode === 'SEA'.*order\.containerMode === 'FULL_CONTAINER' \? 'FCL' : 'LCL'/s) assert.match(storeSource, /order\.id \?\? order\.orderId \?\? ''/) assert.match(storeSource, /order\.transportMode \? clientTransport\(order\) : null/) assert.match(storeSource, /draft\.transportMode === 'ROAD'\) return 'TRUCK'/) assert.match(storeSource, /status === 'SUBMITTED'\) return 'PENDING_REVIEW'/) assert.match(storeSource, /status === 'REJECTED'\) return 'PENDING_REVIEW'/) assert.match(storeSource, /status === 'APPROVED' \|\| status === 'ACCEPTED' \|\| status === 'PROCESSING'\) return 'WAIT_MEASURE'/) assert.match(storeSource, /status === 'COMPLETED'\) return 'COMPLETED'/) assert.doesNotMatch(storeSource, /status === 'COMPLETED'\) return 'DELIVERED'/) }) test('uses only the formal workbench read and surfaces failures', () => { assert.match(storeSource, /getMerchantOrderWorkbench\(query\)/) assert.match(storeSource, /orders\.value = \[\]/) assert.doesNotMatch(storeSource, /isUnifiedOrderQueryUnavailable|getOrdersForClient|getMerchantFirstLegOrders|initialOrders/) }) test('declares the final C02 row and detail contract in the API adapter', () => { assert.match(unifiedApiSource, /const unifiedOrderBaseUrl = '\/merchant\/v1\/orders'/) assert.doesNotMatch(unifiedApiSource, /orders\/unified/) assert.match(unifiedApiSource, /orderId: number \| string/) assert.match(unifiedApiSource, /mainStatus: ApiUnifiedOrderMainStatus/) assert.match(unifiedApiSource, /nextAction: string \| null/) assert.match(unifiedApiSource, /fulfillmentType\?: 'STANDARD' \| 'ONE_CLICK_DROPSHIP' \| null/) assert.match(unifiedApiSource, /lxCode\?: string \| null/) assert.match(unifiedApiSource, /customerRemark: string \| null/) for (const field of ['pickupMethod', 'requestedPickupAt', 'containerMode', 'destinationType', 'destinationCode', 'skuNos', 'totalQuantity', 'totalNetWeightKg', 'chargeableVolumeCbm', 'inboundCompletedAt', 'shipmentId', 'referenceId']) { assert.match(unifiedApiSource, new RegExp(`${field}:`)) } assert.match(unifiedApiSource, /taxMode: ApiTaxMode \| null/) assert.match(unifiedApiSource, /customsInspection: boolean \| null/) assert.match(unifiedApiSource, /loadingVersion: number/) assert.match(unifiedApiSource, /pickingVersion: number/) assert.match(unifiedApiSource, /summary: MerchantUnifiedOrderRow/) assert.match(unifiedApiSource, /order: MerchantFirstLegOrderDetail/) assert.match(unifiedApiSource, /timeline: MerchantUnifiedTimelineEvent\[\]/) assert.match(unifiedApiSource, /customNodes\?: MerchantUnifiedCustomNode\[\]/) }) test('keeps unified order pagination valid when the store omits page and size', () => { assert.match(unifiedApiSource, /const \{ page, size, \.\.\.filters \} = params/) assert.match(unifiedApiSource, /params: \{ page: page \?\? 1, size: size \?\? 200, \.\.\.filters \}/) }) test('draft editing reads the order aggregate while navigation uses unified detail', () => { assert.match(storeSource, /return loadOrderAggregate\(id\)/) assert.match(storeSource, /const detail = await getMerchantUnifiedOrder\(id\)/) assert.doesNotMatch(storeSource, /loadLegacyDetail|draftOnly|includeDrafts/) }) test('maps C02 authoritative status, transport, cargo and pickup snapshots', () => { assert.match(storeSource, /id: String\(summary\.orderId\)/) assert.match(storeSource, /transportMode: unifiedTransport\(summary\.containerMode\)/) assert.match(storeSource, /status: summary\.mainStatus/) assert.match(storeSource, /taxMode: summary\.taxMode \?\? 'BUY_DECLARATION'/) assert.match(storeSource, /customsInspection: summary\.customsInspection \?\? false/) assert.match(storeSource, /fulfillmentType: summary\.fulfillmentType \?\? 'STANDARD'/) assert.match(storeSource, /lxCode: summary\.lxCode \?\? ''/) assert.match(storeSource, /mapped\.fulfillmentType = detail\.summary\.fulfillmentType \?\? mapped\.fulfillmentType/) assert.match(storeSource, /mapped\.lxCode = detail\.summary\.lxCode \?\? mapped\.lxCode/) assert.match(storeSource, /requestedPickupAt: summary\.requestedPickupAt \?\? ''/) assert.match(storeSource, /chargeableVolumeCbm: summary\.chargeableVolumeCbm \?\? null/) assert.match(storeSource, /inboundedAt: summary\.inboundCompletedAt \?\? ''/) assert.match(storeSource, /pickupMethod: summary\.pickupMethod \?\? 'SELF_EXPRESS'/) assert.match(storeSource, /destinationType: summary\.destinationType \?\? 'PRIVATE'/) assert.match(storeSource, /mapped\.requestedPickupAt = summary\.requestedPickupAt/) assert.match(storeSource, /summary\?\.loading\?\.loadingVersion/) assert.match(storeSource, /summary\?\.loading\?\.pickingVersion/) assert.match(storeSource, /summary\?\.inboundId == null \? '' : String\(summary\.inboundId\)/) assert.match(storeSource, /customerRemark: summary\.customerRemark \?\? ''/) assert.match(storeSource, /PALLETIZE_DROPSHIP: '一件代发组托'/) }) test('sends a manually entered old-system inbound code with the draft payload', () => { assert.match(storeSource, /inboundCode: draft\.inboundCode\?\.trim\(\) \|\| undefined/) }) test('sends backend-required channel, pricing, customs, destination and cargo fields', () => { for (const field of ['pickupMethod', 'channelCode', 'channelName', 'pricingTaxMode', 'taxMode', 'customsInspection', 'destinationType', 'packageType']) { assert.match(storeSource, new RegExp(field)) } assert.match(storeSource, /containerMode: draft\.transportMode === 'FCL' \? 'FULL_CONTAINER'/) assert.doesNotMatch(storeSource, /customerId: draft\.shipperPartyId/) assert.doesNotMatch(apiSource, /interface FirstLegOrderSaveRequest \{[^}]*customerId\??:/s) assert.match(storeSource, /customerName: customerName\.trim\(\)/) assert.match(storeSource, /destinationWarehouseId: draft\.destinationType === 'PRIVATE' \? undefined : draft\.destinationWarehouseId/) assert.match(storeSource, /senderAddressId: draft\.pickupMethod === 'PICKUP' \? draft\.senderAddressId : undefined/) assert.match(storeSource, /privateDestinationAddressId: draft\.destinationType === 'PRIVATE' \? draft\.privateDestinationAddressId : undefined/) assert.doesNotMatch(storeSource, /sender: partyPayload|receiver: partyPayload/) for (const field of [ 'customsHsCode', 'lengthCm', 'widthCm', 'heightCm', 'unitsPerPackage', 'totalQuantity', 'netWeightKg', 'unitDeclaredValue', 'material', 'usage', 'model', 'brand', 'productLengthCm', 'productWidthCm', 'productHeightCm', 'shipmentId', 'referenceId', 'productImageFileId', 'woodenProduct', ]) { assert.match(storeSource, new RegExp(`${field}: item\\.`)) } assert.match(apiSource, /POST[^\n]*product-images|method: 'POST', url: '\/merchant\/v1\/files\/product-images'/) assert.match(apiSource, /GET[^\n]*product-images|method: 'GET', url: `\/merchant\/v1\/files\/product-images\/\$\{fileId\}`/) }) test('separates domestic receiving warehouses from public destinations', () => { assert.match(apiSource, /warehouseType\?: MerchantWarehouseType/) assert.match(apiSource, /params: \{ page: 1, size: 200, status: 'ACTIVE', \.\.\.params \}/) assert.match(storeSource, /loadAllWarehouseRecords\(warehouseType, getMerchantWarehouses\)/) assert.match(storeSource, /loadWarehouseType\('DOMESTIC'\)/) assert.match(storeSource, /warehouse\.warehouseType !== 'DOMESTIC'/) assert.match(storeSource, /item\.warehouseType === draft\.destinationType/) assert.match(storeSource, /draft\.amazonWarehouseCode = draft\.destinationType === 'FBA' \? destinationWarehouse\.code : ''/) }) test('only blocks submission when a known company audit status is not active', () => { assert.match(storeSource, /companyAuditStatus\?: MerchantTenantStatus/) assert.match(storeSource, /if \(companyAuditStatus && companyAuditStatus !== 'ACTIVE'\)/) }) test('uses the versioned merchant cancellation contract', () => { assert.match(storeSource, /cancelMerchantFirstLegOrder\(id, payload, createIdempotencyKey\(/) assert.match(apiSource, /cancelMerchantFirstLegOrder\(id: number \| string, payload: \{ expectedVersion: number; reason: string \}, idempotencyKey: string\)/) }) test('sends an idempotency key for create and submit writes', () => { assert.match(apiSource, /'Idempotency-Key': createIdempotencyKey\('first-leg-create'\)/) assert.match(apiSource, /submitMerchantFirstLegOrder\(id: number \| string, payload: \{ expectedVersion: number \}, idempotencyKey: string\)/) assert.match(apiSource, /'Idempotency-Key': idempotencyKey/) assert.match(apiSource, /createMerchantFirstLegOrderBatch\(items: MerchantBatchDraftItem\[\], idempotencyKey: string\)/) assert.match(apiSource, /headers: \{ 'Idempotency-Key': idempotencyKey \}/) assert.match(storeSource, /createMerchantFirstLegOrderBatch\(items, idempotencyKey\)/) assert.doesNotMatch(storeSource, /pendingSubmissions|pendingEdits|pendingCancellation/) assert.match(storeSource, /submitMerchantFirstLegOrder\(id, \{ expectedVersion: order\.version \}, createIdempotencyKey\(/) }) test('does not expose the contradictory backend rejected state in the client model', () => { assert.match(storeSource, /status === 'REJECTED'\) return 'PENDING_REVIEW'/) assert.match(storeSource, /item\.toStatus === 'REJECTED' \? '订单信息已补充'/) }) test('maps the final backend timeline and keeps missing custom nodes empty', () => { assert.match(storeSource, /\(detail\.timeline \?\? \[\]\)\.flatMap/) assert.match(storeSource, /item\.mainStatus/) assert.match(storeSource, /\(detail\.customNodes \?\? \[\]\)/) assert.match(storeSource, /\.filter\(\(item\) => item\.customerVisible\)/) assert.match(storeSource, /kind: 'CUSTOM_NODE'/) assert.match(storeSource, /status: null/) assert.match(storeSource, /\.sort\(\(left, right\)/) }) test('keeps unified detail mapping recoverable for historical partial responses', () => { assert.match(storeSource, /\(detail\.parties \?\? \[\]\)\.find/) assert.match(storeSource, /\(detail\.statusHistory \?\? \[\]\)\.map/) assert.match(storeSource, /item\.attachmentIds\?\.length \?\? 0/) assert.match(storeSource, /if \(!detail\?\.summary \|\| !detail\.order\?\.order\) throw new Error\('订单详情数据不完整,请刷新列表后重试'\)/) }) test('maps customer-visible carrier and order lifecycle snapshots into detail', () => { assert.match(apiSource, /export interface MerchantFirstLegOrder[\s\S]*carrierId\?: number \| string \| null/) assert.match(storeSource, /carrierName: order\.carrierName \?\? ''/) assert.match(storeSource, /receivingTime: order\.receivingTime \?\? ''/) assert.match(storeSource, /submittedAt: order\.submittedAt \?\? ''/) assert.match(storeSource, /completedAt: order\.completedAt \?\? ''/) }) test('maps backend warehouse snapshots and fulfillment courier fields', () => { assert.match(storeSource, /order\.receivingWarehouseAddress/) assert.match(storeSource, /order\.expressCompany \?\? ''/) assert.match(storeSource, /order\.expressTrackingNo \?\? ''/) assert.match(storeSource, /getMerchantWarehouseDetail\(id\)/) assert.match(storeSource, /receivingCapability\.cutoffTime/) }) test('keeps failed order loads distinct from empty results', () => { assert.match(storeSource, /const loadError = ref\(''\)/) assert.match(storeSource, /orderResult\.reason instanceof Error/) assert.match(storeSource, /warehouseLoadError/) assert.match(storeSource, /return \{ orders, orderDetails, total, queueCounts, orderProgress, queryChannelNames, warehouses, loading, loadedFromApi, loadError, warehouseLoadError/) })