Skip to content

登录组件测试前置工具(loginTestUtils.js)

用于在组件测试前完成真实登录流程,获取有效 token 和用户信息,为后续依赖登录状态的测试提供前置环境。

javascript
import { mount } from "@vue/test-utils";
import Vue from "vue";
import Vuex from "vuex";
import Login from "@/views/login.vue"; // 登录组件
import flushPromises from "flush-promises";
import * as loginApi from "@/api/login"; // 使用真实登录接口
import { setToken } from "@/utils/auth"; // 导入 token 存储工具(mock 或真实)
import MOCK_USER from "./mockuser"; // 登录测试用账号

// 注册 Vuex
Vue.use(Vuex);

/**
 * 创建包含登录状态的 Vuex Store
 * @returns {Vuex.Store} 初始化的 Store 实例
 */
const createStore = () => {
  return new Vuex.Store({
    state: {
      token: "", // 初始为空
      user: null,
    },
    mutations: {
      // 同步更新 token(需与项目中保持一致)
      SET_TOKEN(state, token) {
        state.token = token;
      },
      // 同步更新用户信息
      SET_USER(state, user) {
        state.user = user;
      },
    },
    actions: {
      // 真实登录逻辑(复用项目登录 action)
      Login: async ({ commit }, loginForm) => {
        const response = await loginApi.login(loginForm); // 调用真实登录接口
        const { token, userInfo } = response.data;
        commit("SET_TOKEN", token);
        commit("SET_USER", userInfo);
        return response.data;
      },
    },
  });
};

/**
 * 模拟用户登录流程(真实接口调用)
 * @param {Object} credentials - 登录凭证(默认使用 MOCK_USER)
 * @returns {Object} 登录结果(包含 token、user、store 等)
 * @throws {Error} 登录失败时抛出错误
 */
export async function mockLogin(credentials = MOCK_USER) {
  // 1. 初始化 Store
  const store = createStore();

  // 2. 挂载登录组件
  const loginWrapper = mount(Login, {
    Vue,
    store, // 注入 Store,确保组件内可访问 this.$store
    mocks: {
      $router: { push: jest.fn() }, // 模拟路由跳转(避免真实导航)
    },
  });

  // 3. 输入登录信息
  await loginWrapper
    .find(".login-form .el-form-item:nth-of-type(1) input")
    .setValue(credentials.phoneNumber);
  await loginWrapper
    .find(".login-form .el-form-item:nth-of-type(2) input")
    .setValue(credentials.code);

  // 4. 触发登录按钮点击
  await loginWrapper.find(".login-btn").trigger("click");

  // 5. 等待接口响应与状态更新(最多等待 10 秒)
  let waitCount = 0;
  while (waitCount < 100) {
    // 100 * 100ms = 10s 超时
    await new Promise((resolve) => setTimeout(resolve, 100));
    waitCount++;
  }
  await flushPromises(); // 等待所有异步操作完成
  await loginWrapper.vm.$nextTick(); // 等待 DOM 更新

  // 6. 验证登录结果
  const token = store.state.token;
  if (!token) {
    throw new Error("登录失败:未获取到 token,请检查接口或凭证");
  }

  // 7. 存储 token 供后续请求使用
  setToken(token);

  // 8. 返回登录状态
  return {
    token, // 真实接口返回的 token
    user: store.state.user, // 真实用户信息
    loginWrapper, // 登录组件 Wrapper 实例
    store, // 包含登录状态的 Store 实例
  };
}

核心功能说明:

  1. 真实登录流程:调用项目真实登录接口,模拟用户输入和点击行为,获取有效 token。
  2. 状态管理:通过 Vuex Store 管理登录状态(token 和用户信息),与项目实际逻辑一致。
  3. 前置依赖准备:登录成功后自动存储 token,为后续依赖登录状态的组件测试(如个人中心、订单页)提供环境。
  4. 超时控制:避免接口长时间无响应导致测试卡死,最长等待 10 秒。

使用场景:

在需要登录状态的组件测试文件中引入:

javascript
import { mockLogin } from "./loginTestUtils";

// 在测试用例执行前完成登录
beforeAll(async () => {
  const { token, store } = await mockLogin();
  // 将 store 传入后续组件的挂载参数中
});

Released under the MIT License.