Files
X-Financial/web/tests/expense-attachment-draft-selection.test.mjs
caoxiaozhu e725b7f19c feat(web): 票据夹资产缓存接入与 AI 工作台附件流程完善
- ReceiptFolderView 删除票据后提示已关联附件副本保留,接入 useToast;fetchReceiptFolderAsset 加 no-store 避免预览缓存
- PersonalWorkbenchAiMode 附件区/对话气泡适配资产缓存,personal-workbench-ai-mode.css 调整布局
- usePersonalWorkbenchAiMode/useWorkbenchAiApplicationPreviewFlow/useWorkbenchAiAttachmentAssociationFlow/useWorkbenchAiStewardFlow 完善附件草稿选择与关联流程
- travelRequestDetailSmartEntryRecognition 智能识别增强,AppShellRouteView/PersonalWorkbenchView/useApplicationPreviewEditor/useTravelReimbursementSubmitComposer 等配套适配
- 新增 expense-attachment-draft-selection、receipt-folder-asset-cache、travel-request-detail-smart-entry-recognition 测试,更新 attachment-association-confirmation、expense-application-fast-preview、workbench-ai-mode-switch 测试
2026-06-23 09:42:13 +08:00

91 lines
3.2 KiB
JavaScript

import assert from 'node:assert/strict'
import { readFileSync } from 'node:fs'
import test from 'node:test'
import { fileURLToPath } from 'node:url'
import { useTravelReimbursementCreateViewControls } from '../src/views/scripts/useTravelReimbursementCreateViewControls.js'
function ref(value) {
return { value }
}
const submitComposerScript = readFileSync(
fileURLToPath(new URL('../src/views/scripts/useTravelReimbursementSubmitComposer.js', import.meta.url)),
'utf8'
)
test('选择候选草稿时直接确认归集并带入附件原件', async () => {
const submitCalls = []
const attachedFiles = [{ name: '2月20 武汉-上海.pdf' }]
const message = {
queryPayload: {
selectionMode: 'draft_association'
}
}
const controls = useTravelReimbursementCreateViewControls({
activeSessionType: ref('expense'),
attachedFiles: ref(attachedFiles),
clearAssistantSessionSnapshot: () => {},
closeAfterBusy: ref(false),
conversationId: ref('conversation-1'),
deleteConversation: async () => {},
deleteSessionBusy: ref(false),
deleteSessionDialogOpen: ref(false),
draftClaimId: ref(''),
emitClose: () => {},
getExpenseQueryActivePage: () => 1,
getExpenseQueryTotalPages: () => 1,
persistSessionState: () => {},
resetCurrentSessionState: () => {},
reviewActionBusy: ref(false),
router: { push: () => {} },
resolveCurrentUserId: () => 'user-1',
sessionSwitchBusy: ref(false),
submitComposer: async (options) => {
submitCalls.push(options)
return { ok: true }
},
submitting: ref(false),
toast: () => {},
workbenchVisible: ref(true)
})
await controls.handleExpenseQueryRecordClick(message, {
claimId: 'claim-1',
claimNo: 'R74CB7C2R'
})
assert.equal(submitCalls.length, 1)
assert.equal(submitCalls[0].associationConfirmed, true)
assert.equal(submitCalls[0].skipDraftAssociationPrompt, true)
assert.equal(submitCalls[0].uploadDisposition, 'continue_existing')
assert.deepEqual(submitCalls[0].files, attachedFiles)
assert.equal(submitCalls[0].files[0], attachedFiles[0])
assert.equal(submitCalls[0].extraContext.review_action, 'link_to_existing_draft')
assert.equal(submitCalls[0].extraContext.attachment_association_confirmed, true)
assert.equal(submitCalls[0].extraContext.draft_claim_id, 'claim-1')
assert.equal(message.queryPayload.selectionLocked, true)
assert.equal(message.queryPayload.selectedClaimId, 'claim-1')
})
test('确认归集到现有草稿时先同步附件再渲染最终结果', () => {
assert.match(
submitComposerScript,
/let attachmentSyncCompleted = false/
)
assert.match(
submitComposerScript,
/if \(\s*reviewActionResult === 'link_to_existing_draft'[\s\S]*await persistComposerFilesToDraft\(\)[\s\S]*attachmentSyncCompleted = true[\s\S]*\}/
)
assert.ok(
submitComposerScript.indexOf('await persistComposerFilesToDraft()') <
submitComposerScript.indexOf('const assistantMessage = createMessage('),
'附件同步应先于最终助手消息,避免详情页先展示空明细和旧风险'
)
assert.match(
submitComposerScript,
/if \(!attachmentSyncCompleted\) \{\s*const persistTask = persistComposerFilesToDraft\(\)/
)
})