const { test } = require("node:test") const assert = require("node:assert/strict") const fs = require("node:fs") const path = require("node:path") const ts = require("typescript") const vue = require("vue") const { parse, compileScript, compileTemplate } = require("@vue/compiler-sfc") const root = path.join(__dirname, "../src") function load(source, mocks, globals = {}) { const compiled = ts.transpileModule(source, { compilerOptions: { module: ts.ModuleKind.CommonJS, target: ts.ScriptTarget.ES2021 } }).outputText const mod = { exports: {} } new Function("module", "exports", "require", ...Object.keys(globals), compiled)(mod, mod.exports, key => key in mocks ? mocks[key] : require(key), ...Object.values(globals)) return mod.exports } for (const scene of ["cz", "jz", "qb"]) { test(`${scene} 页面提交对应后台任务,固定筛选并保留进度和下载流程`, async () => { const requests = [], progress = [], downloads = [] const submitted = { taskId: "a".repeat(32), redisKey: `wallet:export:${scene}`, status: "PENDING" } const request = options => { requests.push(options); return Promise.resolve({ data: submitted }) } const tasks = load(fs.readFileSync(path.join(root, "api/asyncTask.ts"), "utf8"), { "/@/utils/request": { default: request } }) const apis = {} for (const api of ["wallet-manage", "wallet-transaction"]) { apis[`/@/api/wallet/${api}`] = load(fs.readFileSync(path.join(root, `api/wallet/${api}.ts`), "utf8"), { "/@/utils/request": { default: request }, "/@/api/asyncTask": tasks, }) } const hook = load(fs.readFileSync(path.join(root, "hooks/batchExport.ts"), "utf8"), { vue, "/@/components/AsyncTaskProgress.vue": {}, "/@/hooks/message": { useMessage: () => ({ error: message => assert.fail(message) }) }, "/@/utils/exportDownload": { downloadExportFile: (...args) => downloads.push(args) }, }) const descriptor = parse(fs.readFileSync(path.join(root, `views/wallet/wallet-${scene}/index.vue`), "utf8")).descriptor assert.deepEqual(compileTemplate({ source: descriptor.template.content, filename: `${scene}.vue`, id: scene }).errors, []) const page = load(compileScript(descriptor, { id: scene }).content, { ...apis, vue, dayjs: { default: require("dayjs") }, "/@/components/AsyncTaskProgress.vue": {}, "/@/hooks/batchExport": hook, "/@/hooks/table": { useTable: state => { state.pagination = { current: 8, size: 10 } return { getDataList() {}, tableStyle: {} } } }, "/@/hooks/message": {}, "/@/hooks/dict": { useDict: () => ({}) }, "/@/utils/formatMoney": {}, "/@/api/admin/dept": {}, "/@/utils/formatTime": { formatDate: () => "2026-09" }, }, { ref: vue.ref, reactive: vue.reactive, defineAsyncComponent: vue.defineAsyncComponent, useRouter: () => ({ push() {} }) }) const state = page.default.setup({}, { expose() {} }) state.exportProgressRef.value = { startSubmitting: name => progress.push(name), start: value => progress.push(value), submissionFailed: message => assert.fail(message) } Object.assign(state.state.queryForm, { current: 8, size: 10, userId: "123", deptIds: ["456"], walletTypeIdList: ["789"], isInclude: false }) if (scene !== "qb") Object.assign(state.state.queryForm, { bizType: "3", createTimeList: ["2026-09-01", "2026-09-30"], tagList: ["7"] }) const before = JSON.parse(JSON.stringify(state.state.queryForm)) const expected = { ...before }; delete expected.current; delete expected.size await state.exportExcel() assert.equal(requests.length, 1) assert.equal(requests[0].url, scene === "qb" ? "/wallet/wallet-manage/export-qb-async" : `/wallet/wallet-transaction/export-${scene}-async`) assert.equal(requests[0].method, "post") assert.deepEqual(requests[0].data, expected) assert.deepEqual(JSON.parse(JSON.stringify(state.state.queryForm)), before) assert.equal(state.exportTaskConfig.progressUrl, "/wallet/async-task/progress") assert.equal(state.exportTaskConfig.redisKey, submitted.redisKey) assert.deepEqual(progress[1], submitted) state.state.queryForm.deptIds.push("999") assert.deepEqual(requests[0].data.deptIds, ["456"]) state.handleExportSuccess({ ...submitted, status: "SUCCESS", resultFileUrl: "https://files.example.com/export.xlsx", resultFileName: "原导出文件.xlsx" }) assert.deepEqual(downloads, [["https://files.example.com/export.xlsx", "原导出文件.xlsx"]]) }) }