Files
client-web/src/modules/finance/views/FinanceAccountView.test.mjs
T
2026-09-19 17:30:27 +08:00

70 lines
4.7 KiB
JavaScript

import assert from 'node:assert/strict'
import { readFileSync } from 'node:fs'
import test from 'node:test'
const apiSource = readFileSync(new URL('../api/account.ts', import.meta.url), 'utf8')
const viewSource = readFileSync(new URL('./FinanceAccountView.vue', import.meta.url), 'utf8')
const routesSource = readFileSync(new URL('../routes.ts', import.meta.url), 'utf8')
const permissionsSource = readFileSync(new URL('../../tenant-management/contracts.ts', import.meta.url), 'utf8')
test('uses only authenticated client finance account endpoints without customer scope', () => {
for (const path of ['/client/finance/v1/account', '/client/finance/v1/account/ledger', '/client/finance/v1/recharge-requests']) {
assert.match(apiSource, new RegExp(path.replaceAll('/', '\\/')))
}
assert.match(apiSource, /headers: \{ 'Idempotency-Key': idempotencyKey \}/)
assert.match(apiSource, /formData\.append\('amount', amount\)/)
assert.match(apiSource, /formData\.append\('file', file, file\.name\)/)
assert.doesNotMatch(apiSource, /RechargePaymentMethod|paymentMethod|WECHAT|ALIPAY/)
assert.doesNotMatch(apiSource, /customerId|tenantId|mock|fallback/i)
})
test('activates the account route and maps read and recharge permissions independently', () => {
assert.match(routesSource, /path: 'finance\/account'[\s\S]*FinanceAccountView\.vue[\s\S]*release: 'active'[\s\S]*permission: 'merchant:finance:account:view'/)
assert.match(permissionsSource, /'merchant:finance:account:view': \['merchant:finance:account:view'\]/)
assert.match(permissionsSource, /'merchant:finance:recharge:create': \['merchant:finance:recharge:create'\]/)
assert.match(viewSource, /auth\.hasPermission\('merchant:finance:recharge:create'\)/)
assert.match(viewSource, /class="balance-title"[\s\S]*?<el-button v-if="canRecharge" size="small" type="primary"/)
assert.match(viewSource, /\.balance-summary \{[^}]*grid-template-columns: repeat\(6,/)
assert.doesNotMatch(viewSource, /class="account-actions"|class="balance-grid"/)
assert.doesNotMatch(viewSource, /class="account-heading"/)
})
test('renders server balances, ledger and recharge states without internal identifiers', () => {
for (const field of ['actualBalance', 'frozenBalance', 'availableBalance', 'creditLimit', 'creditUsed', 'availableCredit']) assert.match(viewSource, new RegExp(`account\\?\\.${field}`))
assert.match(viewSource, /实际可用资金与可用授信合计/)
assert.match(viewSource, /CREDIT_LIMIT: '授信调整'/)
assert.match(viewSource, /row-key="businessNo"/)
assert.match(viewSource, /row-key="requestNo"/)
assert.match(viewSource, /empty-text="暂无资金流水"/)
assert.match(viewSource, /empty-text="暂无充值申请"/)
assert.match(viewSource, /account-state--error/)
assert.match(viewSource, /v-loading="pageLoading"/)
assert.match(viewSource, /function formatAccountAmount[\s\S]*value == null \? '—' : formatAmount\(value\)/)
assert.match(viewSource, /formatAccountAmount\(account\?\.actualBalance\)/)
assert.match(viewSource, /<DataTable v-model:page="ledgerPage" v-model:page-size="ledgerPageSize"/)
assert.match(viewSource, /<DataTable v-model:page="rechargePage" v-model:page-size="rechargePageSize"/)
assert.match(viewSource, /const ledgerColumns: DataTableColumn\[]/)
assert.match(viewSource, /const rechargeColumns: DataTableColumn\[]/)
assert.doesNotMatch(viewSource, /label: '已用授信'|label: '可用授信'/)
assert.doesNotMatch(viewSource, /<el-table|<el-pagination/)
assert.match(apiSource, /function normalizePageResult<[\s\S]*total: Number\(result\.total\)/)
assert.match(apiSource, /page: Number\(result\.page\)/)
assert.doesNotMatch(viewSource, /requestId|ledgerId|customerId|tenantId/)
})
test('matches the frozen recharge workflow and preserves an idempotency key for failed retries', () => {
assert.match(viewSource, /title="账户充值" width="760px"/)
for (const amount of ['1000', '5000', '20000', '50000']) assert.match(viewSource, new RegExp(amount))
assert.match(viewSource, /自定义/)
assert.match(viewSource, /src="\/customer-recharge-qr\.png"/)
assert.match(viewSource, /alt="平台收款二维码"/)
assert.match(viewSource, /请扫描平台收款二维码,付款后上传截图。/)
assert.match(viewSource, /accept="\.jpg,\.jpeg,\.png,image\/jpeg,image\/png"/)
assert.match(viewSource, /if \(!pendingIdempotencyKey\)[\s\S]*globalThis\.crypto\?\.randomUUID\?\.\(\)/)
assert.match(viewSource, /pendingIdempotencyKey = ''[\s\S]*rechargeVisible\.value = false/)
assert.match(viewSource, /:disabled="!canSubmit"/)
assert.match(viewSource, /await loadAccountData\(\)/)
assert.doesNotMatch(viewSource, /payment SDK|支付成功|模拟成功/)
assert.doesNotMatch(viewSource, /微信支付|支付宝|payment-methods|paymentMethod/)
})