Files
2026-09-13 23:16:08 +08:00

117 lines
3.7 KiB
JavaScript

/**
* FmsSelect 远程查找选择器测试。
* 覆盖契约:展开即加载首页、选中抛出 id/label/整行 record、
* 键入按 labelKey 防抖远程 LIKE 搜索、当前选中项不在结果中时回显补入列表首。
*/
import { describe, it, expect, vi, beforeEach, afterEach } from 'vitest'
import { mount, flushPromises } from '@vue/test-utils'
import { nextTick } from 'vue'
import FmsSelect from '@/components/fms-select/FmsSelect.vue'
import { pageDataApi } from '@/services/api'
vi.mock('@/services/api', () => ({
pageDataApi: vi.fn(),
}))
/** 让 pageDataApi 返回给定行 */
function mockRows(rows, total = rows.length) {
pageDataApi.mockResolvedValue({ data: { rows, total } })
}
beforeEach(() => {
pageDataApi.mockReset()
})
afterEach(() => {
vi.useRealTimers()
// 清空 Teleport 到 body 的下拉浮层残留;replaceChildren 不解析 markup,比 innerHTML='' 更安全
document.body.replaceChildren()
})
describe('FmsSelect 远程查找', () => {
it('展开即加载首页并渲染选项', async () => {
mockRows([
{ b_id: '1', b_name: '甲' },
{ b_id: '2', b_name: '乙' },
])
const wrapper = mount(FmsSelect, {
props: { viewName: 'v_customer' },
attachTo: document.body,
})
await wrapper.find('.select-trigger').trigger('click')
await flushPromises()
await nextTick()
expect(pageDataApi).toHaveBeenCalledWith(
expect.objectContaining({ viewName: 'v_customer', pageNo: 1 }),
)
const options = document.body.querySelectorAll('.select-option')
expect(options.length).toBe(2)
expect(options[0].textContent).toContain('甲')
wrapper.unmount()
})
it('选中抛出 id / label / 整行 record', async () => {
mockRows([{ b_id: '1', b_name: '甲', extra: 'x' }])
const wrapper = mount(FmsSelect, {
props: { viewName: 'v_customer' },
attachTo: document.body,
})
await wrapper.find('.select-trigger').trigger('click')
await flushPromises()
await nextTick()
document.body.querySelector('.select-option').click()
await flushPromises()
await nextTick()
expect(wrapper.emitted('update:modelValue')?.at(-1)).toEqual(['1'])
expect(wrapper.emitted('update:label')?.at(-1)).toEqual(['甲'])
expect(wrapper.emitted('change')?.at(-1)?.[0]).toEqual({ b_id: '1', b_name: '甲', extra: 'x' })
wrapper.unmount()
})
it('当前选中项不在结果中时回显到列表首', async () => {
mockRows([{ b_id: '2', b_name: '乙' }])
const wrapper = mount(FmsSelect, {
props: { viewName: 'v_customer', modelValue: '9', label: '既存客户' },
attachTo: document.body,
})
await wrapper.find('.select-trigger').trigger('click')
await flushPromises()
await nextTick()
const options = document.body.querySelectorAll('.select-option')
expect(options.length).toBe(2)
expect(options[0].textContent).toContain('既存客户')
wrapper.unmount()
})
it('键入按 labelKey 远程 LIKE 搜索(防抖)', async () => {
mockRows([])
const wrapper = mount(FmsSelect, {
props: { viewName: 'v_customer', searchDelay: 300 },
attachTo: document.body,
})
// 先展开:immediate('') 会拉一次全量,与后续搜索区分开
await wrapper.find('.select-trigger').trigger('click')
await flushPromises()
vi.useFakeTimers()
pageDataApi.mockClear()
await wrapper.find('.select-input').setValue('kw')
// 防抖窗口内不发请求
expect(pageDataApi).not.toHaveBeenCalled()
await vi.advanceTimersByTimeAsync(300)
expect(pageDataApi).toHaveBeenCalledWith(
expect.objectContaining({ searchCondition: "b_name LIKE '%kw%'" }),
)
wrapper.unmount()
})
})