import assert from 'node:assert/strict' import { readFileSync } from 'node:fs' import test from 'node:test' import ts from 'typescript' const apiSource = readFileSync(new URL('./api/deliveryOrders.ts', import.meta.url), 'utf8') const routesSource = readFileSync(new URL('./routes.ts', import.meta.url), 'utf8') const listSource = readFileSync(new URL('./views/DeliveryOrdersView.vue', import.meta.url), 'utf8') const detailSource = readFileSync(new URL('./views/DeliveryOrderDetailView.vue', import.meta.url), 'utf8') const createSource = readFileSync(new URL('./views/DeliveryOrderCreateView.vue', import.meta.url), 'utf8') const permissionSource = readFileSync(new URL('../tenant-management/contracts.ts', import.meta.url), 'utf8') async function importTypeScriptModule(source) { const compiled = ts.transpileModule(source, { compilerOptions: { module: ts.ModuleKind.ESNext, target: ts.ScriptTarget.ES2022 }, }).outputText return import(`data:text/javascript;base64,${Buffer.from(compiled).toString('base64')}`) } test('uses only authenticated merchant delivery endpoints without customer scope or mock fallback', () => { assert.match(apiSource, /method: 'GET'[\s\S]*url: '\/merchant\/v1\/last-leg\/delivery-orders'/) assert.match(apiSource, /delivery-orders\/\$\{encodeURIComponent\(deliveryNo\)\}/) assert.match(apiSource, /method: 'POST'[\s\S]*url: '\/merchant\/v1\/last-leg\/delivery-orders'/) assert.match(apiSource, /const \{ dispatchNo, \.\.\.request \} = payload/) assert.match(apiSource, /params: \{ dispatchNo \}/) assert.match(apiSource, /overseasApiRequest/) assert.match(apiSource, /\.then\(\(\{ order, skus, fees \}\) => \(\{[\s\S]*\.\.\.order,[\s\S]*fees,[\s\S]*items: skus/) assert.match(apiSource, /overseasApiRequest/) assert.doesNotMatch(apiSource, /customerId|tenantId|Record|mock|fallback/i) }) test('keeps list, read-only detail and create permissions independent in active routes', () => { assert.match(routesSource, /path: 'orders\/delivery'[\s\S]*permission: 'merchant:warehouse:delivery:list'[\s\S]*navigation:/) assert.match(routesSource, /path: 'orders\/delivery\/create'[\s\S]*DeliveryOrderCreateView\.vue[\s\S]*permission: 'merchant:warehouse:delivery:create'/) assert.match(routesSource, /path: 'orders\/delivery\/:deliveryNo'[\s\S]*DeliveryOrderDetailView\.vue[\s\S]*props: true[\s\S]*permission: 'merchant:warehouse:delivery:list'/) assert.match(routesSource, /orders-delivery-create[\s\S]*keepAlive: false/) assert.match(routesSource, /orders-delivery-detail[\s\S]*keepAlive: false/) }) test('renders the operation column first and covers loading, empty, error and pagination states', () => { const operationIndex = listSource.indexOf('label="操作"') const deliveryNumberIndex = listSource.indexOf('label="派送单号"') assert.ok(operationIndex >= 0 && operationIndex < deliveryNumberIndex) assert.match(listSource, /v-loading="loading"/) assert.match(listSource, /empty-text="暂无派送单"/) assert.match(listSource, /delivery-state--error/) assert.match(listSource, /@click="loadOrders">重试/) assert.match(listSource, /listDeliveryOrders\(buildQuery\(\)\)/) assert.match(listSource, / { assert.match(listSource, /auth\.hasPermission\('merchant:warehouse:delivery:create'\)/) assert.match(listSource, / { assert.match(detailSource, /defineProps<\{ deliveryNo: string \}>/) assert.match(detailSource, /getDeliveryOrder\(props\.deliveryNo\)/) assert.match(detailSource, /派送单详情加载失败/) for (const heading of ['订单信息', '运输与预约', '货物明细', '费用明细']) assert.match(detailSource, new RegExp(heading)) assert.doesNotMatch(detailSource, /detail\?\.id|deliveryNo \|\| detail\?\.id|customerId|tenantId/) }) test('submits the complete create contract with stable retry idempotency and recoverable failures', () => { for (const model of ['dispatchNo', 'plannedDeliveryAt', 'deliveryMethod', 'pickupMethod', 'loadingType', 'waybillNo', 'carrierName', 'vehicleType', 'vehicleSize', 'driverName', 'driverPhone', 'vehiclePlate', 'appointmentAccount', 'sellerName', 'remark']) { assert.match(createSource, new RegExp(`v-model="form\\.${model}"`)) } assert.match(createSource, /if \(!pendingIdempotencyKey\) pendingIdempotencyKey = crypto\.randomUUID\(\)/) assert.match(createSource, /createDeliveryOrder\(requestPayload\(\)\)/) assert.match(createSource, /fees: form\.fees\.map/) assert.match(createSource, /if \(form\.fees\.length === 0\)/) assert.match(createSource, /请至少添加一条费用明细/) for (const value of ['FBA_PICKUP', 'CUSTOMER_PICKUP', 'TRUCK_PALLET', 'TRUCK_FLOOR', 'EXPRESS', 'OUTSOURCED', 'DEDICATED_TRUCK', 'LTL']) { assert.match(createSource, new RegExp(`value="${value}"`)) } for (const value of ['ONE_PICKUP_ONE_DROP', 'ONE_PICKUP_MULTI_DROP', 'MULTI_PICKUP_ONE_DROP', 'MULTI_PICKUP_MULTI_DROP', 'WAREHOUSE_PICKUP', 'PALLET', 'FLOOR', 'MIXED']) { assert.match(createSource, new RegExp(`value="${value}"`)) } assert.doesNotMatch(createSource, /value="(?:TRUCK|COURIER|SELF_PICKUP|DOOR_PICKUP|LOOSE_CARTON)"/) assert.match(createSource, /submitError\.value = error instanceof Error/) assert.match(createSource, /useUnsavedWorkRegistration/) assert.doesNotMatch(createSource, /customerId|tenantId|mock|fallback/i) }) test('maps both merchant delivery permissions independently', async () => { assert.match(permissionSource, /'merchant:warehouse:delivery:list': \['merchant:warehouse:delivery:list'\]/) assert.match(permissionSource, /'merchant:warehouse:delivery:create': \['merchant:warehouse:delivery:create'\]/) const contracts = await importTypeScriptModule(permissionSource) assert.equal(contracts.hasMappedMerchantPermission('merchant:warehouse:delivery:list', new Set(['merchant:warehouse:delivery:list'])), true) assert.equal(contracts.hasMappedMerchantPermission('merchant:warehouse:delivery:list', new Set(['merchant:warehouse:delivery:create'])), false) assert.equal(contracts.hasMappedMerchantPermission('merchant:warehouse:delivery:create', new Set(['merchant:warehouse:delivery:create'])), true) assert.equal(contracts.hasMappedMerchantPermission('merchant:warehouse:delivery:create', new Set(['merchant:warehouse:delivery:list'])), false) })