/* * Tencent is pleased to support the open source community by making TMagicEditor available. * * Copyright (C) 2025 Tencent. */ import { beforeEach, describe, expect, test, vi } from 'vitest'; import { defineComponent, h } from 'vue'; import { mount } from '@vue/test-utils'; import DisplayConds from '@editor/fields/DisplayConds.vue'; const dataSourceService = { getDataSourceById: vi.fn(), }; vi.mock('@editor/hooks/use-services', () => ({ useServices: () => ({ dataSourceService }), })); const { fieldTypeMock } = vi.hoisted(() => ({ fieldTypeMock: vi.fn((_ds: any, names: string[]) => { const key = names?.[0]; if (key === 'numField') return 'number'; if (key === 'boolField') return 'boolean'; if (key === 'nullField') return 'null'; return 'string'; }), })); vi.mock('@editor/utils', async () => { const actual = await vi.importActual('@editor/utils'); return { ...actual, getCascaderOptionsFromFields: vi.fn(() => [{ label: 'f1', value: 'f1' }]), getFieldType: fieldTypeMock, }; }); let capturedConfig: any = null; vi.mock('@tmagic/form', async () => { const actual = await vi.importActual('@tmagic/form'); return { ...actual, filterFunction: vi.fn((_m: any, v: any) => (typeof v === 'function' ? v() : v)), MGroupList: defineComponent({ name: 'MGroupList', props: ['config', 'name', 'disabled', 'model', 'lastValues', 'prop', 'size'], emits: ['change'], setup(props, { emit }) { capturedConfig = props.config; return () => h('div', { class: 'fake-group-list', onClick: () => emit('change', [{ field: ['fa'], op: 'eq', value: 'a' }]), }); }, }), }; }); beforeEach(() => { vi.clearAllMocks(); capturedConfig = null; dataSourceService.getDataSourceById.mockReturnValue({ fields: [{ name: 'a', type: 'string' }] }); }); describe('DisplayConds', () => { test('change 事件初始化数组', async () => { const model: any = {}; const wrapper = mount(DisplayConds, { props: { config: { titlePrefix: 't', parentFields: [] }, model, name: 'conds' } as any, }); await wrapper.find('.fake-group-list').trigger('click'); expect(model.conds).toEqual([]); expect(wrapper.emitted('change')).toBeTruthy(); }); test('parentFields 不为空时使用 cascader', () => { mount(DisplayConds, { props: { config: { titlePrefix: 't', parentFields: ['ds1'] }, model: {}, name: 'conds', } as any, }); const item = capturedConfig.items[0].items[0]; expect(item.type).toBe('cascader'); expect(item.options()).toEqual([{ label: 'f1', value: 'f1' }]); }); test('parentFields 为空时使用 data-source-field-select', () => { mount(DisplayConds, { props: { config: { titlePrefix: 't', parentFields: [] }, model: {}, name: 'conds', } as any, }); const item = capturedConfig.items[0].items[0]; expect(item.type).toBe('data-source-field-select'); }); test('value 字段类型 - number', () => { mount(DisplayConds, { props: { config: { titlePrefix: 't', parentFields: ['ds1'] }, model: {}, name: 'conds' } as any, }); const valueItem = capturedConfig.items[0].items[2].items[0]; expect(valueItem.type(undefined, { model: { field: ['numField'] } })).toBe('number'); expect(valueItem.type(undefined, { model: { field: ['boolField'] } })).toBe('select'); expect(valueItem.type(undefined, { model: { field: ['nullField'] } })).toBe('display'); expect(valueItem.type(undefined, { model: { field: ['anyField'] } })).toBe('text'); }); test('value display 函数', () => { mount(DisplayConds, { props: { config: { titlePrefix: 't', parentFields: [] }, model: {}, name: 'conds' } as any, }); const valueItem = capturedConfig.items[0].items[2].items[0]; expect(valueItem.display(undefined, { model: { op: 'eq' } })).toBe(true); expect(valueItem.display(undefined, { model: { op: 'between' } })).toBe(false); expect(valueItem.displayText(undefined, { model: { value: null } })).toBe('null'); expect(valueItem.displayText(undefined, { model: { value: 'a' } })).toBe('a'); }); test('range display 函数', () => { mount(DisplayConds, { props: { config: { titlePrefix: 't', parentFields: [] }, model: {}, name: 'conds' } as any, }); const rangeItem = capturedConfig.items[0].items[2].items[1]; expect(rangeItem.display(undefined, { model: { op: 'between' } })).toBe(true); expect(rangeItem.display(undefined, { model: { op: 'eq' } })).toBe(false); }); test('field onChange 转换 model.value 类型', () => { mount(DisplayConds, { props: { config: { titlePrefix: 't', parentFields: ['ds1'] }, model: {}, name: 'conds' } as any, }); const item = capturedConfig.items[0].items[0]; const m1: any = { value: '5' }; item.onChange(undefined, ['numField'], { model: m1 }); expect(m1.value).toBe(5); const m2: any = { value: '' }; item.onChange(undefined, ['boolField'], { model: m2 }); expect(m2.value).toBe(false); const m3: any = { value: 'x' }; item.onChange(undefined, ['nullField'], { model: m3 }); expect(m3.value).toBe(null); const m4: any = { value: 1 }; item.onChange(undefined, ['strField'], { model: m4 }); expect(m4.value).toBe('1'); }); test('cascader options 没有 ds 时返回空', () => { dataSourceService.getDataSourceById.mockReturnValue(null); mount(DisplayConds, { props: { config: { titlePrefix: 't', parentFields: ['ds1'] }, model: {}, name: 'conds', } as any, }); const item = capturedConfig.items[0].items[0]; expect(item.options()).toEqual([]); }); });