Files
admin-web/src/modules/self-operated/components/OwnerPicker.test.ts
T

42 lines
3.6 KiB
TypeScript

import { defineComponent, h } from 'vue'
import { flushPromises, mount } from '@vue/test-utils'
import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest'
import OwnerPicker from './OwnerPicker.vue'
import type { QueryContext } from '../types'
const owners = vi.hoisted(() => vi.fn())
vi.mock('../api/analytics', () => ({ analyticsApi: { owners } }))
const context: QueryContext = { salesRunId: '11', inventoryRunId: '12', salesScopeHash: 'sales', inventoryScopeHash: 'stock', queryAsOf: '2026-10-12T01:00:00Z', queryExpiresAt: '2026-10-12T01:30:00Z', businessTimezone: 'Asia/Shanghai', anchorDate: '2026-10-12' }
const select = defineComponent({ props: ['remoteMethod'], setup(props, { slots }) { return () => h('div', [h('button', { onClick: () => props.remoteMethod('Ab_') }, '前缀搜索'), slots.default?.()]) } })
const button = defineComponent({ props: ['disabled'], emits: ['click'], setup(props, { slots, emit }) { return () => h('button', { disabled: props.disabled, onClick: () => emit('click') }, slots.default?.()) } })
const option = defineComponent({ props: ['label'], setup(props) { return () => h('span', props.label) } })
const global = { stubs: { 'el-select': select, 'el-button': button, 'el-option': option } }
const wrappers: ReturnType<typeof mount>[] = []
beforeEach(() => { owners.mockReset(); owners.mockResolvedValue({ context, records: [{ customerCode: 'OWNER-A', customerName: '货主甲' }], total: 25 }) })
afterEach(() => wrappers.splice(0).forEach(wrapper => wrapper.unmount()))
describe('fixed-context owner selector', () => {
it('uses backend pagination and prefix search without changing the pinned context', async () => {
const wrapper = mount(OwnerPicker, { props: { modelValue: '', sourceAccount: 'lingxing-primary', warehouseCode: 'WH-A', context }, global }); wrappers.push(wrapper)
await flushPromises()
await wrapper.findAll('button').find(node => node.text() === '下一页货主')!.trigger('click'); await flushPromises()
expect(owners.mock.calls.at(-1)?.[0]).toMatchObject({ current: 2, size: 20, salesRunId: '11', inventoryRunId: '12', queryAsOf: context.queryAsOf })
await wrapper.findAll('button').find(node => node.text() === '前缀搜索')!.trigger('click'); await flushPromises()
expect(owners.mock.calls.at(-1)?.[0]).toMatchObject({ keyword: 'Ab_', current: 1, queryAsOf: context.queryAsOf })
expect(wrapper.text()).toContain('OWNER-A · 货主甲')
})
it('ignores late options from the old warehouse and rejects mixed-version choices', async () => {
let resolve!: (value: object) => void
owners.mockImplementationOnce(() => new Promise(done => { resolve = done })).mockResolvedValue({ context, records: [{ customerCode: 'OWNER-B', customerName: null }], total: 1 })
const wrapper = mount(OwnerPicker, { props: { modelValue: '', sourceAccount: 'lingxing-primary', warehouseCode: 'WH-A', context }, global }); wrappers.push(wrapper)
await wrapper.setProps({ warehouseCode: 'WH-B' }); await flushPromises()
resolve({ context, records: [{ customerCode: 'OLD-OWNER', customerName: null }], total: 1 }); await flushPromises()
expect(wrapper.text()).toContain('OWNER-B')
expect(wrapper.text()).not.toContain('OLD-OWNER')
expect(owners.mock.calls[0]?.[1].aborted).toBe(true)
owners.mockResolvedValue({ context: { ...context, inventoryRunId: '99' }, records: [{ customerCode: 'WRONG-VERSION' }], total: 1 })
await wrapper.findAll('button').find(node => node.text() === '前缀搜索')!.trigger('click'); await flushPromises()
expect(wrapper.text()).not.toContain('WRONG-VERSION')
expect(wrapper.text()).toContain('货主选项版本已变化')
})
})