Files
X-Financial/web/tests/risk-observation-dashboard.test.mjs
caoxiaozhu 15006a05a7 feat: 数字员工财务报告体系与定时提醒及看板快照调度
- 新增数字员工财务报告生成、邮件投递与渲染调度器
- 引入员工画像扫描调度与定时提醒任务
- 完善财务看板快照、排行口径与部门人员占比计算
- 优化数字员工工作看板仪表盘与技能目录
- 增强前端总览页图表、工作台摘要与顶部导航栏交互
- 新增差旅申请规划推动提醒与报销创建会话状态管理
- 补充财务报告、看板调度、数字员工工作记录测试覆盖
2026-06-03 09:25:23 +08:00

98 lines
4.7 KiB
JavaScript

import assert from 'node:assert/strict'
import { readFileSync } from 'node:fs'
import test from 'node:test'
import { fileURLToPath } from 'node:url'
import { normalizeRiskObservationDashboard } from '../src/services/riskObservations.js'
const dashboardComponent = readFileSync(
fileURLToPath(new URL('../src/components/dashboard/RiskObservationDashboard.vue', import.meta.url)),
'utf8'
)
const overviewViewModel = readFileSync(
fileURLToPath(new URL('../src/composables/useOverviewView.js', import.meta.url)),
'utf8'
)
const overviewTemplate = readFileSync(
fileURLToPath(new URL('../src/views/OverviewView.vue', import.meta.url)),
'utf8'
)
test('risk dashboard normalizes amount, distributions, and ranking fields', () => {
const dashboard = normalizeRiskObservationDashboard({
total_observations: 5,
risk_clue_count: 2,
feedback_sample_count: 3,
total_amount: 12800,
department_distribution: { 风控部: 3 },
expense_type_distribution: { travel: 2 },
risk_type_distribution: { duplicate_invoice: 2 },
supplier_distribution: { 上海差旅供应商: 1 },
employee_grade_distribution: { P6: 2 },
top_departments: [{ name: '风控部', count: 3, amount: 8800 }],
top_employees: [{ name: '风险员工', count: 2, amount: 6200 }],
top_suppliers: [{ name: '上海差旅供应商', count: 1, amount: 1200 }],
top_expense_types: [{ name: 'travel', count: 2, amount: 4600 }],
top_rules: [{ name: 'policy.duplicate_invoice', count: 2, amount: 3000 }]
})
assert.equal(dashboard.totalAmount, 12800)
assert.equal(dashboard.riskClueCount, 2)
assert.equal(dashboard.feedbackSampleCount, 3)
assert.equal(dashboard.departmentDistribution['风控部'], 3)
assert.equal(dashboard.expenseTypeDistribution.travel, 2)
assert.equal(dashboard.riskTypeDistribution.duplicate_invoice, 2)
assert.equal(dashboard.supplierDistribution['上海差旅供应商'], 1)
assert.equal(dashboard.employeeGradeDistribution.P6, 2)
assert.equal(dashboard.topDepartments[0].amount, 8800)
assert.equal(dashboard.topRules[0].name, 'policy.duplicate_invoice')
})
test('risk dashboard renders overview amount and multi-dimension panels', () => {
assert.match(overviewViewModel, /label: '新增风险数'/)
assert.match(overviewViewModel, /label: '涉及金额'/)
assert.match(overviewViewModel, /label: '已确认风险'/)
assert.match(overviewViewModel, /label: '误报数量'/)
assert.match(dashboardComponent, /业务维度分布/)
assert.match(dashboardComponent, /异常排行/)
assert.match(dashboardComponent, /待复核线索/)
assert.match(dashboardComponent, /反馈样本/)
assert.doesNotMatch(dashboardComponent, /候选规则/)
assert.match(dashboardComponent, /departmentDistribution/)
assert.match(dashboardComponent, /expenseTypeDistribution/)
assert.match(dashboardComponent, /supplierDistribution/)
assert.match(dashboardComponent, /employeeGradeDistribution/)
assert.match(dashboardComponent, /topDepartments/)
assert.match(dashboardComponent, /topEmployees/)
assert.match(dashboardComponent, /topSuppliers/)
assert.match(dashboardComponent, /topRules/)
})
test('risk dashboard wires window filter to trend, ranking, and cards data source', () => {
assert.match(overviewViewModel, /const activeRiskWindowDays = ref\(30\)/)
assert.match(overviewViewModel, /windowDays: activeRiskWindowDays\.value/)
assert.match(overviewViewModel, /watch\(activeRiskWindowDays/)
assert.match(overviewViewModel, /setRiskWindowDays/)
assert.match(overviewTemplate, /:window-options="riskWindowOptions"/)
assert.match(overviewTemplate, /:active-window-days="activeRiskWindowDays"/)
assert.match(overviewTemplate, /@update:window-days="setRiskWindowDays"/)
assert.match(dashboardComponent, /EnterpriseSelect/)
assert.match(dashboardComponent, /aria-label="风险看板时间窗口"/)
assert.match(dashboardComponent, /emit\('update:windowDays', \$event\)/)
assert.match(dashboardComponent, /RiskDailyTrendChart/)
assert.match(dashboardComponent, /rankingGroups/)
})
test('risk dashboard shows loading overlay and realtime refresh status', () => {
assert.match(dashboardComponent, /risk-dashboard-loading-overlay/)
assert.match(dashboardComponent, /loadingLabel/)
assert.match(dashboardComponent, /lastUpdatedLabel/)
assert.match(dashboardComponent, /lastUpdatedAt/)
assert.match(overviewViewModel, /riskDashboardLastUpdatedAt/)
assert.match(overviewViewModel, /startRiskDashboardRealtimeRefresh/)
assert.match(overviewViewModel, /setInterval/)
assert.match(overviewViewModel, /document\.visibilityState === 'hidden'/)
assert.match(overviewViewModel, /riskDashboardRequestSeq/)
assert.match(overviewTemplate, /:last-updated-at="riskDashboardLastUpdatedAt"/)
})