Files
workspace/code/fms/fms-vue/tests/unit/module-list-utils.spec.js
T
2026-09-16 17:27:04 +08:00

110 lines
4.5 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import { describe, expect, it } from 'vitest'
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'
/** buildConditionSql 需要按字段名查到字段定义,b_type 决定字面量形式(数字裸写 / 文本 N'...') */
function fieldMapOf(...fields) {
return new Map(fields.map((field) => [field.b_field, field]))
}
function item(over = {}) {
return {
field: { b_field: 'amount', b_type: 'money', b_options: '' },
config: { b_operator: 'eq', b_component: 'number' },
...over,
}
}
describe('fms-module-list query utilities', () => {
it('uses a standalone translation catalog and fallback text', () => {
setMessages({ 'common.search': '查询' }, 'zh-CN')
expect(translate('common.search', '搜索')).toBe('查询')
expect(translate('common.reset', '重置')).toBe('重置')
setMessages({})
})
it('builds numeric and escaped text conditions', () => {
expect(
buildConditionSql(
{ field: 'amount', operator: 'eq', value: 12.5 },
fieldMapOf({ b_field: 'amount', b_type: 'money' }),
),
).toBe('[amount] = 12.5')
expect(
buildConditionSql(
{ field: 'name', operator: 'like', value: "O'Reilly" },
fieldMapOf({ b_field: 'name', b_type: 'input' }),
),
).toBe("[name] LIKE N'%O''Reilly%'")
})
it('builds range and IN conditions while ignoring empty values', () => {
expect(
buildConditionSql(
{ field: 'created', operator: 'between', value: ['2026-01-01', '2026-01-31'] },
fieldMapOf({ b_field: 'created', b_type: 'date' }),
),
).toBe("[created] BETWEEN N'2026-01-01' AND N'2026-01-31'")
expect(
buildConditionSql(
{ field: 'status', operator: 'in', value: ['a', '', 'b'] },
fieldMapOf({ b_field: 'status', b_type: 'input' }),
),
).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([
{ key: '1', name: '启用', value: '1', label: '启用' },
{ value: '2', label: '2' },
])
expect(
defaultQueryValue(
item({
field: { b_field: 'status', b_type: 'input' },
config: { b_operator: 'in', b_default_value: 'a,b' },
}),
),
).toEqual(['a', 'b'])
})
it('formats ISO dates consistently', () => {
expect(formatDateValue('2026-08-01T12:34:56Z')).toMatch(/^2026-08-01/)
expect(formatDateValue(null)).toBe('')
})
/**
* 时间契约:后端统一输出「显示格式」的墙钟串(见后端 DbUtils.normalizeJdbcValue,
* 与旧项目读取 ResultSet 时格式化的做法一致):
* date → "2026-09-15",datetime → "2026-09-15 21:16:47",即拿即显示、不做时区换算。
* 展示层对标准输入应为透传;仅非标准输入(数字时间戳等)走 Date 兜底。
*/
it('passes through display-format strings without timezone math', () => {
expect(formatDateValue('2026-09-15 21:16:47', true)).toBe('2026-09-15 21:16:47')
expect(formatDateValue('2026-09-15 21:16:47', false)).toBe('2026-09-15')
expect(formatDateValue('2026-09-15', false)).toBe('2026-09-15')
// 非日期开头的输入(数字时间戳等)仍走 Date 兜底,按本地时间格式化
expect(formatDateValue(1789471007000, true)).toMatch(/^\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}$/)
})
})