Files
2026-09-21 23:13:14 +08:00

218 lines
7.2 KiB
JavaScript
Raw Permalink 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, it, expect, beforeEach, vi } from 'vitest'
import { nextTick } from 'vue'
import { createTestPinia } from '../helpers/app.js'
import { useAppStore } from '@/stores/app'
import { useAuthStore } from '@/stores/auth'
import { useI18nStore } from '@/stores/i18n'
// app store 的 initThemeSync 依赖 theme 模块操作 documentElement,jest 环境可安全执行
vi.mock('@/theme/index', () => ({
applyPrimaryColor: vi.fn(),
applyDarkMode: vi.fn(),
}))
beforeEach(() => {
localStorage.clear()
sessionStorage.clear()
vi.clearAllMocks()
})
describe('app store · 主题与布局', () => {
it('初始状态:暗色关、默认主色、侧栏展开、工作台页签固定', () => {
createTestPinia()
const app = useAppStore()
expect(app.darkMode).toBe(false)
expect(app.sidebarCollapsed).toBe(false)
expect(app.visitedTabs).toHaveLength(1)
expect(app.visitedTabs[0]).toMatchObject({ key: '/dashboard', closable: false })
})
it('setDark / toggleDark 切换暗色', () => {
createTestPinia()
const app = useAppStore()
app.setDark(true)
expect(app.darkMode).toBe(true)
app.toggleDark()
expect(app.darkMode).toBe(false)
})
it('setPrimary / toggleSidebar / setSidebar', () => {
createTestPinia()
const app = useAppStore()
app.setPrimary('#123456')
expect(app.primaryColor).toBe('#123456')
app.toggleSidebar()
expect(app.sidebarCollapsed).toBe(true)
app.setSidebar(false)
expect(app.sidebarCollapsed).toBe(false)
})
it('toggleContentMaximize:切换内容最大化状态', () => {
createTestPinia()
const app = useAppStore()
expect(app.contentMaximized).toBe(false)
app.toggleContentMaximize()
expect(app.contentMaximized).toBe(true)
app.toggleContentMaximize()
expect(app.contentMaximized).toBe(false)
})
it('i18n store 管理界面语言切换', () => {
createTestPinia()
const i18n = useI18nStore()
i18n.setLocale('zh-CN')
expect(i18n.locale).toBe('zh-CN')
i18n.toggleLocale()
expect(i18n.locale).toBe('en-US')
})
})
describe('app store · 页签管理', () => {
function seedTabs() {
const app = useAppStore()
app.addVisitedTab({ key: '/a', label: 'A', closable: true, name: 'A' })
app.addVisitedTab({ key: '/b', label: 'B', closable: true, name: 'B' })
app.addVisitedTab({ key: '/c', label: 'C', closable: true, name: 'C' })
app.refreshRoute('/a')
app.refreshRoute('/a')
app.refreshRoute('/b')
return app
}
it('addVisitedTab 去重:重复 key 不重复添加', () => {
createTestPinia()
const app = seedTabs()
app.addVisitedTab({ key: '/a', label: 'A2', closable: true, name: 'A' })
expect(app.visitedTabs.filter((t) => t.key === '/a')).toHaveLength(1)
})
it('cachedViews:按 visitedTabs 去重取组件名', () => {
createTestPinia()
const app = seedTabs()
app.addVisitedTab({ key: '/a', label: 'A', closable: true, name: 'A' })
expect(app.cachedViews).toEqual(['Dashboard', 'A', 'B', 'C'])
})
it('removeVisitedTab:移除页签并清理该页刷新计数', () => {
createTestPinia()
const app = seedTabs()
app.removeVisitedTab('/a')
expect(app.visitedTabs.some((t) => t.key === '/a')).toBe(false)
expect(app.routeRefreshKeys['/a']).toBeUndefined()
})
it('closeOthers:保留工作台与指定页签', () => {
createTestPinia()
const app = seedTabs()
app.closeOthers('/b')
expect(app.visitedTabs.map((t) => t.key)).toEqual(['/dashboard', '/b'])
expect(app.routeRefreshKeys['/a']).toBeUndefined()
})
it('closeLeft:保留工作台、指定页签及其右侧', () => {
createTestPinia()
const app = seedTabs()
app.closeLeft('/b')
expect(app.visitedTabs.map((t) => t.key)).toEqual(['/dashboard', '/b', '/c'])
})
it('closeLeft:指定工作台时不裁剪', () => {
createTestPinia()
const app = seedTabs()
app.closeLeft('/dashboard')
expect(app.visitedTabs).toHaveLength(4)
})
it('closeRight:保留指定页签及其左侧', () => {
createTestPinia()
const app = seedTabs()
app.closeRight('/b')
expect(app.visitedTabs.map((t) => t.key)).toEqual(['/dashboard', '/a', '/b'])
})
it('closeAll:仅保留工作台并清理全部刷新计数', () => {
createTestPinia()
const app = seedTabs()
app.closeAll()
expect(app.visitedTabs.map((t) => t.key)).toEqual(['/dashboard'])
expect(Object.keys(app.routeRefreshKeys)).toHaveLength(0)
})
it('refreshRoute / getRouteRefreshKey:计数递增与读取', () => {
createTestPinia()
const app = useAppStore()
expect(app.getRouteRefreshKey('/x')).toBe(0)
app.refreshRoute('/x')
app.refreshRoute('/x')
expect(app.getRouteRefreshKey('/x')).toBe(2)
})
})
describe('auth store · 用户信息回显(userInfo)', () => {
it('saveLastLogin 写入机构与账号', () => {
createTestPinia()
const auth = useAuthStore()
auth.saveLastLogin('ORG1', 'admin')
expect(auth.userInfo).toEqual({ orgId: 'ORG1', account: 'admin' })
})
it('持久化 key 为 fms-user(localStorage)', async () => {
createTestPinia()
const auth = useAuthStore()
auth.saveLastLogin('ORG9', 'u9')
// persist 插件通过 $subscribe 同步写 storage,冲刷微任务兜底
await nextTick()
expect(localStorage.getItem('fms-user')).toContain('ORG9')
expect(localStorage.getItem('fms-user')).toContain('"account":"u9"')
})
})
describe('auth store', () => {
it('setSession:token/orgid/user 三种字段形态兼容', () => {
createTestPinia()
const auth = useAuthStore()
auth.setSession(
{ access_token: 'at', orgid: 'O1', user_info: { id: 7 } },
'O_FALLBACK',
)
expect(auth.loginInfo.token).toBe('at')
expect(auth.userInfo.orgId).toBe('O1')
expect(auth.loginInfo.user).toEqual({ id: 7 })
expect(auth.isAuthenticated).toBe(true)
})
it('setSession:缺失字段时回退到 organizationId 参数', () => {
createTestPinia()
const auth = useAuthStore()
auth.setSession({ token: 't' }, 'ORG-FB')
expect(auth.userInfo.orgId).toBe('ORG-FB')
})
it('clearSession:清会话凭证,保留 userInfo 回显数据', () => {
createTestPinia()
const auth = useAuthStore()
auth.setSession({ token: 't', user: { id: 1 } }, 'ORG')
auth.saveLastLogin('ORG', 'admin')
auth.clearSession()
expect(auth.loginInfo.token).toBe('')
expect(auth.loginInfo.user).toBe(null)
expect(auth.isAuthenticated).toBe(false)
// userInfo 是登录页回显数据,不属于会话,退出登录后保留
expect(auth.userInfo).toEqual({ orgId: 'ORG', account: 'admin' })
})
it('持久化:会话写 sessionStorage(fms-login)、回显写 localStorage(fms-user)', async () => {
createTestPinia()
const auth = useAuthStore()
auth.setSession({ token: 't', user: { id: 1 } }, 'ORG')
auth.saveLastLogin('ORG', 'admin')
await nextTick()
expect(sessionStorage.getItem('fms-login')).toContain('"token":"t"')
expect(localStorage.getItem('fms-user')).toContain('"orgId":"ORG"')
// 会话与回显物理隔离:清会话不影响回显 key
auth.clearSession()
await nextTick()
expect(localStorage.getItem('fms-user')).toContain('"orgId":"ORG"')
})
})