import assert from 'node:assert/strict' import test from 'node:test' import { readFileSync } from 'node:fs' import ts from 'typescript' import * as vue from 'vue' function evaluate(source, dependencies = {}) { const code = ts.transpileModule(source, { compilerOptions: { module: ts.ModuleKind.CommonJS, target: ts.ScriptTarget.ES2022 } }).outputText const exports = {} new Function('require', 'exports', code)(id => { assert.ok(id in dependencies, `Unexpected dependency ${id}`) return dependencies[id] }, exports) return exports } const eligibility = evaluate(readFileSync(new URL('../utils/customsEligibility.ts', import.meta.url), 'utf8')) const customsApi = evaluate(readFileSync(new URL('../api/customs.ts', import.meta.url), 'utf8'), { '@/api/http': {}, '@/modules/first-leg/api/firstLeg': {}, }) const order = (id, status = 'LOADED', taxMode = 'TAX_REFUND') => ({ id, status, taxMode, hasCompletedLoadingPlan: ['LOADED', 'DELIVERED', 'COMPLETED'].includes(status), orderNo: `ORDER-${id}`, businessSummary: { inboundCode: `IN-${id}` } }) const detail = id => ({ status: 'COMPLETED', merchantStatus: 'CUSTOMS_COMPLETED', inbounds: [{ orderId: id, taxMode: 'TAX_REFUND' }] }) function harness(t, orders, getDetail = async id => detail(id)) { const store = { loadError: '', failPage: 0, transformPage: value => value }, calls = [], pageCalls = [] const unifiedApi = evaluate(readFileSync(new URL('../api/unifiedOrders.ts', import.meta.url), 'utf8'), { '@/api/http': { apiRequest: async ({ method, url, params: { page, size, taxMode, loaded } }) => { assert.equal(method, 'GET') assert.equal(url, '/merchant/v1/orders') pageCalls.push({ page, size, taxMode, loaded }) if (store.loadError || store.failPage === page) throw new Error(store.loadError || '第二页订单查询失败') // Model server filtering BEFORE pagination and COUNT, using the actual // request produced by the production API. Missing taxMode scans all rows. const filtered = orders.filter(row => (!taxMode || row.taxMode === taxMode) && (loaded === undefined || row.hasCompletedLoadingPlan === loaded)) return store.transformPage({ page, size, total: filtered.length, pages: Math.ceil(filtered.length / size), records: filtered.slice((page - 1) * size, page * size).map(row => ({ orderId: row.id, orderNo: row.orderNo, mainStatus: row.status, taxMode: row.taxMode, inboundCode: row.businessSummary.inboundCode })) }) } }, }) const reader = evaluate(readFileSync(new URL('../utils/customsDocumentsReader.ts', import.meta.url), 'utf8'), { './customsEligibility': eligibility, '../api/unifiedOrders': unifiedApi, '../api/customs': { getMerchantCustomsForOrder: id => { calls.push(id); return getDetail(id) }, isMerchantCustomsUnavailable: error => error?.code === 'A0404' }, }) const source = readFileSync(new URL('./CustomsDocumentsView.vue', import.meta.url), 'utf8').match(/