2026-10-13 20:44:31 +08:00
|
|
|
vi.mock('vue-echarts', () => ({ default: { name: 'VChart', props: ['option'], template: '<div />' } }))
|
2026-10-13 16:52:09 +08:00
|
|
|
import { mount } from '@vue/test-utils'
|
2026-10-13 20:44:31 +08:00
|
|
|
import { describe, expect, it, vi } from 'vitest'
|
2026-10-13 16:52:09 +08:00
|
|
|
import CollectionAccountMonitor from './CollectionAccountMonitor.vue'
|
|
|
|
|
import CollectionTaskProgress from './CollectionTaskProgress.vue'
|
|
|
|
|
import type { Overview, Task, WarehouseOverview } from '../types'
|
|
|
|
|
|
|
|
|
|
const child: Task = { taskNo: 'CHILD', warehouseCode: 'US01', dataFamily: 'OUTBOUND', taskStatus: 'WAITING_SOURCE', allowedActions: [], progress: null, taskType: 'BACKFILL', queryFrom: null, queryUntil: null, applyState: null, attemptCount: 0, latestAttemptNo: null, resultPublicationState: 'NOT_PUBLISHED', nextRetryAt: null, actionBlockReason: null }
|
|
|
|
|
const source: Task = { ...child, taskNo: 'SOURCE', warehouseCode: '', taskStatus: 'RUNNING', progress: { phase: 'DETAIL', progressScope: 'ACCOUNT_SHARED', countBasis: 'TASK_CUMULATIVE', completed: 339, total: 2787, totalKnown: true, unit: 'ORDER' } }
|
|
|
|
|
function overview(account: Task | null = source): Overview {
|
|
|
|
|
return { sourceAccount: 'lingxing-primary', collectionMode: 'BUSINESS', environmentLabel: 'TEST', observedAt: '2026-10-13T08:00:00Z', accountActivity: account,
|
|
|
|
|
warehouses: [{ warehouseCode: 'US01', dataFamily: 'OUTBOUND', activeTasks: [child], sharedUpstream: account }, { warehouseCode: 'US02', dataFamily: 'OUTBOUND', activeTasks: [{ ...child, taskNo: 'CHILD-2', warehouseCode: 'US02' }], sharedUpstream: account }] as WarehouseOverview[] }
|
|
|
|
|
}
|
|
|
|
|
const options = { global: { stubs: { 'el-button': true } } }
|
|
|
|
|
describe('single account collection monitor', () => {
|
2026-10-14 16:15:40 +08:00
|
|
|
it('identifies account master-data work without calling it outbound detail fetching', () => {
|
|
|
|
|
const task = { ...source, dataFamily: 'MASTER_DATA', taskType: 'MASTER_DATA', progress: { ...source.progress!, phase: 'PRODUCTS', unit: 'PAGE', completed: 2, total: 86 } }
|
|
|
|
|
const data = { ...overview(task), warehouses: [] }
|
|
|
|
|
const w = mount(CollectionAccountMonitor, { ...options, props: { overview: data } })
|
|
|
|
|
expect(w.text()).toContain('客户/商品资料'); expect(w.text()).toContain('获取商品资料'); expect(w.text()).not.toContain('获取出库目录'); w.unmount()
|
|
|
|
|
})
|
2026-10-13 20:44:31 +08:00
|
|
|
it('shows server schedules once per family and time, excluding disabled scopes', async () => {
|
|
|
|
|
const data = overview()
|
|
|
|
|
data.warehouses.forEach(row => { row.executionEnabled = true; row.nextScheduledAt = '2026-10-13T16:05:00Z' })
|
|
|
|
|
const w = mount(CollectionAccountMonitor, { ...options, props: { overview: data } })
|
|
|
|
|
expect(w.find('.account-schedules').text()).toContain('US01 / US02')
|
|
|
|
|
expect(w.find('.account-schedules').text()).toContain('2026/10/14 00:05:00')
|
|
|
|
|
expect(w.find('.account-schedules').text()).toContain('计划时间不代表当前任务完成时间')
|
|
|
|
|
await w.setProps({ stale: true })
|
|
|
|
|
expect(w.find('.account-schedules').text()).toContain('上次自动采集计划')
|
|
|
|
|
await w.setProps({ overview: { ...data, warehouses: data.warehouses.map(row => ({ ...row, executionEnabled: false })) } })
|
|
|
|
|
expect(w.find('.account-schedules').exists()).toBe(false)
|
|
|
|
|
w.unmount()
|
|
|
|
|
})
|
|
|
|
|
it('keeps the account snapshot when warehouse references contain older unknown counts', () => {
|
|
|
|
|
const data = overview()
|
|
|
|
|
data.warehouses[1]!.sharedUpstream = { ...source, progress: { ...source.progress!, phase: 'DIRECTORY', totalKnown: false, total: null, completed: 0 } }
|
|
|
|
|
const w = mount(CollectionAccountMonitor, { ...options, props: { overview: data } })
|
|
|
|
|
expect(w.findComponent(CollectionTaskProgress).props('task')).toEqual(source)
|
|
|
|
|
expect(w.text()).toContain('12.1%')
|
|
|
|
|
w.unmount()
|
|
|
|
|
})
|
2026-10-13 17:29:45 +08:00
|
|
|
it('does not claim idle or an empty queue when the first status read fails', () => {
|
|
|
|
|
const w = mount(CollectionAccountMonitor, { ...options, props: { overview: null, stale: true } })
|
|
|
|
|
expect(w.text()).toContain('暂未取得账号状态')
|
|
|
|
|
expect(w.text()).toContain('暂未取得安排')
|
|
|
|
|
expect(w.text()).not.toContain('待机')
|
|
|
|
|
expect(w.text()).not.toContain('保留最后一次')
|
|
|
|
|
expect(w.text()).not.toContain('暂无其他待处理项')
|
|
|
|
|
w.unmount()
|
|
|
|
|
})
|
2026-10-13 16:52:09 +08:00
|
|
|
it('shows account work once despite two waiting warehouses and keeps the phase counts', () => {
|
|
|
|
|
const w = mount(CollectionAccountMonitor, { ...options, props: { overview: overview() } })
|
|
|
|
|
expect(w.findAllComponents(CollectionTaskProgress)).toHaveLength(1)
|
|
|
|
|
expect(w.findComponent(CollectionTaskProgress).props('task').taskNo).toBe('SOURCE')
|
|
|
|
|
expect(w.text()).toContain('12.1%'); expect(w.text()).toContain('2448')
|
|
|
|
|
expect(w.text()).toContain('US01 · 出库销量'); expect(w.text()).toContain('US02 · 出库销量')
|
|
|
|
|
expect(w.text()).toContain('完整队列数量及下一任务顺序尚未提供')
|
|
|
|
|
expect(w.text()).not.toContain('查看配置'); expect(w.text()).not.toContain('执行心跳')
|
|
|
|
|
w.unmount()
|
|
|
|
|
})
|
|
|
|
|
it('moves on when account work ends and does not present historical completion as running', async () => {
|
|
|
|
|
const w = mount(CollectionAccountMonitor, { ...options, props: { overview: overview() } })
|
|
|
|
|
const next = overview({ ...source, taskStatus: 'SUCCEEDED' })
|
|
|
|
|
const inventory = { ...child, taskNo: 'STOCK', warehouseCode: 'US02', dataFamily: 'INVENTORY', taskStatus: 'RUNNING' }
|
|
|
|
|
next.warehouses[1]!.activeTasks = [inventory]
|
|
|
|
|
await w.setProps({ overview: next })
|
|
|
|
|
expect(w.findComponent(CollectionTaskProgress).props('task').taskNo).toBe('STOCK')
|
|
|
|
|
await w.setProps({ overview: { ...next, warehouses: [] } })
|
|
|
|
|
expect(w.text()).toContain('当前没有正在运行的采集')
|
|
|
|
|
expect(w.findComponent(CollectionTaskProgress).exists()).toBe(false)
|
|
|
|
|
w.unmount()
|
|
|
|
|
})
|
|
|
|
|
it('preserves real last counts when stale without claiming an estimate', () => {
|
|
|
|
|
const w = mount(CollectionAccountMonitor, { ...options, props: { overview: overview(), stale: true } })
|
|
|
|
|
expect(w.text()).toContain('339'); expect(w.text()).toContain('状态更新失败')
|
|
|
|
|
expect(w.text()).toContain('已暂停估算')
|
2026-10-14 11:02:56 +08:00
|
|
|
expect(w.find('.account-flow li[data-state="active"]').exists()).toBe(false)
|
2026-10-13 16:52:09 +08:00
|
|
|
w.unmount()
|
|
|
|
|
})
|
|
|
|
|
})
|