Files
admin-web/src/modules/finance/pages/FinancePresentation.test.ts
T

180 lines
11 KiB
TypeScript
Raw Normal View History

2026-08-11 19:35:28 +08:00
import { readFileSync } from 'node:fs'
import { resolve } from 'node:path'
import { describe, expect, it } from 'vitest'
const settlement = readFileSync(resolve(process.cwd(), 'src/modules/finance/pages/FinanceFormalSettlementPage.vue'), 'utf8')
2026-08-13 12:22:41 +08:00
const financeRoutes = readFileSync(resolve(process.cwd(), 'src/modules/finance/routes.ts'), 'utf8')
2026-08-14 12:50:42 +08:00
const accounts = readFileSync(resolve(process.cwd(), 'src/modules/finance/pages/FinanceCustomerAccountsView.vue'), 'utf8')
2026-08-11 19:59:15 +08:00
const statements = readFileSync(resolve(process.cwd(), 'src/modules/finance/pages/FinanceCustomerStatementsView.vue'), 'utf8')
2026-08-11 19:35:28 +08:00
const arap = readFileSync(resolve(process.cwd(), 'src/modules/finance/pages/FinanceCustomerArapView.vue'), 'utf8')
describe('finance presentation governance', () => {
it('shows customer names instead of internal customer IDs in formal settlements', () => {
2026-08-13 12:22:41 +08:00
expect(settlement).toContain('customerName(detail.value.customerId, detail.value.customerName)')
expect(settlement).toContain('detailPartyName()')
2026-08-11 19:35:28 +08:00
expect(settlement).toContain('activeCustomers.value.map')
expect(settlement).not.toContain('{{ selected.customerId }}')
})
2026-08-13 12:22:41 +08:00
it('uses prototype-defined standalone settlement details and modal partial payments', () => {
expect(financeRoutes).toContain("finance/settlement-receivables/:settlementId")
expect(financeRoutes).toContain("finance/settlement-payables/:settlementId")
2026-08-19 10:00:50 +08:00
expect(financeRoutes).toContain("finance/receivable-statistics")
expect(financeRoutes).toContain("platform:finance:receivable-statistics:list")
2026-08-13 12:22:41 +08:00
expect(financeRoutes).toContain('showPageHeading: false')
2026-08-17 12:31:27 +08:00
expect(settlement).toContain('class="settlement-detail-page surface-panel"')
2026-08-13 12:22:41 +08:00
expect(settlement).toContain('返回列表')
expect(settlement).not.toContain('AppDrawer')
expect(settlement).toContain('登记后剩余余额')
expect(settlement).toContain('remainingAfter(receiptForm.amount)')
expect(settlement).toContain('remainingAfter(paymentForm.amount)')
})
2026-08-17 12:31:27 +08:00
it('uses one continuous desktop detail surface with balanced summary and scroll-safe tables', () => {
expect(settlement).toContain('<DetailPageLayout v-else-if="detailMode" class="settlement-detail-page surface-panel"')
expect(settlement).toContain('class="settlement-detail-content"')
2026-08-19 09:14:35 +08:00
expect(settlement).toContain('.settlement-detail-header { display: flex; min-height: 68px;')
2026-08-17 16:45:46 +08:00
expect(settlement).toContain('align-items: center;')
expect(settlement).toContain('justify-content: space-between')
2026-08-17 12:31:27 +08:00
expect(settlement).toContain('<el-descriptions :column="4" class="settlement-detail-info">')
for (const title of ['基本信息', '费用明细', '修订记录']) expect(settlement).toContain(`title="${title}"`)
expect(settlement).toContain(':title="kind === \'receivable\' ? \'收款记录\' : \'付款记录\'"')
expect(settlement.match(/class="detail-table-scroll"/g)).toHaveLength(3)
expect(settlement).toContain('grid-template-columns: repeat(4, minmax(0, 1fr))')
expect(settlement).toContain(':deep(.detail-table-scroll .el-table) { min-width: 920px; }')
expect(settlement).not.toContain('class="detail-section surface-panel"')
expect(settlement.match(/width="min\(760px, 94vw\)"/g)).toHaveLength(2)
expect(settlement.match(/class="settlement-operation-form"/g)).toHaveLength(2)
expect(settlement).toContain('grid-template-columns: repeat(5, minmax(0, 1fr))')
2026-08-17 16:45:46 +08:00
expect(settlement).toContain('grid-template-columns: repeat(2, minmax(0, 1fr));')
expect(settlement).toContain('column-gap: 14px;')
2026-08-17 12:31:27 +08:00
})
2026-08-19 09:14:35 +08:00
it('keeps settlement totals and list actions in the table toolbar', () => {
expect(settlement).toContain('<template #toolbar-start>')
2026-08-17 13:24:55 +08:00
expect(settlement).toContain('class="settlement-summary" aria-label="结算汇总"')
2026-08-19 09:14:35 +08:00
expect(settlement).toContain('<template #toolbar-actions>')
2026-08-17 13:24:55 +08:00
expect(settlement).toContain('class="settlement-list-actions"')
expect(settlement).toContain('.settlement-summary .summary-item + .summary-item')
2026-08-19 09:14:35 +08:00
expect(settlement).not.toContain('class="settlement-list-toolbar"')
2026-08-17 13:24:55 +08:00
})
it('keeps settlement details focused on finance-facing labels and fields', () => {
expect(settlement).toContain('financeSourceTypeLabel(scope.row.sourceType)')
expect(settlement).toContain('financeOperationActionLabel(scope.row.action)')
expect(settlement).toContain('displayDateTime(scope.row.occurredAt)')
expect(settlement).not.toContain('label="来源版本"')
})
2026-08-12 17:29:35 +08:00
it('uses optional all-customer filters without a customer-selection blocker', () => {
2026-08-26 14:33:13 +08:00
for (const source of [settlement]) {
2026-08-12 17:29:35 +08:00
expect(source).toContain("placeholder: '全部客户'")
expect(source).not.toContain('全客户查询暂不可用')
expect(source).not.toContain('empty-text="请选择客户查询')
}
2026-08-25 22:08:59 +08:00
expect(arap).toContain("placeholder: '请选择客户'")
expect(arap).not.toContain("placeholder: '全部客户'")
2026-08-26 14:33:13 +08:00
expect(statements).toContain("placeholder: '请选择客户'")
2026-08-27 21:48:15 +08:00
expect(statements).toContain("placeholder: '请选择对账单状态'")
expect(statements).toContain(':search-on-clear="false"')
2026-08-26 14:33:13 +08:00
expect(statements).toContain("placeholder: '请选择结清状态'")
expect(statements).toContain("startPlaceholder: '请选择开始日期'")
expect(statements).toContain("endPlaceholder: '请选择结束日期'")
expect(statements).not.toContain("placeholder: '全部客户'")
2026-08-27 21:48:15 +08:00
expect(settlement).toContain(':search-on-clear="false"')
2026-08-12 17:29:35 +08:00
})
2026-08-14 12:50:42 +08:00
it('uses active-customer name selectors across all formal finance pages', () => {
for (const source of [accounts, arap, statements, settlement]) {
expect(source).toContain("type: 'select'")
expect(source).toContain("label: '客户名称'")
expect(source).toContain('label: item.tenantName')
expect(source).not.toContain('tenantCode} · ${item.tenantName')
}
expect(accounts).not.toContain("key: 'keyword', type: 'input'")
})
2026-08-25 22:08:59 +08:00
it('keeps customer arap selector text within a stable dropdown layout', () => {
expect(arap).toContain("class: 'finance-customer-select'")
expect(arap).toContain("popperClass: 'finance-customer-arap-popper'")
expect(arap).toContain('teleported: false')
expect(arap).toContain('onVisibleChange: onCustomerSelectVisible')
expect(arap).toContain("document.addEventListener('scroll', closeCustomerSelectOnScroll, true)")
expect(arap).toContain('.finance-customer-arap-popper .el-select-dropdown__item')
expect(arap).toContain('text-overflow: ellipsis;')
})
it('keeps the customer arap table body independently scrollable', () => {
expect(arap).toContain('max-height="calc(100vh - 300px)"')
})
2026-08-11 19:35:28 +08:00
it('translates source codes and provides reason placeholders', () => {
2026-08-15 09:47:23 +08:00
expect(arap).toContain('sourceTypeDisplay(detail.sourceType)')
2026-08-11 19:35:28 +08:00
expect(arap).toContain('financeOperationActionLabel(log.action)')
expect(arap).toContain('financeOperationResultLabel(log.result)')
2026-08-11 19:59:15 +08:00
expect(arap).toContain('financeDirectionLabel(row.direction)')
expect(arap).toContain('financeDirectionLabel(detail.direction)')
expect(arap).not.toContain("detail.direction === 'RECEIVABLE' ? '应收' : '应付'")
2026-08-11 19:35:28 +08:00
expect(arap).toContain('请填写驳回原因')
2026-08-19 09:14:35 +08:00
expect(arap).toContain('请填写操作原因')
2026-08-11 19:35:28 +08:00
})
2026-08-11 19:59:15 +08:00
2026-08-12 09:25:55 +08:00
it('exposes frozen G3 controls without unavailable placeholders', () => {
2026-08-11 19:59:15 +08:00
expect(settlement).not.toContain('生成{{ title }}')
expect(settlement).not.toContain('接口尚未提供,暂不可操作')
2026-08-12 09:25:55 +08:00
expect(statements).toContain('生成对账单')
expect(statements).toContain('createReconciliationStatement')
expect(statements).toContain('actionReconciliationStatement')
expect(statements).toContain('<template #toolbar-actions>')
expect(statements).toContain('aria-label="更多对账单操作"')
expect(statements).toContain('adjustmentLines: selected.map')
2026-08-11 19:59:15 +08:00
expect(statements).not.toContain('disabled title="接口尚未提供')
})
2026-08-12 19:04:48 +08:00
it('uses bordered striped tables for statement business details', () => {
expect(statements).toContain(':data="detail.lines" size="small" border stripe')
expect(statements).toContain(':data="detail.revisions" size="small" border stripe')
expect(statements).toContain(':data="adjustLines" size="small" max-height="420" border stripe')
})
2026-08-17 13:24:55 +08:00
2026-08-17 16:45:46 +08:00
it('opens statement details on a compact dedicated route instead of below the list', () => {
expect(statements).toContain('v-else-if="isDetailRoute" class="surface-panel statement-detail-page"')
2026-08-17 13:24:55 +08:00
expect(statements).toContain('@row-click="openDetail"')
2026-08-17 16:45:46 +08:00
expect(statements).toContain("name: 'finance-customer-statement-detail'")
expect(statements).toContain('.statement-detail-page :deep(.detail-page-layout) { gap: 0; }')
expect(statements).toContain('返回客户对账单')
expect(statements).not.toContain('aria-label="所选对账单联动明细"')
2026-08-17 13:24:55 +08:00
expect(statements).not.toContain('核对账期、金额和结清状态后查看下方业务明细。')
expect(statements).not.toContain('展示当前对账单版本中的业务与计费明细。')
expect(statements).not.toContain('只读展示当前对账单关联的有效收款记录。')
})
it('uses a compact financial summary row for customer accounts', () => {
2026-08-17 16:45:46 +08:00
expect(accounts).toContain('.finance-account-detail__layout :deep(.detail-page-layout)')
expect(accounts).toContain('gap: 0;')
expect(accounts).toContain('.account-metric + .account-metric')
expect(accounts).toContain('border-left: 1px solid')
expect(accounts).toContain('.account-metric::before')
expect(accounts).toContain('display: none;')
expect(accounts).toContain(':deep(.ledger-query.query-toolbar)')
expect(accounts).toContain('padding: 0;')
expect(accounts).toContain('border: 0;')
expect(accounts).toContain('background: transparent;')
2026-08-17 13:24:55 +08:00
expect(accounts).not.toContain('展示应收、应付及每次变动后的未收金额。')
expect(accounts).not.toContain('到期日按账单日期加客户账期计算;每个客户独立设置,默认 30 天。')
})
it('keeps fee-source details continuous without nested metric and section cards', () => {
2026-08-17 16:45:46 +08:00
expect(arap).toContain('.finance-arap-detail__layout :deep(.detail-page-layout)')
expect(arap).toContain('.arap-metric + .arap-metric')
expect(arap).toContain('border-left: 1px solid')
expect(arap).toContain('.arap-settlement {')
expect(arap).toContain('padding-left: 16px;')
expect(arap).toContain('border-left: 1px solid')
2026-08-17 13:24:55 +08:00
expect(arap).not.toContain('.arap-metric.is-amount { border-color:')
expect(arap).not.toContain('description="费用来源与关联业务摘要"')
2026-08-19 09:14:35 +08:00
expect(arap).not.toContain('description="当前审核和出账状态"')
2026-08-17 13:24:55 +08:00
expect(arap).not.toContain('description="按时间查看审核与结算调整记录"')
})
2026-08-11 19:35:28 +08:00
})