20260819173221

This commit is contained in:
oneao committed 2026-08-19 17:32:25 +08:00
1 parent 1ffc8e1ac9
commit a0a4273f4c
326 files changed
+301646 -2314

No files matched your search

@@ -0,0 +1,200 @@
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'
// 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.locale).toBe('zh-CN')
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 / toggleLocale', () => {
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)
app.toggleLocale()
expect(app.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"')
})
})