/** * 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() }) })