111
build / task (16.x, npm, macOS-latest) (push) Canceled after 0s
build / task (16.x, npm, ubuntu-latest) (push) Canceled after 0s
build / task (16.x, npm, windows-latest) (push) Canceled after 0s
build / task (16.x, pnpm, macOS-latest) (push) Canceled after 0s
build / task (16.x, pnpm, ubuntu-latest) (push) Canceled after 0s
build / task (16.x, pnpm, windows-latest) (push) Canceled after 0s
build / task (16.x, yarn, macOS-latest) (push) Canceled after 0s
build / task (16.x, yarn, ubuntu-latest) (push) Canceled after 0s
build / task (16.x, yarn, windows-latest) (push) Canceled after 0s
build / task (18.x, npm, macOS-latest) (push) Canceled after 0s
build / task (18.x, npm, ubuntu-latest) (push) Canceled after 0s
build / task (18.x, npm, windows-latest) (push) Canceled after 0s
build / task (18.x, pnpm, macOS-latest) (push) Canceled after 0s
build / task (18.x, pnpm, ubuntu-latest) (push) Canceled after 0s
build / task (18.x, pnpm, windows-latest) (push) Canceled after 0s
build / task (18.x, yarn, macOS-latest) (push) Canceled after 0s
build / task (18.x, yarn, ubuntu-latest) (push) Canceled after 0s
build / task (18.x, yarn, windows-latest) (push) Canceled after 0s
build / task (20.x, npm, macOS-latest) (push) Canceled after 0s
build / task (20.x, npm, ubuntu-latest) (push) Canceled after 0s
build / task (20.x, npm, windows-latest) (push) Canceled after 0s
build / task (20.x, pnpm, macOS-latest) (push) Canceled after 0s
build / task (20.x, pnpm, ubuntu-latest) (push) Canceled after 0s
build / task (20.x, pnpm, windows-latest) (push) Canceled after 0s
build / task (20.x, yarn, macOS-latest) (push) Canceled after 0s
build / task (20.x, yarn, ubuntu-latest) (push) Canceled after 0s
build / task (20.x, yarn, windows-latest) (push) Canceled after 0s
build / task (16.x, npm, macOS-latest) (push) Canceled after 0s
build / task (16.x, npm, ubuntu-latest) (push) Canceled after 0s
build / task (16.x, npm, windows-latest) (push) Canceled after 0s
build / task (16.x, pnpm, macOS-latest) (push) Canceled after 0s
build / task (16.x, pnpm, ubuntu-latest) (push) Canceled after 0s
build / task (16.x, pnpm, windows-latest) (push) Canceled after 0s
build / task (16.x, yarn, macOS-latest) (push) Canceled after 0s
build / task (16.x, yarn, ubuntu-latest) (push) Canceled after 0s
build / task (16.x, yarn, windows-latest) (push) Canceled after 0s
build / task (18.x, npm, macOS-latest) (push) Canceled after 0s
build / task (18.x, npm, ubuntu-latest) (push) Canceled after 0s
build / task (18.x, npm, windows-latest) (push) Canceled after 0s
build / task (18.x, pnpm, macOS-latest) (push) Canceled after 0s
build / task (18.x, pnpm, ubuntu-latest) (push) Canceled after 0s
build / task (18.x, pnpm, windows-latest) (push) Canceled after 0s
build / task (18.x, yarn, macOS-latest) (push) Canceled after 0s
build / task (18.x, yarn, ubuntu-latest) (push) Canceled after 0s
build / task (18.x, yarn, windows-latest) (push) Canceled after 0s
build / task (20.x, npm, macOS-latest) (push) Canceled after 0s
build / task (20.x, npm, ubuntu-latest) (push) Canceled after 0s
build / task (20.x, npm, windows-latest) (push) Canceled after 0s
build / task (20.x, pnpm, macOS-latest) (push) Canceled after 0s
build / task (20.x, pnpm, ubuntu-latest) (push) Canceled after 0s
build / task (20.x, pnpm, windows-latest) (push) Canceled after 0s
build / task (20.x, yarn, macOS-latest) (push) Canceled after 0s
build / task (20.x, yarn, ubuntu-latest) (push) Canceled after 0s
build / task (20.x, yarn, windows-latest) (push) Canceled after 0s
This commit is contained in:
1 parent
cce677e3ff
commit
530cfcd939
42 files changed
+3951
-483
No files matched your search
@@ -0,0 +1,163 @@
|
||||
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 } = require("@vue/compiler-sfc")
|
||||
const root = path.join(__dirname, "../src")
|
||||
const flush = () => new Promise(setImmediate)
|
||||
const deferred = () => { let resolve, reject; const promise = new Promise((a, b) => { resolve = a; reject = b }); return { promise, resolve, reject } }
|
||||
|
||||
function load(source, mocks, globals = {}) {
|
||||
const compiled = ts.transpileModule(source, { compilerOptions: { module: ts.ModuleKind.CommonJS, target: ts.ScriptTarget.ES2021 } }).outputText
|
||||
const module = { exports: {} }
|
||||
const names = Object.keys(globals)
|
||||
new Function("module", "exports", "require", ...names, compiled)(module, module.exports, key => key in mocks ? mocks[key] : require(key), ...Object.values(globals))
|
||||
return module.exports
|
||||
}
|
||||
|
||||
function component(query) {
|
||||
let unmount
|
||||
let now = 0
|
||||
let timerId = 0
|
||||
const timers = new Map()
|
||||
const events = []
|
||||
const requests = []
|
||||
let exposed
|
||||
const source = compileScript(parse(fs.readFileSync(path.join(root, "components/AsyncTaskProgress.vue"), "utf8")).descriptor, { id: "test" }).content
|
||||
const mod = load(source, {
|
||||
vue: { ...vue, onBeforeUnmount: fn => { unmount = fn } },
|
||||
"/@/api/asyncTask": { getAsyncTaskProgress: async (url, params) => { requests.push({ url, params }); return query(requests.length) } },
|
||||
"/@/utils/exportDownload": { downloadExportFile() {} },
|
||||
"/@/hooks/message": { useMessage: () => ({ error() {} }) },
|
||||
}, {
|
||||
setTimeout: fn => { timers.set(++timerId, fn); return timerId },
|
||||
clearTimeout: id => timers.delete(id),
|
||||
Date: { now: () => now },
|
||||
})
|
||||
const state = mod.default.setup({ config: { progressUrl: "/wallet/async-task/progress", redisKey: "wallet:export:xf", pollTimeoutMs: 1000 } }, {
|
||||
expose: value => { exposed = value }, emit: (...args) => events.push(args),
|
||||
})
|
||||
return { state, exposed, events, requests, timers, unmount: () => unmount(), setNow: value => { now = value },
|
||||
async tick() { const entry = timers.entries().next().value; assert.ok(entry, "下一次轮询已安排"); timers.delete(entry[0]); entry[1](); await flush() } }
|
||||
}
|
||||
const initial = { taskId: "a".repeat(32), redisKey: "wallet:export:xf", taskName: "消费记录", status: "PENDING", total: 1, completed: 0, percentage: 0, message: "等待执行", finished: false, success: false }
|
||||
const success = { ...initial, status: "SUCCESS", completed: 1, percentage: 100, finished: true, success: true, resultFileUrl: "/admin/sys-file/oss/file?fileName=test.xlsx", resultFileName: "消费记录.xlsx" }
|
||||
|
||||
test("提交互斥且冻结嵌套筛选,列表分页不限制导出", async () => {
|
||||
const submitted = deferred()
|
||||
const calls = []
|
||||
const ui = []
|
||||
const downloads = []
|
||||
const mod = load(fs.readFileSync(path.join(root, "hooks/batchExport.ts"), "utf8"), {
|
||||
vue,
|
||||
"/@/components/AsyncTaskProgress.vue": {},
|
||||
"/@/hooks/message": { useMessage: () => ({ error: value => ui.push(value) }) },
|
||||
"/@/utils/exportDownload": { downloadExportFile: (...args) => downloads.push(args) },
|
||||
})
|
||||
const task = mod.useBatchExport({ redisKey: initial.redisKey, progressUrl: "/wallet/async-task/progress", taskName: "导出", fileName: "回退.xlsx", submitTask: async query => { calls.push(query); return submitted.promise } })
|
||||
task.exportProgressRef.value = { startSubmitting: () => ui.push("submit"), start: () => ui.push("start"), show: () => ui.push("show") }
|
||||
const query = vue.reactive({ current: 8, size: 10, userIds: ["1"], range: { from: "2026-01-01" }, descs: ["create_time"] })
|
||||
const pending = task.submitExport(query)
|
||||
await task.submitExport(query)
|
||||
query.userIds.push("2"); query.range.from = "2026-02-01"
|
||||
assert.equal(calls.length, 1)
|
||||
assert.deepEqual(calls[0], { userIds: ["1"], range: { from: "2026-01-01" }, descs: ["create_time"] })
|
||||
assert.deepEqual(ui, ["submit", "show"])
|
||||
submitted.resolve({ data: initial }); await pending
|
||||
assert.equal(task.exportSubmitting.value, true)
|
||||
task.handleExportSuccess(success)
|
||||
assert.equal(task.exportSubmitting.value, false)
|
||||
assert.deepEqual(downloads[0], [success.resultFileUrl, success.resultFileName])
|
||||
})
|
||||
|
||||
test("提交失败恢复按钮状态并展示受控错误", async () => {
|
||||
const errors = []
|
||||
const mod = load(fs.readFileSync(path.join(root, "hooks/batchExport.ts"), "utf8"), {
|
||||
vue, "/@/components/AsyncTaskProgress.vue": {},
|
||||
"/@/hooks/message": { useMessage: () => ({ error: message => errors.push(message) }) },
|
||||
"/@/utils/exportDownload": {},
|
||||
})
|
||||
const task = mod.useBatchExport({ submitTask: async () => { throw { msg: "任务繁忙" } } })
|
||||
task.exportProgressRef.value = { startSubmitting() {}, submissionFailed: message => errors.push(message) }
|
||||
await task.submitExport({})
|
||||
assert.equal(task.exportSubmitting.value, false)
|
||||
assert.deepEqual(errors, ["任务繁忙", "任务繁忙"])
|
||||
})
|
||||
|
||||
test("慢查询不重叠,成功只通知一次且停止轮询", async () => {
|
||||
const pending = deferred()
|
||||
const task = component(async count => count === 1 ? pending.promise : { data: success })
|
||||
task.exposed.startSubmitting("导出")
|
||||
assert.equal(task.state.canClose.value, false)
|
||||
task.exposed.start(initial)
|
||||
await flush()
|
||||
assert.equal(task.requests.length, 1)
|
||||
assert.equal(task.timers.size, 0)
|
||||
pending.resolve({ data: { ...initial, status: "RUNNING", total: 10, completed: 1, percentage: 10 } }); await flush()
|
||||
assert.equal(task.timers.size, 1)
|
||||
await task.tick()
|
||||
assert.equal(task.events.length, 1)
|
||||
assert.equal(task.events[0][0], "success")
|
||||
assert.equal(task.timers.size, 0)
|
||||
assert.equal(task.state.canClose.value, true)
|
||||
})
|
||||
|
||||
test("连续五次查询失败暂停,重新查询原任务后仍可下载", async () => {
|
||||
const task = component(async count => { if (count <= 5) throw { msg: "网络中断" }; return { data: success } })
|
||||
task.exposed.start(initial); await flush()
|
||||
for (let i = 0; i < 4; i++) await task.tick()
|
||||
assert.equal(task.requests.length, 5)
|
||||
assert.equal(task.state.state.polling, false)
|
||||
assert.equal(task.state.state.queryError, "网络中断")
|
||||
task.state.state.visible = false; task.exposed.show()
|
||||
assert.equal(task.state.state.visible, true)
|
||||
task.state.retry(); await flush()
|
||||
assert.equal(task.requests.length, 6)
|
||||
assert.ok(task.requests.every(item => item.params.taskId === initial.taskId))
|
||||
assert.equal(task.events[0][0], "success")
|
||||
})
|
||||
|
||||
test("卸载或新任务替换后忽略旧请求响应", async () => {
|
||||
const pending = deferred()
|
||||
const task = component(async () => pending.promise)
|
||||
task.exposed.start(initial); await flush(); task.unmount()
|
||||
pending.resolve({ data: success }); await flush()
|
||||
assert.equal(task.timers.size, 0)
|
||||
assert.equal(task.events.length, 0)
|
||||
const old = deferred()
|
||||
const replacement = component(async count => count === 1 ? old.promise : { data: { ...initial, taskId: "b".repeat(32) } })
|
||||
replacement.exposed.start(initial)
|
||||
replacement.exposed.start({ ...initial, taskId: "b".repeat(32) }); await flush()
|
||||
old.resolve({ data: success }); await flush()
|
||||
assert.equal(replacement.state.state.progress.taskId, "b".repeat(32))
|
||||
assert.equal(replacement.events.length, 0)
|
||||
})
|
||||
|
||||
test("轮询超时只暂停跟踪,后台失败才发出 failure", async () => {
|
||||
const task = component(async () => ({ data: initial }))
|
||||
task.exposed.start(initial); await flush(); task.setNow(1001)
|
||||
await task.tick()
|
||||
assert.equal(task.requests.length, 1)
|
||||
assert.match(task.state.state.queryError, /后台任务可能仍在运行/)
|
||||
assert.equal(task.events.length, 0)
|
||||
const failed = component(async () => ({ data: { ...initial, finished: true, success: false, status: "FAILED", message: "导出失败" } }))
|
||||
failed.exposed.start(initial); await flush()
|
||||
assert.equal(failed.events[0][0], "failure")
|
||||
assert.equal(failed.state.canDownload.value, false)
|
||||
})
|
||||
|
||||
test("大文件下载使用原生附件地址并适配单体路径,不创建 Blob", () => {
|
||||
const links = []
|
||||
const source = fs.readFileSync(path.join(root, "utils/exportDownload.ts"), "utf8").replaceAll("import.meta.env", '({ VITE_API_URL: "/api" })')
|
||||
const mod = load(source, { "/@/utils/other": { default: { adaptationUrl: path => path.replace("/hard/", "/admin/") } } }, {
|
||||
document: { createElement: () => { const link = { style: {}, click() {}, remove() {} }; links.push(link); return link }, body: { appendChild() {} } },
|
||||
Blob: class { constructor() { throw new Error("不能将整个大文件读入 Blob") } },
|
||||
})
|
||||
mod.downloadExportFile("/hard/file?id=large", "充值/扣款.xlsx")
|
||||
assert.equal(links[0].href, "/api/admin/file?id=large")
|
||||
assert.equal(links[0].download, "充值_扣款.xlsx")
|
||||
mod.downloadExportFile("https://files.example.com/test", "test.xlsx")
|
||||
assert.equal(links[1].href, "https://files.example.com/test")
|
||||
})
|
||||
@@ -0,0 +1,56 @@
|
||||
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")
|
||||
|
||||
// 项目尚未配置前端测试框架,使用现有 TypeScript 与 Node 测试业务状态判断。
|
||||
const source = fs.readFileSync(path.join(__dirname, "../src/views/hard/hard-third-order/order.ts"), "utf8")
|
||||
const compiled = ts.transpileModule(source, { compilerOptions: { module: ts.ModuleKind.CommonJS } }).outputText
|
||||
const loaded = { exports: {} }
|
||||
new Function("module", "exports", compiled)(loaded, loaded.exports)
|
||||
const { orderState, refundState, refundDisabledReason, remainingPrice, apiResult, refundTime } = loaded.exports
|
||||
const paid = {
|
||||
id: "90071992547409931",
|
||||
orderType: "6",
|
||||
orderStatus: "5",
|
||||
payType: "3",
|
||||
walletId: "123",
|
||||
payTime: "2026-10-21 10:00:00",
|
||||
payPrice: 1000,
|
||||
refundPrice: 0,
|
||||
}
|
||||
|
||||
test("共享退款状态码仍区分部分退款与全额退款", () => {
|
||||
const partial = { ...paid, orderStatus: "10", refundPrice: 200 }
|
||||
const full = { ...partial, refundPrice: 1000 }
|
||||
assert.equal(orderState(partial).label, "已部分退款")
|
||||
assert.equal(orderState(full).label, "已全额退款")
|
||||
assert.equal(remainingPrice(partial), 800)
|
||||
assert.equal(refundDisabledReason(partial), "")
|
||||
assert.equal(refundDisabledReason(full), "订单已全额退款")
|
||||
})
|
||||
|
||||
test("待支付订单和其他业务订单不提供钱包退款", () => {
|
||||
assert.equal(remainingPrice({ ...paid, orderStatus: "1", payTime: undefined }), 0)
|
||||
assert.equal(refundDisabledReason({ ...paid, orderStatus: "1", payTime: undefined }), "订单尚未完成支付")
|
||||
assert.equal(refundDisabledReason({ ...paid, orderType: "1" }), "仅支持第三方应用支付底单")
|
||||
assert.equal(refundDisabledReason({ ...paid, payType: "10" }), "该支付方式不支持底单钱包退款")
|
||||
})
|
||||
|
||||
test("售后申请中即使底单状态尚未同步也不能重复退款", () => {
|
||||
assert.equal(refundDisabledReason(paid, [{ id: "456", status: "10" }]), "存在处理中的退款")
|
||||
assert.equal(refundState({ ...paid, refundStatus: "10", refundPrice: 200 }).label, "退款处理中")
|
||||
})
|
||||
|
||||
test("历史售后无退款时间时使用审核时间", () => {
|
||||
assert.equal(refundTime({ status: "50", auditTime: "2026-10-21 10:02:00", createTime: "2026-10-21 10:01:00" }), "2026-10-21 10:02:00")
|
||||
assert.equal(refundTime({ status: "10", auditTime: "2026-10-21 10:02:00", createTime: "2026-10-21 10:01:00" }), "2026-10-21 10:01:00")
|
||||
})
|
||||
|
||||
test("接口 HTTP 成功与业务支付成功分别判断,坏日志不误报成功", () => {
|
||||
assert.equal(apiResult({ res: '{"code":200}' }).type, "success")
|
||||
assert.equal(apiResult({ res: '{"code":505,"message":"用户余额不足"}' }).label, "用户余额不足")
|
||||
assert.equal(apiResult({ error: "timeout", res: '{"code":200}' }).type, "danger")
|
||||
assert.equal(apiResult({ res: "invalid-json" }).label, "查看响应")
|
||||
})
|
||||
@@ -0,0 +1,68 @@
|
||||
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"]])
|
||||
})
|
||||
}
|
||||
@@ -0,0 +1,59 @@
|
||||
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
|
||||
}
|
||||
|
||||
test("电子钱包页面提交后台任务,保留筛选快照且不受当前列表页限制", async () => {
|
||||
const requests = []
|
||||
const progress = []
|
||||
const submitted = { taskId: "a".repeat(32), redisKey: "wallet:export:manage", 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 api = load(fs.readFileSync(path.join(root, "api/wallet/wallet-manage.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": {},
|
||||
})
|
||||
const descriptor = parse(fs.readFileSync(path.join(root, "views/wallet/wallet-manage/index.vue"), "utf8")).descriptor
|
||||
assert.deepEqual(compileTemplate({ source: descriptor.template.content, filename: "wallet-manage.vue", id: "wallet-manage" }).errors, [])
|
||||
const page = load(compileScript(descriptor, { id: "wallet-manage" }).content, {
|
||||
vue, "/@/api/wallet/wallet-manage": api,
|
||||
"/@/components/AsyncTaskProgress.vue": {}, "/@/hooks/batchExport": hook,
|
||||
"/@/hooks/table": { useTable: state => {
|
||||
state.pagination = { current: 3, size: 10 }
|
||||
return { getDataList() {}, tableStyle: {} }
|
||||
} },
|
||||
"/@/hooks/message": {}, "/@/hooks/dict": { useDict: () => ({}) },
|
||||
"/@/utils/formatMoney": {},
|
||||
}, { ref: vue.ref, reactive: vue.reactive, defineAsyncComponent: vue.defineAsyncComponent })
|
||||
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: 3, size: 10, userId: "123", deptIds: ["456"], walletTypeId: "789", isInclude: false, leBalance: 100 })
|
||||
const original = JSON.parse(JSON.stringify(state.state.queryForm))
|
||||
await state.exportExcel()
|
||||
assert.equal(requests.length, 1)
|
||||
assert.equal(requests[0].url, "/wallet/wallet-manage/export-async")
|
||||
assert.equal(requests[0].method, "post")
|
||||
assert.deepEqual(requests[0].data, { userId: "123", deptIds: ["456"], walletTypeId: "789", isInclude: false, leBalance: 100 })
|
||||
assert.deepEqual(JSON.parse(JSON.stringify(state.state.queryForm)), original)
|
||||
assert.equal(state.exportTaskConfig.progressUrl, "/wallet/async-task/progress")
|
||||
assert.equal(state.exportTaskConfig.redisKey, "wallet:export:manage")
|
||||
assert.deepEqual(progress, ["电子钱包导出", submitted])
|
||||
state.state.queryForm.deptIds.push("999")
|
||||
assert.deepEqual(requests[0].data.deptIds, ["456"])
|
||||
})
|
||||
Reference in new issue
Block a user