Files
X-Financial/web/tests/approval-task-queue-state.test.mjs

128 lines
3.9 KiB
JavaScript

import assert from 'node:assert/strict'
import test from 'node:test'
import {
createApprovalTaskSelectionState,
reconcileApprovalTaskSelectionAfterBatch,
reconcileApprovalTaskSelectionWithPage,
resolveApprovalTaskSelectionMeta,
resolveCurrentPageApprovalSelection,
syncApprovalTaskSelectionFilters,
toggleApprovalTaskSelection,
toggleCurrentPageApprovalSelection
} from '../src/views/scripts/approvalTaskQueueState.js'
function task(id, overrides = {}) {
return {
id,
status: 'pending',
version: 1,
canAct: true,
availableActions: ['approve'],
batchEligible: true,
...overrides
}
}
test('任务可选性优先使用服务端权限和批量阻断原因', () => {
assert.deepEqual(resolveApprovalTaskSelectionMeta(task('task-001')), {
taskId: 'task-001',
selectable: true,
reason: ''
})
assert.equal(
resolveApprovalTaskSelectionMeta(task('task-002', {
canAct: false,
readOnlyReason: '该任务已委托给李审批'
})).reason,
'该任务已委托给李审批'
)
assert.equal(
resolveApprovalTaskSelectionMeta(task('task-003', {
batchEligible: false,
batchBlockReasons: ['存在开放高风险', '审批意见必须单独填写']
})).reason,
'存在开放高风险;审批意见必须单独填写'
)
assert.equal(
resolveApprovalTaskSelectionMeta(task('task-004', {
availableActions: ['delegate']
})).selectable,
false
)
})
test('当前页全选和半选只处理服务端允许批量审批的任务', () => {
const rows = [
task('task-001'),
task('task-002'),
task('task-003', { batchEligible: false, batchBlockReasons: ['需单独核对'] })
]
let selected = toggleApprovalTaskSelection([], rows[0], true)
let pageState = resolveCurrentPageApprovalSelection(rows, selected)
assert.deepEqual(selected, ['task-001'])
assert.equal(pageState.indeterminate, true)
assert.equal(pageState.allSelected, false)
selected = toggleCurrentPageApprovalSelection(selected, rows, true)
pageState = resolveCurrentPageApprovalSelection(rows, selected)
assert.deepEqual(selected, ['task-001', 'task-002'])
assert.equal(pageState.allSelected, true)
assert.equal(pageState.eligibleCount, 2)
selected = toggleCurrentPageApprovalSelection(selected, rows, false)
assert.deepEqual(selected, [])
})
test('刷新后任务失去权限时从当前页选择中移除', () => {
const selected = ['off-page-task', 'task-001', 'task-002']
const rows = [
task('task-001'),
task('task-002', { canAct: false, readOnlyReason: '任务已转交' })
]
assert.deepEqual(
reconcileApprovalTaskSelectionWithPage(selected, rows),
['off-page-task', 'task-001']
)
})
test('筛选变化清空选择但翻页和每页条数变化不清空', () => {
let state = createApprovalTaskSelectionState({
selectedTaskIds: ['task-001', 'task-002'],
filters: { status: 'pending', riskLevel: 'high', page: 1, pageSize: 20 }
})
state = syncApprovalTaskSelectionFilters(state, {
status: 'pending',
riskLevel: 'high',
page: 2,
pageSize: 50
})
assert.deepEqual(state.selectedTaskIds, ['task-001', 'task-002'])
state = syncApprovalTaskSelectionFilters(state, {
status: 'pending',
riskLevel: 'medium',
page: 1,
pageSize: 20
})
assert.deepEqual(state.selectedTaskIds, [])
})
test('批量部分成功只移除成功和幂等重放项,失败项继续保留', () => {
const selected = ['task-001', 'task-002', 'task-003', 'task-004', 'task-005', 'task-unreported']
const result = {
status: 'partial',
items: [
{ taskId: 'task-001', status: 'succeeded' },
{ taskId: 'task-002', status: 'replayed' },
{ taskId: 'task-003', status: 'blocked' },
{ taskId: 'task-004', status: 'conflict' },
{ taskId: 'task-005', status: 'forbidden' }
]
}
assert.deepEqual(
reconcileApprovalTaskSelectionAfterBatch(selected, result),
['task-003', 'task-004', 'task-005', 'task-unreported']
)
})