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\(\)/ ) })