Files
X-Financial/web/tests/app-shell-financial-assistant-entry.test.mjs
caoxiaozhu d0e946cf47 feat: 完善文档中心与报销申请交互及侧边栏重构
后端优化编排器报销查询和本体检测精度,增强报销单草稿保
存和附件回填逻辑,前端重构侧边栏组件支持折叠和图标导
航,完善文档中心状态筛选和详情提示,报销创建和审批详情
页优化会话管理和费用明细交互,新增助手应用服务和预设动
作工具函数,补充单元测试覆盖。
2026-05-25 13:35:39 +08:00

72 lines
3.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 {
SESSION_TYPE_APPLICATION,
SESSION_TYPE_EXPENSE,
SESSION_TYPE_KNOWLEDGE,
buildWelcomeInsight,
buildWelcomeMessage
} from '../src/views/scripts/travelReimbursementConversationModel.js'
const appShellRouteView = readFileSync(
fileURLToPath(new URL('../src/views/AppShellRouteView.vue', import.meta.url)),
'utf8'
)
const appShellComposable = readFileSync(
fileURLToPath(new URL('../src/composables/useAppShell.js', import.meta.url)),
'utf8'
)
const assistantScript = readFileSync(
fileURLToPath(new URL('../src/views/scripts/TravelReimbursementCreateView.js', import.meta.url)),
'utf8'
)
const assistantTemplate = readFileSync(
fileURLToPath(new URL('../src/views/TravelReimbursementCreateView.vue', import.meta.url)),
'utf8'
)
test('application and reimbursement entries open the same financial assistant modal', () => {
assert.match(appShellRouteView, /<TravelReimbursementCreateView[\s\S]*:entry-source="smartEntryContext\.source"/)
assert.match(appShellRouteView, /@create-request="openTravelCreate"/)
assert.match(appShellRouteView, /@create-application="openExpenseApplicationCreate"/)
assert.match(appShellRouteView, /@new-application="openExpenseApplicationCreate"/)
assert.doesNotMatch(appShellRouteView, /ExpenseApplicationDialog/)
})
test('application entry keeps its own assistant source without creating a separate dialog', () => {
assert.match(appShellComposable, /const SMART_ENTRY_SOURCE_APPLICATION = 'application'/)
assert.match(appShellComposable, /function openExpenseApplicationCreate\(\) \{[\s\S]*openFinancialAssistantCreate\(SMART_ENTRY_SOURCE_APPLICATION\)/)
assert.match(appShellComposable, /function openTravelCreate\(\) \{[\s\S]*openFinancialAssistantCreate\(SMART_ENTRY_SOURCE_REIMBURSEMENT\)/)
assert.match(appShellComposable, /openExpenseApplicationCreate,/)
assert.match(assistantScript, /activeSessionType\.value === SESSION_TYPE_APPLICATION[\s\S]*我想先申请一笔差旅费用/)
})
test('financial assistant toolbar renders four isolated assistant sessions', () => {
assert.match(assistantScript, /ASSISTANT_SESSION_MODE_OPTIONS\.map/)
assert.match(assistantScript, /targetSessionType:\s*mode\.key/)
assert.match(assistantScript, /active:\s*mode\.key === activeSessionType\.value/)
assert.match(assistantTemplate, /:class="\{ active: shortcut\.active \}"/)
assert.match(assistantTemplate, /:aria-pressed="shortcut\.active \? 'true' : 'false'"/)
assert.match(assistantTemplate, /:disabled="shortcut\.active \|\| submitting/)
})
test('financial assistant welcome copy differentiates application intent from reimbursement entry', () => {
const user = { name: '李文静', username: 'wenjing.li', grade: 'P5' }
const applicationWelcome = buildWelcomeMessage('application', null, SESSION_TYPE_APPLICATION, user)
const reimbursementWelcome = buildWelcomeMessage('topbar', null, SESSION_TYPE_EXPENSE, user)
const knowledgeWelcome = buildWelcomeMessage('topbar', null, SESSION_TYPE_KNOWLEDGE, user)
const applicationInsight = buildWelcomeInsight('application', null, SESSION_TYPE_APPLICATION, user)
assert.match(applicationWelcome, /申请助手/)
assert.match(applicationWelcome, /费用申请、报销申请还是其他财务事项/)
assert.match(reimbursementWelcome, /报销助手/)
assert.match(reimbursementWelcome, /报销发起、票据识别、草稿归集、报销信息核对/)
assert.match(knowledgeWelcome, /财务知识助手/)
assert.notEqual(applicationWelcome, reimbursementWelcome)
assert.equal(applicationInsight.metricValue, '申请助手')
assert.equal(applicationInsight.title, '申请助手')
})