- 新增 PersonalWorkbenchAiMode 组件、AI 侧边栏与 orb 机器人视觉资源 - 新增 aiApplicationDraftModel / aiExpenseDraftModel / aiWorkbenchConversationStore 及业务准入 aiSidebarBusinessAccess,支撑 AI 模式下的申请与报销草稿 - 顶栏、侧边栏、工作台样式重构,适配 AI 模式切换与响应式布局 - 同步 steward plan/off_topic、差旅报销引导流、风险建议卡片等测试
108 lines
5.1 KiB
JavaScript
108 lines
5.1 KiB
JavaScript
import assert from 'node:assert/strict'
|
|
import { readFileSync } from 'node:fs'
|
|
import test from 'node:test'
|
|
import { fileURLToPath } from 'node:url'
|
|
|
|
import { departmentRangeOptions } from '../src/data/metrics.js'
|
|
|
|
const overviewView = readFileSync(
|
|
fileURLToPath(new URL('../src/views/OverviewView.vue', import.meta.url)),
|
|
'utf8'
|
|
)
|
|
const overviewViewModel = readFileSync(
|
|
fileURLToPath(new URL('../src/composables/useOverviewView.js', import.meta.url)),
|
|
'utf8'
|
|
)
|
|
const analyticsService = readFileSync(
|
|
fileURLToPath(new URL('../src/services/analytics.js', import.meta.url)),
|
|
'utf8'
|
|
)
|
|
const barChart = readFileSync(
|
|
fileURLToPath(new URL('../src/components/charts/BarChart.vue', import.meta.url)),
|
|
'utf8'
|
|
)
|
|
const trendChart = readFileSync(
|
|
fileURLToPath(new URL('../src/components/charts/TrendChart.vue', import.meta.url)),
|
|
'utf8'
|
|
)
|
|
|
|
test('finance dashboard keeps legacy ranking range constants for backend compatibility', () => {
|
|
assert.deepEqual(departmentRangeOptions, [
|
|
'\u672c\u6708',
|
|
'\u672c\u5b63\u5ea6',
|
|
'\u672c\u5e74',
|
|
'\u5168\u90e8'
|
|
])
|
|
assert.match(analyticsService, /department_employee_mix/)
|
|
assert.match(analyticsService, /departmentEmployeeMix/)
|
|
assert.match(analyticsService, /department_range/)
|
|
})
|
|
|
|
test('finance dashboard rankings follow top range and render department employee mix chart', () => {
|
|
assert.match(overviewView, /departmentEmployeeLegend/)
|
|
assert.match(overviewView, /departmentEmployeeCenterValue/)
|
|
assert.match(overviewView, /class="top-claim-split"/)
|
|
assert.match(overviewView, /card-range-chip/)
|
|
assert.doesNotMatch(overviewView, /aria-label="\u90e8\u95e8\u6392\u884c\u65f6\u95f4\u8303\u56f4"/)
|
|
assert.doesNotMatch(overviewView, /aria-label="\u4e2a\u4eba\u6392\u884c\u65f6\u95f4\u8303\u56f4"/)
|
|
assert.doesNotMatch(overviewView, /v-model="activeDepartmentRange"/)
|
|
assert.doesNotMatch(overviewView, /v-model="activeTrendRange"/)
|
|
assert.match(overviewViewModel, /financeDepartmentEmployeeMix/)
|
|
assert.match(overviewViewModel, /departmentEmployeeLegend/)
|
|
assert.match(overviewViewModel, /employeeCount/)
|
|
assert.match(overviewViewModel, /trendRange: resolveTopRangeKey/)
|
|
assert.match(overviewViewModel, /departmentRange: resolveTopRangeKey/)
|
|
assert.match(overviewViewModel, /const topRangeDays = computed/)
|
|
})
|
|
|
|
test('finance ranking bar chart can display ranking metadata', () => {
|
|
assert.match(barChart, /rank-meta/)
|
|
assert.match(barChart, /item\.meta/)
|
|
assert.match(overviewViewModel, /meta: `\$\{Number\(item\.employeeCount/)
|
|
assert.match(overviewViewModel, /meta: `\$\{item\.department/)
|
|
})
|
|
|
|
test('daily amount trend uses stacked category bars with clear unit and legend', () => {
|
|
assert.match(overviewView, /:category-amount-series="activeTrend\.categoryAmountSeries"/)
|
|
assert.match(overviewView, /:key="`finance-amount-\$\{financeDashboardRenderKey\}`"/)
|
|
assert.match(overviewView, /:key="`finance-count-\$\{financeDashboardRenderKey\}`"/)
|
|
assert.match(overviewView, /return financeDashboardLoading\.value\s*\n\}/)
|
|
assert.doesNotMatch(overviewView, /financeDashboardLoading\.value && !financeDashboardLoaded\.value/)
|
|
assert.match(overviewViewModel, /categoryAmountSeries: \[\]/)
|
|
assert.match(overviewViewModel, /financeDashboardRenderKey/)
|
|
assert.match(overviewViewModel, /financeDashboardRequestSeq/)
|
|
assert.match(overviewViewModel, /requestSeq !== financeDashboardRequestSeq/)
|
|
assert.match(overviewViewModel, /financeDashboardRenderKey\.value \+= 1/)
|
|
assert.match(trendChart, /categoryAmountSeries/)
|
|
assert.match(trendChart, /CustomChart as EChartsCustomChart/)
|
|
assert.match(trendChart, /type: 'custom'/)
|
|
assert.match(trendChart, /renderStackedAmountBar/)
|
|
assert.match(trendChart, /resolveCategoryColor/)
|
|
assert.match(trendChart, /expenseCategoryColorMap/)
|
|
assert.match(trendChart, /clipPath/)
|
|
assert.match(trendChart, /enterFrom/)
|
|
assert.match(trendChart, /originY: zeroY/)
|
|
assert.match(trendChart, /scaleY: 0/)
|
|
assert.match(trendChart, /chart-unit/)
|
|
assert.match(trendChart, /unitLabel/)
|
|
assert.match(trendChart, /legendItems/)
|
|
assert.match(trendChart, /单位:元/)
|
|
assert.match(trendChart, /单位:单/)
|
|
assert.match(trendChart, /comparisonAmount/)
|
|
assert.match(trendChart, /isComparisonMode/)
|
|
assert.match(trendChart, /props\.mode === 'compareAmount'/)
|
|
assert.match(trendChart, /props\.comparisonLabel/)
|
|
assert.match(trendChart, /const compactScale = computed/)
|
|
assert.match(trendChart, /const chartGrid = computed/)
|
|
assert.match(trendChart, /gridBottom:\s*props\.compact \? 18 : 22/)
|
|
assert.match(trendChart, /gridTop:\s*props\.compact \? 10 : 12/)
|
|
assert.match(trendChart, /splitNumber:\s*props\.compact \? 2 : 5/)
|
|
assert.match(trendChart, /primaryLineWidth:\s*props\.compact \? 3\.8 : 3/)
|
|
assert.match(trendChart, /axisLabelSize:\s*props\.compact \? 12 : 11/)
|
|
assert.match(trendChart, /lineStyle:[\s\S]*type:\s*'dashed'/)
|
|
assert.match(trendChart, /\.trend-chart-compact\s*\{[\s\S]*min-height:\s*124px;/)
|
|
assert.match(trendChart, /\.trend-chart-compact \.chart-legend\s*\{[\s\S]*font-size:\s*13px;/)
|
|
assert.doesNotMatch(trendChart, /name:\s*isCountMode\.value/)
|
|
assert.doesNotMatch(trendChart, /stack: 'expenseAmount'/)
|
|
})
|