Files
pj_admin_cloud/tests/wallet-qb-statistics.test.cjs
T
dzc dec9fd96e3
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
111
2026-10-23 14:38:26 +08:00

154 lines
6.4 KiB
JavaScript

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")
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"]
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 errors = []
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 Promise.resolve({ data: { records: [], total: 100 } }) },
qbTotal: (query, signal) => new Promise((resolve, reject) => requests.push({ query, signal, resolve, reject })),
},
"/@/hooks/batchExport": { useBatchExport: () => ({}) },
"/@/components/AsyncTaskProgress.vue": {},
"/@/hooks/message": { useMessage: () => ({ error: message => errors.push(message) }) },
"/@/hooks/dict": { useDict: () => ({}) },
"/@/utils/formatMoney": {},
"/@/utils/formatTime": { formatDate: () => "2026-10" },
})
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({})
return { state, requests, lists, errors, close: () => app.unmount() }
}
const settle = () => new Promise(resolve => setImmediate(resolve))
const result = total => ({ code: 0, data: { total, eatTotal: total, payTotal: 0, topupTotal: 0 } })
test("列表首次加载、筛选和翻页均不触发全量余额统计", async () => {
const page = mount()
try {
await settle()
assert.equal(page.lists.length, 1)
await page.state.getDataList()
page.state.currentChangeHandle(2)
page.state.sizeChangeHandle(20)
await settle()
assert.equal(page.lists.length, 4)
assert.equal(page.requests.length, 0)
} finally { page.close() }
})
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)
} finally { page.close() }
})
test("关闭和重开立即取消旧请求,旧成功或失败不污染新统计与 loading", async () => {
const page = mount()
try {
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("旧请求失败"))
await settle()
assert.equal(page.state.balanceStatisticsLoading.value, true)
assert.deepEqual(page.errors, [])
page.state.drawerClose()
page.state.viewBalanceStatistics()
page.requests[2].resolve(result(3000))
await settle()
page.requests[1].resolve(result(1000))
await settle()
assert.equal(page.state.balanceStatistics.total, 3000)
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("统计 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, [])
})