feat:余额区间查询
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
41d9c49508
commit
431371a13c
9 files changed
+767
-402
No files matched your search
@@ -15,7 +15,7 @@ function load(source, mocks, globals = {}) {
|
||||
return mod.exports
|
||||
}
|
||||
|
||||
for (const scene of ["cz", "jz", "qb"]) {
|
||||
for (const scene of ["cz", "jz"]) {
|
||||
test(`${scene} 页面提交对应后台任务,固定筛选并保留进度和下载流程`, async () => {
|
||||
const requests = [], progress = [], downloads = []
|
||||
const submitted = { taskId: "a".repeat(32), redisKey: `wallet:export:${scene}`, status: "PENDING" }
|
||||
@@ -48,12 +48,12 @@ for (const scene of ["cz", "jz", "qb"]) {
|
||||
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"] })
|
||||
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].url, `/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)
|
||||
@@ -66,3 +66,66 @@ for (const scene of ["cz", "jz", "qb"]) {
|
||||
assert.deepEqual(downloads, [["https://files.example.com/export.xlsx", "原导出文件.xlsx"]])
|
||||
})
|
||||
}
|
||||
|
||||
test("用户钱包汇总导出沿用已应用的区间和筛选,分页和未提交的表单不进入后台任务", async () => {
|
||||
const requests = [], progress = [], downloads = []
|
||||
const submitted = { taskId: "b".repeat(32), redisKey: "wallet:export:qb-users", status: "PENDING" }
|
||||
const request = options => {
|
||||
requests.push(options)
|
||||
return Promise.resolve(options.url.endsWith("/page-qb-users")
|
||||
? { code: 0, data: { records: [], total: 100 } } : { 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 message = { useMessage: () => ({ error: message => assert.fail(message) }) }
|
||||
const users = load(fs.readFileSync(path.join(root, "views/wallet/wallet-qb/useWalletQbUsers.ts"), "utf8"), {
|
||||
vue, "/@/api/wallet/wallet-manage": api, "/@/hooks/message": message,
|
||||
"/@/utils/formatTime": { formatDate: () => "2026-11" },
|
||||
})
|
||||
const batch = load(fs.readFileSync(path.join(root, "hooks/batchExport.ts"), "utf8"), {
|
||||
vue, "/@/components/AsyncTaskProgress.vue": {}, "/@/hooks/message": message,
|
||||
"/@/utils/exportDownload": { downloadExportFile: (...args) => downloads.push(args) },
|
||||
})
|
||||
const descriptor = parse(fs.readFileSync(path.join(root, "views/wallet/wallet-qb/index.vue"), "utf8")).descriptor
|
||||
const page = load(compileScript(descriptor, { id: "qb-users-export" }).content, {
|
||||
vue, "./useWalletQbUsers": users, "/@/api/wallet/wallet-manage": api,
|
||||
"/@/hooks/batchExport": batch, "/@/components/AsyncTaskProgress.vue": {},
|
||||
"/@/hooks/message": message, "/@/hooks/dict": { useDict: () => ({}) },
|
||||
"/@/utils/formatMoney": {}, "/@/utils/formatTime": { formatDate: () => "2026-11" },
|
||||
}, { ref: vue.ref, reactive: vue.reactive, computed: vue.computed })
|
||||
const renderer = vue.createRenderer({
|
||||
createElement: () => ({}), createText: () => ({}), createComment: () => ({}),
|
||||
setText() {}, setElementText() {}, patchProp() {}, insert() {}, remove() {}, parentNode: () => null, nextSibling: () => null,
|
||||
})
|
||||
let state
|
||||
const app = renderer.createApp({ setup() { state = page.default.setup({}, { expose() {} }); return () => null } })
|
||||
app.mount({})
|
||||
try {
|
||||
await new Promise(resolve => setImmediate(resolve))
|
||||
state.exportProgressRef.value = { startSubmitting: name => progress.push(name), start: value => progress.push(value), submissionFailed: message => assert.fail(message) }
|
||||
Object.assign(state.state.queryForm, { userId: "123", deptIds: ["456"], walletTypeIdList: ["789"], isInclude: false,
|
||||
minBalanceYuan: "1000.01", maxBalanceYuan: "2000" })
|
||||
await state.getDataList()
|
||||
const expected = state.getAppliedQuery()
|
||||
state.currentChangeHandle(8)
|
||||
await new Promise(resolve => setImmediate(resolve))
|
||||
Object.assign(state.state.queryForm, { minBalanceYuan: "0", walletRecordMonth: "2026-10" })
|
||||
state.state.queryForm.deptIds.push("999")
|
||||
await state.exportExcel()
|
||||
const exported = requests.filter(request => request.url.endsWith("/export-qb-users-async"))
|
||||
assert.equal(exported.length, 1)
|
||||
assert.equal(exported[0].method, "post")
|
||||
assert.deepEqual(exported[0].data, expected)
|
||||
assert.equal(exported[0].data.minBalance, 100001)
|
||||
assert.equal(exported[0].data.maxBalance, 200000)
|
||||
assert.equal(exported[0].data.current, undefined)
|
||||
assert.equal(exported[0].data.size, undefined)
|
||||
assert.equal(state.exportTaskConfig.progressUrl, "/wallet/async-task/progress")
|
||||
assert.equal(state.exportTaskConfig.redisKey, submitted.redisKey)
|
||||
assert.deepEqual(progress[1], submitted)
|
||||
state.handleExportSuccess({ ...submitted, status: "SUCCESS", resultFileUrl: "https://files.example.com/users.xlsx", resultFileName: "用户钱包余额.xlsx" })
|
||||
assert.deepEqual(downloads, [["https://files.example.com/users.xlsx", "用户钱包余额.xlsx"]])
|
||||
} finally { app.unmount() }
|
||||
})
|
||||
+148
-114
@@ -8,179 +8,213 @@ const { parse, compileScript, compileTemplate } = require("@vue/compiler-sfc")
|
||||
|
||||
const root = path.join(__dirname, "../src")
|
||||
const filename = path.join(root, "views/wallet/wallet-qb/index.vue")
|
||||
const descriptor = parse(fs.readFileSync(filename, "utf8"), { filename }).descriptor
|
||||
const source = compileScript(descriptor, { id: "wallet-qb-statistics-test" }).content
|
||||
|
||||
function load(source, mocks) {
|
||||
const compiled = ts.transpileModule(source, {
|
||||
compilerOptions: { module: ts.ModuleKind.CommonJS, target: ts.ScriptTarget.ES2020, esModuleInterop: true },
|
||||
}).outputText
|
||||
const mod = { exports: {} }
|
||||
const autoImports = ["ref", "reactive", "onMounted"]
|
||||
const autoImports = ["ref", "reactive", "computed", "watch", "onMounted", "onBeforeUnmount"]
|
||||
new Function("module", "exports", "require", ...autoImports, compiled)(
|
||||
mod, mod.exports, id => id in mocks ? mocks[id] : require(id), ...autoImports.map(key => vue[key]),
|
||||
)
|
||||
return mod.exports
|
||||
}
|
||||
|
||||
function mount() {
|
||||
const requests = []
|
||||
const lists = []
|
||||
const listRequests = []
|
||||
const errors = []
|
||||
function mount({ deferredLists = false } = {}) {
|
||||
const lists = [], statistics = [], errors = []
|
||||
const request = options => {
|
||||
if (options.url.endsWith("/page-qb-users")) {
|
||||
if (deferredLists) return new Promise((resolve, reject) => lists.push({ ...options, resolve, reject }))
|
||||
lists.push(options)
|
||||
return Promise.resolve({ code: 0, data: { records: [], total: 100 } })
|
||||
}
|
||||
assert.equal(options.url, "/wallet/wallet-manage/qb-users-total")
|
||||
return new Promise((resolve, reject) => statistics.push({ ...options, resolve, reject }))
|
||||
}
|
||||
const api = load(fs.readFileSync(path.join(root, "api/wallet/wallet-manage.ts"), "utf8"), {
|
||||
"/@/utils/request": options => { listRequests.push(options); return Promise.resolve({ data: { records: [], total: 100 } }) },
|
||||
"/@/api/asyncTask": {},
|
||||
"/@/utils/request": request, "/@/api/asyncTask": {},
|
||||
})
|
||||
const table = load(fs.readFileSync(path.join(root, "hooks/table.ts"), "utf8"), {
|
||||
"element-plus": { ElMessage: { error: message => errors.push(message) } },
|
||||
"/@/utils/other": {}, "../utils/formatTime": {},
|
||||
})
|
||||
const page = load(source, {
|
||||
"/@/hooks/table": table,
|
||||
"/@/api/wallet/wallet-manage": {
|
||||
fetchListJoinQb: query => { lists.push(query); return api.fetchListJoinQb(query) },
|
||||
qbTotal: (query, signal) => new Promise((resolve, reject) => requests.push({ query, signal, resolve, reject })),
|
||||
},
|
||||
"/@/hooks/batchExport": { useBatchExport: () => ({}) },
|
||||
"/@/components/AsyncTaskProgress.vue": {},
|
||||
const hook = load(fs.readFileSync(path.join(root, "views/wallet/wallet-qb/useWalletQbUsers.ts"), "utf8"), {
|
||||
vue, "/@/api/wallet/wallet-manage": api,
|
||||
"/@/hooks/message": { useMessage: () => ({ error: message => errors.push(message) }) },
|
||||
"/@/hooks/dict": { useDict: () => ({}) },
|
||||
"/@/utils/formatMoney": {},
|
||||
"/@/utils/formatTime": { formatDate: () => "2026-10" },
|
||||
"/@/utils/formatTime": { formatDate: () => "2026-11" },
|
||||
})
|
||||
const renderer = vue.createRenderer({
|
||||
createElement: () => ({}), createText: () => ({}), createComment: () => ({}),
|
||||
setText() {}, setElementText() {}, patchProp() {}, insert() {}, remove() {}, parentNode: () => null, nextSibling: () => null,
|
||||
})
|
||||
let state
|
||||
const app = renderer.createApp({
|
||||
setup() { state = page.default.setup({}, { expose() {} }); return () => null },
|
||||
})
|
||||
const app = renderer.createApp({ setup() { state = hook.useWalletQbUsers(); return () => null } })
|
||||
app.mount({})
|
||||
return { state, requests, lists, listRequests, errors, close: () => app.unmount() }
|
||||
return { state, lists, statistics, errors, close: () => app.unmount() }
|
||||
}
|
||||
|
||||
const settle = () => new Promise(resolve => setImmediate(resolve))
|
||||
const result = total => ({ code: 0, data: { total, eatTotal: total, payTotal: 0, topupTotal: 0 } })
|
||||
const result = total => ({ code: 0, data: { total, eatTotal: total, payTotal: 0, topupTotal: 0, userCount: 4, walletCount: 7 } })
|
||||
|
||||
test("余额排序经真实表格 hook 和 API 传至后端,切换回首页、翻页保留筛选且取消后恢复默认", async () => {
|
||||
const page = mount()
|
||||
try {
|
||||
await settle()
|
||||
Object.assign(page.state.state.queryForm, { deptIds: ["11"], walletTypeIdList: ["21"], isInclude: false })
|
||||
page.state.currentChangeHandle(3)
|
||||
await settle()
|
||||
await page.state.handleBalanceSortChange({ prop: "balance", order: "ascending" })
|
||||
const ascending = page.listRequests.at(-1)
|
||||
assert.equal(ascending.url, "/wallet/wallet-manage/page-join-qb")
|
||||
assert.equal(ascending.method, "post")
|
||||
assert.deepEqual(ascending.params, { current: 1, size: 10, ascs: "balance", descs: undefined })
|
||||
assert.equal(ascending.data.walletRecordMonth, "2026-10")
|
||||
assert.deepEqual(ascending.data.deptIds, ["11"])
|
||||
assert.deepEqual(ascending.data.walletTypeIdList, ["21"])
|
||||
assert.equal(ascending.data.isInclude, false)
|
||||
page.state.currentChangeHandle(2)
|
||||
await settle()
|
||||
assert.deepEqual(page.listRequests.at(-1).params, { current: 2, size: 10, ascs: "balance", descs: undefined })
|
||||
await page.state.handleBalanceSortChange({ prop: "balance", order: "descending" })
|
||||
await page.state.handleBalanceSortChange({ prop: "balance", order: "descending" })
|
||||
assert.deepEqual(page.listRequests.at(-1).params, { current: 1, size: 10, ascs: undefined, descs: "balance" })
|
||||
await page.state.handleBalanceSortChange({ order: null })
|
||||
assert.deepEqual(page.listRequests.at(-1).params, { current: 1, size: 10, ascs: undefined, descs: undefined })
|
||||
assert.equal(page.requests.length, 0)
|
||||
} finally { page.close() }
|
||||
test("用户汇总 API 使用新路径并传递分页、排序和取消信号,旧接口继续兼容", async () => {
|
||||
const requests = []
|
||||
const api = load(fs.readFileSync(path.join(root, "api/wallet/wallet-manage.ts"), "utf8"), {
|
||||
"/@/utils/request": options => { requests.push(options); return Promise.resolve({}) }, "/@/api/asyncTask": {},
|
||||
})
|
||||
const controller = new AbortController()
|
||||
const query = { current: 2, size: 20, ascs: "eat_balance", descs: "", walletRecordMonth: "2026-11", minBalance: 0 }
|
||||
await api.fetchQbUsers(query, controller.signal)
|
||||
assert.equal(requests[0].url, "/wallet/wallet-manage/page-qb-users")
|
||||
assert.equal(requests[0].method, "post")
|
||||
assert.deepEqual(requests[0].params, { current: 2, size: 20, ascs: "eat_balance", descs: undefined })
|
||||
assert.equal(requests[0].data, query)
|
||||
assert.equal(requests[0].signal, controller.signal)
|
||||
await api.qbUsersTotal(query, controller.signal)
|
||||
assert.equal(requests[1].url, "/wallet/wallet-manage/qb-users-total")
|
||||
assert.equal(requests[1].method, "post")
|
||||
assert.equal(requests[1].signal, controller.signal)
|
||||
await api.qbTotal(query, controller.signal)
|
||||
await api.fetchListJoinQb(query)
|
||||
assert.equal(requests[2].url, "/wallet/wallet-manage/qb-total")
|
||||
assert.equal(requests[3].url, "/wallet/wallet-manage/page-join-qb")
|
||||
})
|
||||
|
||||
test("列表首次加载、筛选和翻页均不触发全量余额统计", async () => {
|
||||
test("首次加载和翻页仅查询用户汇总列表,统计由用户单独触发", async () => {
|
||||
const page = mount()
|
||||
try {
|
||||
await settle()
|
||||
assert.equal(page.lists.length, 1)
|
||||
await page.state.getDataList()
|
||||
page.state.currentChangeHandle(2)
|
||||
await settle()
|
||||
page.state.sizeChangeHandle(20)
|
||||
await settle()
|
||||
assert.equal(page.lists.length, 4)
|
||||
assert.equal(page.requests.length, 0)
|
||||
assert.equal(page.lists.length, 3)
|
||||
assert.equal(page.statistics.length, 0)
|
||||
} finally { page.close() }
|
||||
})
|
||||
|
||||
test("统计请求在途去重,数组筛选冻结且加载完成前不展示旧统计", async () => {
|
||||
test("合计余额区间以元输入精确转成分,包含零、负数及单边条件", async () => {
|
||||
const page = mount()
|
||||
try {
|
||||
Object.assign(page.state.state.queryForm, { deptIds: ["11"], walletTypeIdList: ["9007199254740993999"], isInclude: false })
|
||||
page.state.viewBalanceStatistics()
|
||||
page.state.viewBalanceStatistics()
|
||||
assert.equal(page.requests.length, 1)
|
||||
assert.equal(page.state.balanceStatisticsLoading.value, true)
|
||||
assert.equal(page.state.balanceStatisticsLoaded.value, false)
|
||||
page.state.state.queryForm.deptIds.push("12")
|
||||
assert.deepEqual(page.requests[0].query, {
|
||||
walletRecordMonth: "2026-10", deptIds: ["11"], walletTypeIdList: ["9007199254740993999"], isInclude: false,
|
||||
})
|
||||
page.requests[0].resolve(result(1200))
|
||||
await settle()
|
||||
assert.equal(page.state.balanceStatistics.total, 1200)
|
||||
assert.equal(page.state.balanceStatisticsLoaded.value, true)
|
||||
assert.equal(page.state.balanceStatisticsLoading.value, false)
|
||||
for (const [minimum, maximum, expectedMin, expectedMax] of [
|
||||
["1000.10", "2000.99", 100010, 200099], ["-5.01", "0", -501, 0],
|
||||
["90071992547409.01", "90071992547409.91", 9007199254740901, 9007199254740991],
|
||||
["0", "", 0, undefined], ["", "2000", undefined, 200000], ["", "", undefined, undefined],
|
||||
]) {
|
||||
Object.assign(page.state.state.queryForm, { minBalanceYuan: minimum, maxBalanceYuan: maximum })
|
||||
await page.state.getDataList()
|
||||
assert.equal(page.lists.at(-1).data.minBalance, expectedMin)
|
||||
assert.equal(page.lists.at(-1).data.maxBalance, expectedMax)
|
||||
assert.equal(page.state.rangeError.value, "")
|
||||
}
|
||||
} finally { page.close() }
|
||||
})
|
||||
|
||||
test("关闭和重开立即取消旧请求,旧成功或失败不污染新统计与 loading", async () => {
|
||||
test("反向区间、非法金额及超出分精度的输入拦截请求并保留已应用条件", async () => {
|
||||
const page = mount()
|
||||
try {
|
||||
await settle()
|
||||
const original = page.state.getAppliedQuery()
|
||||
for (const [minimum, maximum] of [["2000", "1000"], ["abc", ""], ["1.001", ""], ["9007199254740992", ""]]) {
|
||||
const before = page.lists.length
|
||||
Object.assign(page.state.state.queryForm, { minBalanceYuan: minimum, maxBalanceYuan: maximum })
|
||||
await page.state.getDataList()
|
||||
assert.equal(page.lists.length, before)
|
||||
assert.ok(page.state.rangeError.value)
|
||||
assert.deepEqual(page.state.getAppliedQuery(), original)
|
||||
}
|
||||
} finally { page.close() }
|
||||
})
|
||||
|
||||
test("翻页、分项排序和统计沿用已应用快照,未提交的表单修改不会改变查询范围", async () => {
|
||||
const page = mount()
|
||||
try {
|
||||
await settle()
|
||||
Object.assign(page.state.state.queryForm, { deptIds: ["11"], walletTypeIdList: ["21"], isInclude: false, minBalanceYuan: "1000", maxBalanceYuan: "2000" })
|
||||
await page.state.getDataList()
|
||||
const applied = page.state.getAppliedQuery()
|
||||
page.state.state.queryForm.deptIds.push("12")
|
||||
Object.assign(page.state.state.queryForm, { walletRecordMonth: "2026-10", minBalanceYuan: "0" })
|
||||
page.state.currentChangeHandle(3)
|
||||
await settle()
|
||||
assert.equal(page.lists.at(-1).params.current, 3)
|
||||
assert.deepEqual(page.lists.at(-1).data.deptIds, ["11"])
|
||||
assert.equal(page.lists.at(-1).data.minBalance, 100000)
|
||||
for (const [prop, order, ascending, descending] of [
|
||||
["eatBalance", "ascending", "eat_balance", undefined], ["payBalance", "descending", undefined, "pay_balance"],
|
||||
["topupBalance", "ascending", "topup_balance", undefined], ["balance", "descending", undefined, "balance"],
|
||||
]) {
|
||||
await page.state.handleBalanceSortChange({ prop, order })
|
||||
assert.equal(page.lists.at(-1).params.current, 1)
|
||||
assert.equal(page.lists.at(-1).params.ascs, ascending)
|
||||
assert.equal(page.lists.at(-1).params.descs, descending)
|
||||
}
|
||||
await page.state.handleBalanceSortChange({ order: null })
|
||||
assert.equal(page.lists.at(-1).params.ascs, undefined)
|
||||
assert.equal(page.lists.at(-1).params.descs, undefined)
|
||||
page.state.viewBalanceStatistics()
|
||||
page.state.drawerClose()
|
||||
assert.equal(page.requests[0].signal.aborted, true)
|
||||
page.state.state.queryForm.walletRecordMonth = "2026-09"
|
||||
page.state.viewBalanceStatistics()
|
||||
page.requests[0].reject(new Error("旧请求失败"))
|
||||
assert.equal(page.statistics.length, 1)
|
||||
const { ascs, descs, ...expectedStatisticsQuery } = applied
|
||||
assert.deepEqual(page.statistics[0].data, expectedStatisticsQuery)
|
||||
const snapshot = page.state.getAppliedQuery()
|
||||
snapshot.deptIds.push("99")
|
||||
assert.deepEqual(page.state.getAppliedQuery().deptIds, ["11"])
|
||||
} finally { page.close() }
|
||||
})
|
||||
|
||||
test("新筛选取消旧统计,迟到的成功和失败均不覆盖新结果,空数据可明确统计为零", async () => {
|
||||
const page = mount()
|
||||
try {
|
||||
await settle()
|
||||
page.state.viewBalanceStatistics()
|
||||
Object.assign(page.state.state.queryForm, { minBalanceYuan: "1000" })
|
||||
await page.state.getDataList()
|
||||
assert.equal(page.statistics[0].signal.aborted, true)
|
||||
assert.equal(page.state.balanceStatisticsLoaded.value, false)
|
||||
page.state.viewBalanceStatistics()
|
||||
page.statistics[0].reject(new Error("旧请求失败"))
|
||||
await settle()
|
||||
assert.equal(page.state.balanceStatisticsLoading.value, true)
|
||||
assert.deepEqual(page.errors, [])
|
||||
page.state.drawerClose()
|
||||
page.state.clearStatistics()
|
||||
page.state.viewBalanceStatistics()
|
||||
page.requests[2].resolve(result(3000))
|
||||
page.statistics[2].resolve(result(0))
|
||||
await settle()
|
||||
page.requests[1].resolve(result(1000))
|
||||
page.statistics[1].resolve(result(1000))
|
||||
await settle()
|
||||
assert.equal(page.state.balanceStatistics.total, 3000)
|
||||
assert.equal(page.state.balanceStatistics.total, 0)
|
||||
assert.equal(page.state.balanceStatisticsLoaded.value, true)
|
||||
assert.equal(page.state.balanceStatisticsLoading.value, false)
|
||||
} finally { page.close() }
|
||||
})
|
||||
|
||||
test("网络失败展示可读错误并可重试,卸载取消在途请求", async () => {
|
||||
const page = mount()
|
||||
page.state.viewBalanceStatistics()
|
||||
page.requests[0].reject(new Error("查询超时"))
|
||||
await settle()
|
||||
assert.deepEqual(page.errors, ["查询超时"])
|
||||
assert.equal(page.state.balanceStatisticsLoaded.value, false)
|
||||
assert.equal(page.state.balanceStatisticsLoading.value, false)
|
||||
page.state.viewBalanceStatistics()
|
||||
assert.equal(page.requests.length, 2)
|
||||
page.close()
|
||||
assert.equal(page.requests[1].signal.aborted, true)
|
||||
page.requests[1].resolve(result(2000))
|
||||
await settle()
|
||||
assert.equal(page.state.balanceStatisticsLoaded.value, false)
|
||||
test("统计失败可以重试,卸载取消统计和列表,过期列表不会覆盖新页", async () => {
|
||||
const page = mount({ deferredLists: true })
|
||||
try {
|
||||
await settle()
|
||||
Object.assign(page.state.state.queryForm, { minBalanceYuan: "1000" })
|
||||
const newest = page.state.getDataList()
|
||||
assert.equal(page.lists[0].signal.aborted, true)
|
||||
page.lists[1].resolve({ code: 0, data: { records: [{ userId: "new" }], total: 1 } })
|
||||
await newest
|
||||
page.lists[0].resolve({ code: 0, data: { records: [{ userId: "old" }], total: 100 } })
|
||||
await settle()
|
||||
assert.equal(page.state.state.dataList[0].userId, "new")
|
||||
page.state.viewBalanceStatistics()
|
||||
page.statistics[0].reject(new Error("查询超时"))
|
||||
await settle()
|
||||
assert.equal(page.state.balanceStatisticsLoaded.value, false)
|
||||
assert.equal(page.state.balanceStatisticsLoading.value, false)
|
||||
assert.equal(page.state.balanceStatisticsError.value, "查询超时")
|
||||
page.state.viewBalanceStatistics()
|
||||
page.state.currentChangeHandle(2)
|
||||
page.close()
|
||||
assert.equal(page.statistics[1].signal.aborted, true)
|
||||
assert.equal(page.lists[2].signal.aborted, true)
|
||||
} finally { /* 此测试在验证卸载时已经关闭组件。 */ }
|
||||
})
|
||||
|
||||
test("统计 API 保留路径与 POST 参数并传递取消信号,实际 Vue 模板可编译", async () => {
|
||||
const requests = []
|
||||
const api = load(fs.readFileSync(path.join(root, "api/wallet/wallet-manage.ts"), "utf8"), {
|
||||
"/@/utils/request": options => { requests.push(options); return Promise.resolve({}) },
|
||||
"/@/api/asyncTask": {},
|
||||
})
|
||||
const controller = new AbortController()
|
||||
const query = { walletRecordMonth: "2026-10", deptIds: ["11"] }
|
||||
await api.qbTotal(query, controller.signal)
|
||||
assert.equal(requests[0].url, "/wallet/wallet-manage/qb-total")
|
||||
assert.equal(requests[0].method, "post")
|
||||
assert.equal(requests[0].data, query)
|
||||
assert.equal(requests[0].signal, controller.signal)
|
||||
const script = compileScript(descriptor, { id: "wallet-qb-statistics-test" })
|
||||
assert.deepEqual(compileTemplate({ source: descriptor.template.content, filename, id: "wallet-qb-statistics-test", compilerOptions: { bindingMetadata: script.bindings } }).errors, [])
|
||||
test("真实页面的查询、统计和用户汇总表格模板可编译", () => {
|
||||
const descriptor = parse(fs.readFileSync(filename, "utf8"), { filename }).descriptor
|
||||
const script = compileScript(descriptor, { id: "wallet-qb-users-test" })
|
||||
assert.deepEqual(compileTemplate({ source: descriptor.template.content, filename, id: "wallet-qb-users-test", compilerOptions: { bindingMetadata: script.bindings } }).errors, [])
|
||||
})
|
||||
Reference in new issue
Block a user