Files
lpt-fe/src/__tests__/integration/login-flow.spec.ts
T

72 lines
2.9 KiB
TypeScript

import { describe, it, expect, vi, beforeEach } from 'vitest'
import { flushPromises, mount } from '@vue/test-utils'
import ElementPlus, { ElMessage } from 'element-plus'
import Login from '@/components/Login.vue'
import router from '@/router'
import { login } from '@/api/login'
vi.mock('@/api/login', () => ({
login: vi.fn(),
logout: vi.fn(),
}))
/**
* 交互式集成测试:真实挂载 Login,通过 setValue / trigger('click') 模拟用户行为,
* 断言提交链路(凭证传递、成功/失败分支、localStorage 与路由结果)。
*
* 注意:jsdom 下 Element Plus 的 callback 式表单校验不可靠(空表单也可能判有效),
* “空账号被校验拦截”这类行为由 e2e/login.spec 在真实浏览器中覆盖,此处不重复断言。
*/
describe('Login 交互流程(集成)', () => {
beforeEach(async () => {
vi.clearAllMocks()
localStorage.clear()
await router.push('/login')
await router.isReady()
})
const mountLogin = async () => {
const wrapper = mount(Login, {
global: { plugins: [ElementPlus, router] },
})
await flushPromises()
return wrapper
}
const findSubmitButton = (wrapper: ReturnType<typeof mount> extends Promise<infer T> ? T : never) =>
wrapper.findAll('button').find((b) => b.text().includes('进入系统'))!
it('填写账号密码后点击“进入系统”,提交凭证并跳转 /welcome', async () => {
vi.mocked(login).mockResolvedValue({ code: 200, message: '登录成功' } as any)
const wrapper = await mountLogin()
await wrapper.find('input[placeholder="请输入账号"]').setValue('admin')
await wrapper.find('input[placeholder="请输入密码"]').setValue('123456')
await findSubmitButton(wrapper).trigger('click')
// /welcome 是懒加载路由,动态 import 需要宏任务,用 waitFor 轮询等待到达
await vi.waitFor(() => expect(router.currentRoute.value.path).toBe('/welcome'))
expect(login).toHaveBeenCalledWith('admin', '123456')
expect(localStorage.getItem('isLoggedIn')).toBe('true')
expect(ElMessage.success).toHaveBeenCalledWith('登录成功')
wrapper.unmount()
})
it('后端返回失败时提示错误、不写登录标记、不跳转', async () => {
vi.mocked(login).mockResolvedValue({ code: 500, message: '账号或密码错误' } as any)
const wrapper = await mountLogin()
await wrapper.find('input[placeholder="请输入账号"]').setValue('admin')
await wrapper.find('input[placeholder="请输入密码"]').setValue('wrong-pass')
await findSubmitButton(wrapper).trigger('click')
await flushPromises()
await flushPromises()
expect(login).toHaveBeenCalledWith('admin', 'wrong-pass')
expect(ElMessage.error).toHaveBeenCalledWith('账号或密码错误')
expect(localStorage.getItem('isLoggedIn')).toBeNull()
expect(router.currentRoute.value.path).toBe('/login')
wrapper.unmount()
})
})