test: 单元测试改为直接测试真实代码

This commit is contained in:
2026-08-03 22:21:36 +08:00
parent f71abdd000
commit 6595ed0dfc
9 changed files with 522 additions and 808 deletions
+50 -84
View File
@@ -1,106 +1,72 @@
import { describe, it, expect, vi, beforeEach } from 'vitest'
import { computed, ref } from 'vue'
import { mount } from '@vue/test-utils'
import ElementPlus from 'element-plus'
import { ElMessage } from 'element-plus'
import MyHead from '@/components/MyHead.vue'
import router from '@/router'
import { logout } from '@/api/login'
vi.mock('@/api/login', () => ({
login: vi.fn(),
logout: vi.fn().mockResolvedValue({ code: 200 }),
logout: vi.fn(),
}))
vi.mock('element-plus', () => ({
ElMessage: {
success: vi.fn(),
error: vi.fn(),
warning: vi.fn(),
info: vi.fn(),
},
}))
async function mountAt(path: string) {
await router.push(path)
await router.isReady()
return mount(MyHead, {
shallow: true,
global: {
plugins: [ElementPlus, router],
},
})
}
import { logout } from '@/api/login'
import { ElMessage } from 'element-plus'
describe('MyHead.vue logic', () => {
beforeEach(() => {
describe('MyHead.vue', () => {
beforeEach(async () => {
vi.clearAllMocks()
localStorage.clear()
await router.push('/login')
await router.isReady()
})
describe('route-based computed properties', () => {
it('isLoginRoute is true when path is /login', () => {
const routePath = ref('/login')
const isLoginRoute = computed(() => routePath.value === '/login')
expect(isLoginRoute.value).toBe(true)
})
it('derives route-based computed properties from real route', async () => {
const loginWrapper = await mountAt('/login')
expect(loginWrapper.vm.isLoginRoute).toBe(true)
expect(loginWrapper.vm.showBackButton).toBe(false)
it('isLoginRoute is false for other paths', () => {
const routePath = ref('/welcome')
const isLoginRoute = computed(() => routePath.value === '/login')
expect(isLoginRoute.value).toBe(false)
})
localStorage.setItem('isLoggedIn', 'true')
const studyWrapper = await mountAt('/study')
expect(studyWrapper.vm.isLoginRoute).toBe(false)
expect(studyWrapper.vm.showBackButton).toBe(true)
expect(studyWrapper.vm.pageTitle).toBe('学习任务')
it('showBackButton is true for non-login, non-welcome routes', () => {
const routePath = ref('/study')
const showBackButton = computed(() => routePath.value !== '/login' && routePath.value !== '/welcome')
expect(showBackButton.value).toBe(true)
})
it('showBackButton is false on welcome route', () => {
const routePath = ref('/welcome')
const showBackButton = computed(() => routePath.value !== '/login' && routePath.value !== '/welcome')
expect(showBackButton.value).toBe(false)
})
it('showBackButton is false on login route', () => {
const routePath = ref('/login')
const showBackButton = computed(() => routePath.value !== '/login' && routePath.value !== '/welcome')
expect(showBackButton.value).toBe(false)
})
it('pageTitle is derived from route meta', () => {
const meta = { title: '学习任务' }
const pageTitle = computed(() => meta?.title as string | undefined)
expect(pageTitle.value).toBe('学习任务')
})
it('pageTitle is undefined when no meta title', () => {
const meta = {}
const pageTitle = computed(() => meta?.title as string | undefined)
expect(pageTitle.value).toBeUndefined()
})
const welcomeWrapper = await mountAt('/welcome')
expect(welcomeWrapper.vm.showBackButton).toBe(false)
expect(welcomeWrapper.vm.pageTitle).toBeUndefined()
})
describe('handleLogout logic', () => {
it('clears login state and navigates to login', async () => {
localStorage.setItem('isLoggedIn', 'true')
it('clears login state and navigates to login on logout', async () => {
vi.mocked(logout).mockResolvedValue({ code: 200 } as any)
localStorage.setItem('isLoggedIn', 'true')
const wrapper = await mountAt('/study')
// Simulate handleLogout
try {
await logout()
} catch {
// Backend failure shouldn't block logout
} finally {
localStorage.removeItem('isLoggedIn')
ElMessage.success('已退出登录')
}
await wrapper.vm.handleLogout()
expect(localStorage.getItem('isLoggedIn')).toBeNull()
expect(ElMessage.success).toHaveBeenCalledWith('已退出登录')
})
expect(localStorage.getItem('isLoggedIn')).toBeNull()
expect(ElMessage.success).toHaveBeenCalledWith('已退出登录')
expect(router.currentRoute.value.path).toBe('/login')
})
it('clears login state even when API call fails', async () => {
vi.mocked(logout).mockRejectedValue(new Error('Network error'))
localStorage.setItem('isLoggedIn', 'true')
it('clears login state even when logout API fails', async () => {
vi.mocked(logout).mockRejectedValue(new Error('Network error'))
localStorage.setItem('isLoggedIn', 'true')
const wrapper = await mountAt('/study')
try {
await logout()
} catch {
// Expected
} finally {
localStorage.removeItem('isLoggedIn')
ElMessage.success('已退出登录')
}
await wrapper.vm.handleLogout()
expect(localStorage.getItem('isLoggedIn')).toBeNull()
expect(ElMessage.success).toHaveBeenCalledWith('已退出登录')
})
expect(localStorage.getItem('isLoggedIn')).toBeNull()
expect(ElMessage.success).toHaveBeenCalledWith('已退出登录')
expect(router.currentRoute.value.path).toBe('/login')
})
})