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 extends Promise ? 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() }) })