Files
X-Financial/web/tests/receipt-folder-view.test.mjs
caoxiaozhu 92444e7eae feat: 扩展风险规则体系、审批动态路由与预算中心列表化改造
- 新增 25+ 条风险规则(预算/报销/申请/通用类),完善风险规则模拟与反馈发布机制
- 引入费用审批动态路由、平台风险分级、预审与风险阶段管理
- 预算中心列表化改造,优化票据夹仪表盘与数字员工工作看板
- 新增 Hermes 风险线索收集器、Agent 链路追踪中心
- 扩展数字员工能力库(18 个领域 Skill)与交通费用自动预估
- 完善报销申请快速预览、权限控制与前端测试覆盖
2026-06-01 17:07:14 +08:00

162 lines
7.6 KiB
JavaScript

import assert from 'node:assert/strict'
import { readFileSync } from 'node:fs'
import { join } from 'node:path'
const root = process.cwd()
function readProjectFile(path) {
return readFileSync(join(root, path), 'utf8')
}
function testReceiptFolderViewSurface() {
const view = readProjectFile('web/src/views/ReceiptFolderView.vue')
assert.match(view, /activeStatus = ref\('all'\)/)
assert.match(view, /value: 'all'/)
assert.match(view, /openAssociateDialog/)
assert.match(view, /receipt-detail-toolbar/)
assert.match(view, /receipt-dashboard/)
assert.match(view, /receipt-dashboard-preview/)
assert.match(view, /receipt-dashboard-side/)
assert.match(view, /receipt-dashboard-bottom/)
assert.match(view, /receipt-ocr-panel/)
assert.match(view, /receipt-status-panel/)
assert.match(view, /keyReceiptFields/)
assert.match(view, /editableOtherFields/)
assert.match(view, /ocrPreviewFields/)
assert.match(view, /class="receipt-key-grid"/)
assert.match(view, /class="receipt-other-collapse"/)
assert.match(view, /class="receipt-other-scroll"/)
assert.match(view, /previewTransform/)
assert.match(view, /openAssociateDialogForCurrentReceipt/)
assert.match(view, /createReceiptDetailDashboardModel/)
assert.match(view, /ElCollapse/)
assert.doesNotMatch(view, /addField/)
assert.match(view, /const isTrainTicket = computed/)
assert.doesNotMatch(view, /打开源文件/)
assert.doesNotMatch(view, /openSourceFile/)
assert.match(view, /back-label=/)
assert.doesNotMatch(view, /back-btn/)
assert.match(view, /deleteCurrentReceipt/)
assert.match(view, /ElCheckboxGroup/)
assert.match(view, /fetchReceiptFolderItems\('all'\)/)
assert.match(view, /buildReceiptFile\(item\)/)
assert.match(view, /source: selectedDraft \? 'detail' : 'receipt-folder'/)
assert.match(view, /emit\('open-assistant'/)
}
function testReceiptFolderServiceContract() {
const service = readProjectFile('web/src/services/receiptFolder.js')
const ocrService = readProjectFile('web/src/services/ocr.js')
const reimbursementService = readProjectFile('web/src/services/reimbursements.js')
assert.match(service, /\/receipt-folder\$\{buildStatusQuery\(status\)\}/)
assert.match(service, /\/receipt-folder\/\$\{encodeURIComponent/)
assert.match(service, /responseType: 'blob'/)
assert.match(service, /new File\(\[blob\], fileName/)
assert.match(service, /receiptId/)
assert.match(ocrService, /formData\.append\('receipt_ids'/)
assert.match(reimbursementService, /formData\.append\('receipt_id'/)
}
function testAppShellWiresReceiptFolder() {
const shell = readProjectFile('web/src/views/AppShellRouteView.vue')
const topBar = readProjectFile('web/src/components/layout/TopBar.vue')
assert.match(shell, /activeView === 'receiptFolder'/)
assert.match(shell, /ReceiptFolderView/)
assert.match(shell, /@open-assistant="openSmartEntry"/)
assert.match(shell, /@detail-open-change="receiptFolderDetailOpen = \$event"/)
assert.match(shell, /@detail-topbar-change="detailTopBarPayload = \$event"/)
assert.match(shell, /receipt-folder-workarea/)
assert.match(topBar, /receiptFolder/)
assert.match(topBar, /eyebrowLabel/)
}
function testSharedDocumentListStyleReuse() {
const receiptView = readProjectFile('web/src/views/ReceiptFolderView.vue')
const documentView = readProjectFile('web/src/views/DocumentsCenterView.vue')
const receiptStyles = readProjectFile('web/src/assets/styles/views/receipt-folder-view.css')
const sharedStyles = readProjectFile('web/src/assets/styles/components/document-list-shared.css')
assert.match(receiptView, /document-list-shared\.css/)
assert.match(documentView, /document-list-shared\.css/)
assert.match(sharedStyles, /\.table-wrap\b/)
assert.match(sharedStyles, /\.doc-kind-tag\b/)
assert.match(sharedStyles, /\.list-foot\b/)
assert.doesNotMatch(receiptStyles, /\.table-wrap\b/)
assert.doesNotMatch(receiptStyles, /\.doc-kind-tag\b/)
assert.doesNotMatch(receiptStyles, /\.list-foot\b/)
}
function testReceiptFolderDetailLayoutAdjustments() {
const receiptView = readProjectFile('web/src/views/ReceiptFolderView.vue')
const receiptStyles = readProjectFile('web/src/assets/styles/views/receipt-folder-view.css')
const fieldModel = readProjectFile('web/src/views/scripts/receiptFolderDetailFields.js')
assert.match(receiptView, /showStatusColumn/)
assert.match(receiptView, /<col v-if="showStatusColumn" class="col-status">/)
assert.match(receiptView, /<th v-if="showStatusColumn">/)
assert.match(receiptView, /document_date/)
assert.match(receiptView, /<td>\s*<strong class="doc-id">/)
assert.match(receiptView, /<td v-if="showStatusColumn">\s*<span class="status-tag"/)
assert.match(receiptView, /const activeStatus = ref\('all'\)/)
assert.match(receiptView, /import EnterpriseDetailCard/)
assert.match(receiptView, /import EnterpriseDetailPage/)
assert.match(receiptView, /<EnterpriseDetailPage/)
assert.match(receiptView, /variant="receipt-folder-detail"/)
assert.match(receiptView, /<EnterpriseDetailCard class="receipt-basic-panel"/)
assert.match(receiptView, /receipt-dashboard-preview/)
assert.match(receiptView, /receipt-dashboard-bottom/)
assert.match(receiptView, /createReceiptDetailFieldModel/)
assert.match(receiptView, /createReceiptDetailDashboardModel/)
assert.match(receiptView, /buildDetailPayload\(\)/)
assert.match(receiptView, /receiptDetailSubtitle/)
assert.match(receiptView, /receiptDetailTopBarPayload/)
assert.match(receiptView, /eyebrow:/)
assert.match(receiptView, /detail-topbar-change/)
assert.doesNotMatch(receiptView, /<article v-else class="receipt-folder-detail/)
assert.doesNotMatch(receiptView, /class="back-btn"/)
assert.doesNotMatch(receiptView, /receipt-detail-head/)
assert.doesNotMatch(receiptView, /detail-actions receipt-detail-foot/)
assert.match(receiptStyles, /\.receipt-folder-list th:first-child/)
assert.match(receiptStyles, /\.receipt-folder-detail :deep\(\.detail-grid\)/)
assert.match(receiptStyles, /\.receipt-folder-detail :deep\(\.detail-actions\)/)
assert.match(receiptStyles, /\.receipt-folder-detail :deep\(\.enterprise-detail-card \.card-head\)/)
assert.match(receiptStyles, /\.receipt-detail-toolbar/)
assert.match(receiptStyles, /\.receipt-dashboard/)
assert.match(receiptStyles, /\.receipt-dashboard-bottom/)
assert.match(receiptStyles, /\.receipt-preview-tools/)
assert.match(receiptStyles, /\.receipt-log-list/)
assert.match(receiptStyles, /\.receipt-key-grid/)
assert.match(receiptStyles, /\.receipt-other-collapse/)
assert.match(receiptStyles, /\.receipt-other-scroll/)
assert.doesNotMatch(receiptStyles, /\.receipt-detail-head\b/)
assert.doesNotMatch(receiptStyles, /\.receipt-detail-layout\b/)
assert.doesNotMatch(receiptStyles, /\.detail-loading\b/)
assert.doesNotMatch(receiptStyles, /\.back-btn\b/)
assert.doesNotMatch(receiptStyles, /\.danger-btn\b/)
assert.match(fieldModel, /TRAIN_KEY_FIELD_DEFINITIONS/)
assert.match(fieldModel, /id: 'invoice_number'/)
assert.match(fieldModel, /id: 'invoice_date'/)
assert.match(fieldModel, /id: 'fare'/)
assert.match(fieldModel, /id: 'passenger_name'/)
assert.match(fieldModel, /syncEditableFieldsToTopLevel/)
const dashboardModel = readProjectFile('web/src/views/scripts/receiptFolderDetailDashboard.js')
assert.match(dashboardModel, /createReceiptDetailDashboardModel/)
assert.match(dashboardModel, /basicInfoItems/)
assert.match(dashboardModel, /operationLogs/)
assert.match(dashboardModel, /archiveInfoItems/)
}
function run() {
testReceiptFolderViewSurface()
testReceiptFolderServiceContract()
testAppShellWiresReceiptFolder()
testSharedDocumentListStyleReuse()
testReceiptFolderDetailLayoutAdjustments()
console.log('receipt folder view tests passed')
}
run()