Files
2026-09-23 23:05:01 +08:00

120 lines
4.5 KiB
JavaScript

import { beforeEach, describe, expect, it, vi } from 'vitest'
const loadDataApi = vi.fn()
const saveObjectApi = vi.fn()
const authState = { userInfo: { account: 'u001' } }
vi.mock('@/services/api', () => ({
loadDataApi: (...args) => loadDataApi(...args),
saveObjectApi: (...args) => saveObjectApi(...args),
}))
vi.mock('@/stores/auth', () => ({
useAuthStore: () => authState,
}))
const {
currentUserId,
loadFieldPower,
loadModulePref,
mergeDefaultViewCodes,
removeModulePref,
saveModulePref,
viewCodeDelta,
} = await import('@/components/fms-module-list/useModulePref')
describe('用户模块偏好', () => {
beforeEach(() => {
loadDataApi.mockReset()
saveObjectApi.mockReset()
loadDataApi.mockResolvedValue({ data: [] })
saveObjectApi.mockResolvedValue({})
})
it('取当前登录账号作为偏好用户编码', () => {
expect(currentUserId()).toBe('u001')
})
it('个人默认页签:与系统默认一致时不产生覆盖', () => {
expect(viewCodeDelta({}, {})).toBeNull()
expect(viewCodeDelta({ 状态: '' }, { 状态: 'all' })).toBeNull()
expect(viewCodeDelta({ 状态: 'all' }, { 状态: 'all' })).toBeNull()
expect(viewCodeDelta({ 状态: 'pending' }, { 状态: 'all' })).toEqual({
schemaVersion: 2,
defaultViewCodes: { 状态: 'pending' },
})
})
it('个人默认页签只记与系统默认不同的分组', () => {
expect(viewCodeDelta({ 状态: 'pending', 审核状态: 'audited' }, { 状态: 'all' })).toEqual({
schemaVersion: 2,
defaultViewCodes: { 状态: 'pending', 审核状态: 'audited' },
})
// 该分组系统没有默认:个人选了即产生覆盖
expect(viewCodeDelta({ 状态: 'all' }, {})).toEqual({
schemaVersion: 2,
defaultViewCodes: { 状态: 'all' },
})
})
it('个人默认页签必须仍是本组可用页签,否则回落系统默认', () => {
const allowed = { 状态: new Set(['all', 'pending']) }
expect(
mergeDefaultViewCodes({ 状态: 'all' }, { defaultViewCodes: { 状态: 'pending' } }, allowed),
).toEqual({ 状态: 'pending' })
expect(
mergeDefaultViewCodes({ 状态: 'all' }, { defaultViewCodes: { 状态: 'deleted' } }, allowed),
).toEqual({ 状态: 'all' })
expect(mergeDefaultViewCodes({ 状态: 'all' }, null, allowed)).toEqual({ 状态: 'all' })
})
it('兼容 v1 个人层:单一 defaultViewCode 视作默认组的覆盖', () => {
const allowed = { '': new Set(['all', 'pending']) }
expect(mergeDefaultViewCodes({ '': 'all' }, { defaultViewCode: 'pending' }, allowed)).toEqual({
'': 'pending',
})
expect(mergeDefaultViewCodes({ '': 'all' }, { defaultViewCode: 'deleted' }, allowed)).toEqual({
'': 'all',
})
})
it('读取个人偏好时按用户/模块/schema 类型过滤,解析失败返回 null', async () => {
loadDataApi.mockResolvedValueOnce({ data: [{ b_schema_json: '{ "schemaVersion": 1 }' }] })
await expect(loadModulePref('u001', 'sea')).resolves.toEqual({ schemaVersion: 1 })
expect(loadDataApi.mock.calls[0][0]).toBe('s_user_module_pref')
expect(loadDataApi.mock.calls[0][1]).toContain("b_user_id = N'u001'")
expect(loadDataApi.mock.calls[0][1]).toContain("b_schema_type = N'query'")
loadDataApi.mockResolvedValueOnce({ data: [{ b_schema_json: 'not-json' }] })
await expect(loadModulePref('u001', 'sea')).resolves.toBeNull()
})
it('删除个人层覆盖用于恢复默认', async () => {
await removeModulePref('u001', 'sea')
expect(saveObjectApi.mock.calls[0][0][0].table).toBe('s_user_module_pref')
expect(saveObjectApi.mock.calls[0][0][0].deletes).toEqual([
{ b_user_id: 'u001', b_module_id: 'sea', b_schema_type: 'query' },
])
})
it('保存偏好:首次写入走 inserts,主键冲突时重试 updates', async () => {
await saveModulePref('u001', 'sea', { schemaVersion: 1 }, false)
expect(saveObjectApi.mock.calls[0][0][0].inserts).toHaveLength(1)
saveObjectApi.mockRejectedValueOnce(new Error('duplicate key'))
await saveModulePref('u001', 'sea', { schemaVersion: 1 }, false)
expect(saveObjectApi.mock.calls[2][0][0].updates).toHaveLength(1)
})
it('字段查询权限:b_query = 0 的字段被标记为不可查询', async () => {
loadDataApi.mockResolvedValueOnce({
data: [
{ b_field_id: 'b_no', b_query: 1 },
{ b_field_id: 'b_bz', b_query: 0 },
],
})
const power = await loadFieldPower('u001', 'sea')
expect(power.get('b_no')).toBe(1)
expect(power.get('b_bz')).toBe(0)
})
})