20260916172703
This commit is contained in:
1 parent
dce29f250e
commit
de05498552
25 files changed
+1141
-1315
No files matched your search
@@ -4,6 +4,7 @@ import { beforeEach, describe, expect, it } from 'vitest'
|
||||
import FmsQueryControl from '@/components/fms-module-list/FmsQueryControl.vue'
|
||||
import FmsQueryToolbar from '@/components/fms-module-list/FmsQueryToolbar.vue'
|
||||
import FmsAdvancedQueryPanel from '@/components/fms-module-list/FmsAdvancedQueryPanel.vue'
|
||||
import FmsField from '@/components/fms-field/FmsField.vue'
|
||||
|
||||
/** 构造一个查询条件项(字段 + 配置),供工具栏布局用例复用 */
|
||||
const queryItem = (field) => ({
|
||||
@@ -11,6 +12,12 @@ const queryItem = (field) => ({
|
||||
config: { b_operator: 'like', b_component: 'input' },
|
||||
})
|
||||
|
||||
/** 构造一个区间条件项:字段类型决定两端控件的形态 */
|
||||
const rangeQueryItem = (bType) => ({
|
||||
field: { b_field: 'created', b_type: bType },
|
||||
config: { b_operator: 'between', b_component: bType },
|
||||
})
|
||||
|
||||
describe('fms-module-list components', () => {
|
||||
beforeEach(() => setActivePinia(createPinia()))
|
||||
|
||||
@@ -98,4 +105,71 @@ describe('fms-module-list components', () => {
|
||||
expect(wrapper.find('.filter-row').exists()).toBe(true)
|
||||
wrapper.unmount()
|
||||
})
|
||||
|
||||
it('日期区间拆成两个独立控件加分隔符,控件类型随字段类型走', () => {
|
||||
const dateRange = mount(FmsQueryControl, {
|
||||
props: { item: rangeQueryItem('date'), modelValue: ['', ''] },
|
||||
})
|
||||
const dateFields = dateRange.findAllComponents(FmsField)
|
||||
expect(dateFields.map((field) => field.props('type'))).toEqual(['date', 'date'])
|
||||
// date 只到日,不需要覆盖控件自身的 format
|
||||
expect(dateFields[0].props('controlProps').format).toBeUndefined()
|
||||
expect(dateRange.find('.fms-query-control__separator').exists()).toBe(true)
|
||||
dateRange.unmount()
|
||||
|
||||
const datetimeRange = mount(FmsQueryControl, {
|
||||
props: { item: rangeQueryItem('datetime'), modelValue: ['', ''] },
|
||||
})
|
||||
const datetimeFields = datetimeRange.findAllComponents(FmsField)
|
||||
expect(datetimeFields.map((field) => field.props('type'))).toEqual(['datetime', 'datetime'])
|
||||
// datetime 端点必须到秒:分钟精度下「当天末」表达不出来,结束端默认时间会被归零成 23:59
|
||||
expect(datetimeFields.map((field) => field.props('controlProps').format)).toEqual([
|
||||
'YYYY-MM-DD HH:mm:ss',
|
||||
'YYYY-MM-DD HH:mm:ss',
|
||||
])
|
||||
datetimeRange.unmount()
|
||||
})
|
||||
|
||||
it('日期区间两端各自只受另一端约束,并带当天起 / 当天末的默认时间', () => {
|
||||
const wrapper = mount(FmsQueryControl, {
|
||||
props: { item: rangeQueryItem('date'), modelValue: ['2026-01-10', '2026-01-20'] },
|
||||
})
|
||||
const [start, end] = wrapper.findAllComponents(FmsField)
|
||||
const startProps = start.props('controlProps')
|
||||
const endProps = end.props('controlProps')
|
||||
|
||||
expect(startProps.timeDefault).toBe('start')
|
||||
expect(endProps.timeDefault).toBe('end')
|
||||
|
||||
// 开始端:只禁晚于结束端,往前扩区间不受限
|
||||
expect(startProps.disabledDate(new Date('2026-01-25'))).toBe(true)
|
||||
expect(startProps.disabledDate(new Date('2026-01-05'))).toBe(false)
|
||||
// 结束端:只禁早于开始端,往后扩区间不受限
|
||||
expect(endProps.disabledDate(new Date('2026-01-05'))).toBe(true)
|
||||
expect(endProps.disabledDate(new Date('2026-01-25'))).toBe(false)
|
||||
wrapper.unmount()
|
||||
})
|
||||
|
||||
it('日期区间单端变更只写对应下标,另一端保持', () => {
|
||||
const wrapper = mount(FmsQueryControl, {
|
||||
props: { item: rangeQueryItem('date'), modelValue: ['2026-01-10', '2026-01-20'] },
|
||||
})
|
||||
const [start, end] = wrapper.findAllComponents(FmsField)
|
||||
|
||||
start.vm.$emit('update:modelValue', '2026-01-05')
|
||||
expect(wrapper.emitted('update:modelValue').at(-1)[0]).toEqual(['2026-01-05', '2026-01-20'])
|
||||
|
||||
end.vm.$emit('update:modelValue', '2026-01-31')
|
||||
expect(wrapper.emitted('update:modelValue').at(-1)[0]).toEqual(['2026-01-10', '2026-01-31'])
|
||||
wrapper.unmount()
|
||||
})
|
||||
|
||||
it('数值区间仍是两个输入框加分隔符', () => {
|
||||
const wrapper = mount(FmsQueryControl, {
|
||||
props: { item: rangeQueryItem('number'), modelValue: ['', ''] },
|
||||
})
|
||||
expect(wrapper.findAll('input')).toHaveLength(2)
|
||||
expect(wrapper.find('.fms-query-control__separator').exists()).toBe(true)
|
||||
wrapper.unmount()
|
||||
})
|
||||
})
|
||||
@@ -1,5 +1,9 @@
|
||||
import { describe, expect, it } from 'vitest'
|
||||
import { buildConditionSql, defaultQueryValue } from '@/components/fms-module-common/queryUtils'
|
||||
import {
|
||||
buildConditionSql,
|
||||
defaultQueryValue,
|
||||
sqlLiteral,
|
||||
} from '@/components/fms-module-common/queryUtils'
|
||||
import { formatDateValue, parseOptions } from '@/components/fms-module-common/fieldUtils'
|
||||
import { setMessages, translate } from '@/stores/i18n'
|
||||
|
||||
@@ -54,6 +58,20 @@ describe('fms-module-list query utilities', () => {
|
||||
).toBe("[status] IN (N'a', N'b')")
|
||||
})
|
||||
|
||||
it('日期时间字面量:自带时分秒按原时刻比较,仅日精度才补当天起 / 当天末', () => {
|
||||
const datetimeField = { b_field: 'created', b_type: 'datetime' }
|
||||
const dateField = { b_field: 'created', b_type: 'date' }
|
||||
|
||||
// datetime 值自带时分秒 → 原样保留,结束端也不再被夹到当天末
|
||||
expect(sqlLiteral('2026-01-01 09:30:00', datetimeField)).toBe("N'2026-01-01 09:30:00'")
|
||||
expect(sqlLiteral('2026-01-31 18:00:00', datetimeField, true)).toBe("N'2026-01-31 18:00:00'")
|
||||
// 只有日精度 → 按端点补默认时间
|
||||
expect(sqlLiteral('2026-01-01', datetimeField)).toBe("N'2026-01-01 00:00:00'")
|
||||
expect(sqlLiteral('2026-01-31', datetimeField, true)).toBe("N'2026-01-31 23:59:59'")
|
||||
// date 字段始终截到日,不补时分秒
|
||||
expect(sqlLiteral('2026-01-01 09:30:00', dateField)).toBe("N'2026-01-01'")
|
||||
})
|
||||
|
||||
it('parses options and normalizes defaults', () => {
|
||||
const parsed = parseOptions({ b_options: '{"options":[{"key":"1","name":"启用"},"2"]}' })
|
||||
expect(parsed.options).toEqual([
|
||||
|
||||
@@ -6,7 +6,8 @@
|
||||
* 2. 新增用户时把选中部门补成默认值(只补新增、且表单未带该字段时);
|
||||
* 3. 未选中部门时不加任何固定条件(显示全部用户)。
|
||||
*
|
||||
* 树的增删改与拖拽已在 DeptTreePanel 内,由 fms-tree / utils 的既有用例覆盖,这里不重复。
|
||||
* 部门树的增删改与拖拽逻辑在本页内,但落库前的计算由 @/utils/tree 承担,
|
||||
* 已由 fms-tree / utils 的既有用例覆盖,这里不重复。
|
||||
*/
|
||||
import { describe, it, expect, beforeEach, vi } from 'vitest'
|
||||
import { flushPromises } from '@vue/test-utils'
|
||||
@@ -94,8 +95,8 @@ const passthrough = {
|
||||
}
|
||||
|
||||
async function mountUser() {
|
||||
// DeptTreePanel 必须真实挂载:本页的「选中部门 → 查询条件」依赖它加载完部门后 emit('loaded'),
|
||||
// 若被默认打桩,emit 不会触发,页面拿到的 depts 恒为空。
|
||||
// 部门的加载在本页内完成(loadDepts 直接写 depts),测试只需让 loadDataApi 返回部门行,
|
||||
// 页面即可拿到 depts,不依赖任何子组件 emit。
|
||||
//
|
||||
// 布局容器必须按「Vue 实际推断出的组件名」打桩。
|
||||
// Splitter/SplitterPanel 两个 SFC 的文件名分别是 splitter.vue / panel.vue,
|
||||
@@ -105,7 +106,6 @@ async function mountUser() {
|
||||
stubs: {
|
||||
splitter: passthrough,
|
||||
panel: passthrough,
|
||||
DeptTreePanel: false,
|
||||
},
|
||||
})
|
||||
await flushPromises()
|
||||
|
||||
Reference in new issue
Block a user