Files
client-web/src/modules/cross-border/orderFundingStatus.test.mjs
T

96 lines
4.7 KiB
JavaScript
Raw Normal View History

2026-10-30 17:59:48 +08:00
import assert from 'node:assert/strict'
import { readFileSync } from 'node:fs'
import test from 'node:test'
import { runInNewContext } from 'node:vm'
import ts from 'typescript'
const source = readFileSync(new URL('./components/OrderFundingStatus.vue', import.meta.url), 'utf8')
const script = source.match(/<script setup lang="ts">([\s\S]*?)<\/script>/)[1].replace(/^import .*$/gm, '')
function harness({ status = 'FUNDING_PENDING', read = async () => ({ status: 'FREEZE_PENDING' }), retry = async () => ({}), detail = async () => ({}) } = {}) {
const props = { kind: 'procurement', orderNo: 'CG1', status, canRetry: true }
const timers = new Map(), events = [], hooks = {}
let nextTimer = 0
const context = {
defineProps: () => props, defineEmits: () => event => events.push(event), ref: value => ({ value }),
watch: (_getter, callback) => { hooks.watch = callback },
onBeforeUnmount: callback => { hooks.unmount = callback },
onActivated: callback => { hooks.activate = callback },
onDeactivated: callback => { hooks.deactivate = callback },
setTimeout: callback => { const id = ++nextTimer; timers.set(id, callback); return id },
clearTimeout: id => timers.delete(id), readOrderFunding: read, retryOrderFunding: retry, getBusinessOrder: detail,
}
const compiled = ts.transpileModule(script, { compilerOptions: { target: ts.ScriptTarget.ES2022 } }).outputText
const api = runInNewContext(`${compiled}\n({check, retry, message, busy})`, context)
return { ...api, props, timers, events, hooks }
}
test('truck rejection uses latest review reason and never customer remarks', async () => {
const h = harness({ status: 'REJECTED', detail: async () => ({ remark: '客户备注', histories: [
{ operationType: 'REVIEW', toStatus: 'REJECTED', remark: '旧原因' },
{ operationType: 'REVIEW', toStatus: 'REJECTED', remark: '路线暂不支持' },
{ operationType: 'UPDATE', toStatus: 'REJECTED', remark: '内部修改' },
] }) })
h.props.kind = 'trucking'
await h.check(0, 0)
assert.equal(h.message.value, '路线暂不支持')
assert.equal(h.timers.size, 0)
const missing = harness({ status: 'REJECTED', detail: async () => ({ remark: '客户备注' }) })
missing.props.kind = 'trucking'; await missing.check(0, 0)
assert.equal(missing.message.value, '未填写拒绝原因')
})
test('funding status polls for a bounded time and refreshes detail only on a result', async () => {
let count = 0
const h = harness({ read: async () => { count++; return { status: 'FREEZE_PENDING' } } })
await h.check(0, 0)
assert.equal(h.timers.size, 1)
for (let i = 1; i <= 30; i++) {
const [id, callback] = h.timers.entries().next().value
h.timers.delete(id); callback(); await new Promise(resolve => setImmediate(resolve))
}
assert.equal(count, 31)
assert.equal(h.timers.size, 0)
assert.equal(h.events.length, 0)
for (const status of ['FROZEN', 'FAILED']) {
const terminal = harness({ read: async () => ({ status, message: '余额不足' }) })
await terminal.check(0, 0)
assert.equal(terminal.events.join(','), 'changed')
assert.equal(terminal.timers.size, 0)
}
})
test('retry keeps original order and suppresses double clicks and stale responses', async () => {
let resolve, calls = 0
const h = harness({ status: 'FUNDING_FAILED', retry: (kind, no) => {
calls++; assert.equal(kind, 'procurement'); assert.equal(no, 'CG1')
return new Promise(done => { resolve = done })
} })
const first = h.retry(); await h.retry()
assert.equal(calls, 1)
h.hooks.deactivate(); resolve({}); await first
assert.equal(h.events.length, 0)
const denied = harness({ status: 'FUNDING_FAILED', retry: async () => { throw new Error('should not call') } })
denied.props.canRetry = false; await denied.retry()
assert.equal(denied.message.value, '')
})
test('switching or leaving an order ignores the old funding result', async () => {
let resolve
const h = harness({ read: () => new Promise(done => { resolve = done }) })
const pending = h.check(0, 0)
h.hooks.unmount(); resolve({ status: 'FAILED', message: 'old order' }); await pending
assert.equal(h.message.value, '')
assert.equal(h.events.length, 0)
assert.equal(h.timers.size, 0)
})
test('failed orders display finance reason and refresh when another session retries', async () => {
const failed = harness({ status: 'FUNDING_FAILED', read: async () => ({ status: 'FAILED', message: '可用余额及授信不足' }) })
await failed.check(0, 0)
assert.equal(failed.message.value, '可用余额及授信不足')
assert.equal(failed.events.length, 0)
const retried = harness({ status: 'FUNDING_FAILED' })
await retried.check(0, 0)
assert.equal(retried.events.join(','), 'changed')
})