test(web): 薄 Web 面加 RTL 组件测试 —— 补最大覆盖缺口 (P1)
完成度审计:web 端几乎零覆盖(仅3个 api 纯逻辑用例、无任何组件测试)——三前端里 最薄。补上 RTL 基建 + 入口流组件测试。 - 加 @testing-library/react+jest-dom+user-event,src/test/setup.ts, vitest setupFiles 接入。 - AuthPage.test.tsx(5 例,mock api 层):登录/注册态切换(名字字段显隐)、 邮箱密码空时按钮禁用、登录成功回调 onAuthed 且带对参数、登录失败显示后端 错误文案不回调、注册态走 authRegister 带名字。 web 测试 3→8。CI web 矩阵已跑 npm test,自动纳入关卡。 tsc + 三前端(desktop 68/admin 41/web 8)全绿。 Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,74 @@
|
||||
import { describe, it, expect, vi, beforeEach } from "vitest";
|
||||
import { render, screen, waitFor } from "@testing-library/react";
|
||||
import userEvent from "@testing-library/user-event";
|
||||
import { AuthPage } from "./AuthPage";
|
||||
|
||||
// 隔离 api 层:只测组件行为(态切换/校验/提交/报错),不打真网络。
|
||||
vi.mock("../api", () => ({
|
||||
authLogin: vi.fn(),
|
||||
authRegister: vi.fn(),
|
||||
}));
|
||||
import { authLogin, authRegister } from "../api";
|
||||
|
||||
describe("AuthPage", () => {
|
||||
beforeEach(() => vi.clearAllMocks());
|
||||
|
||||
it("默认登录态:无名字字段,切到注册后出现", async () => {
|
||||
render(<AuthPage onAuthed={vi.fn()} />);
|
||||
// 登录态无「名字」标签
|
||||
expect(screen.queryByText(/名字/)).toBeNull();
|
||||
await userEvent.click(screen.getByText(/还没有账户/));
|
||||
expect(screen.getByText(/名字/)).toBeInTheDocument();
|
||||
// 切回登录,名字字段消失
|
||||
await userEvent.click(screen.getByText(/已有账户/));
|
||||
expect(screen.queryByText(/名字/)).toBeNull();
|
||||
});
|
||||
|
||||
it("邮箱或密码为空时提交按钮禁用", async () => {
|
||||
render(<AuthPage onAuthed={vi.fn()} />);
|
||||
const btn = screen.getByRole("button", { name: "登录" });
|
||||
expect(btn).toBeDisabled();
|
||||
await userEvent.type(screen.getByPlaceholderText(/you@example/), "a@b.com");
|
||||
expect(btn).toBeDisabled(); // 还差密码
|
||||
await userEvent.type(screen.getByPlaceholderText("••••••"), "pass123");
|
||||
expect(btn).toBeEnabled();
|
||||
});
|
||||
|
||||
it("登录成功回调 onAuthed", async () => {
|
||||
const user = { id: "u1", email: "a@b.com" };
|
||||
(authLogin as ReturnType<typeof vi.fn>).mockResolvedValue(user);
|
||||
const onAuthed = vi.fn();
|
||||
render(<AuthPage onAuthed={onAuthed} />);
|
||||
await userEvent.type(screen.getByPlaceholderText(/you@example/), "a@b.com");
|
||||
await userEvent.type(screen.getByPlaceholderText("••••••"), "pass123");
|
||||
await userEvent.click(screen.getByRole("button", { name: "登录" }));
|
||||
await waitFor(() => expect(onAuthed).toHaveBeenCalledWith(user));
|
||||
expect(authLogin).toHaveBeenCalledWith("a@b.com", "pass123");
|
||||
expect(authRegister).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it("登录失败显示后端错误文案,不回调", async () => {
|
||||
(authLogin as ReturnType<typeof vi.fn>).mockRejectedValue(new Error("邮箱或密码不正确"));
|
||||
const onAuthed = vi.fn();
|
||||
render(<AuthPage onAuthed={onAuthed} />);
|
||||
await userEvent.type(screen.getByPlaceholderText(/you@example/), "a@b.com");
|
||||
await userEvent.type(screen.getByPlaceholderText("••••••"), "wrong");
|
||||
await userEvent.click(screen.getByRole("button", { name: "登录" }));
|
||||
await waitFor(() => expect(screen.getByText("邮箱或密码不正确")).toBeInTheDocument());
|
||||
expect(onAuthed).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it("注册态走 authRegister 并带上名字", async () => {
|
||||
const user = { id: "u2", email: "c@d.com", name: "小明" };
|
||||
(authRegister as ReturnType<typeof vi.fn>).mockResolvedValue(user);
|
||||
const onAuthed = vi.fn();
|
||||
render(<AuthPage onAuthed={onAuthed} />);
|
||||
await userEvent.click(screen.getByText(/还没有账户/));
|
||||
await userEvent.type(screen.getByPlaceholderText(/怎么称呼你/), "小明");
|
||||
await userEvent.type(screen.getByPlaceholderText(/you@example/), "c@d.com");
|
||||
await userEvent.type(screen.getByPlaceholderText("••••••"), "pass123");
|
||||
await userEvent.click(screen.getByRole("button", { name: "注册" }));
|
||||
await waitFor(() => expect(onAuthed).toHaveBeenCalledWith(user));
|
||||
expect(authRegister).toHaveBeenCalledWith("c@d.com", "pass123", "小明");
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,2 @@
|
||||
// Vitest 全局初始化:jest-dom 断言(toBeInTheDocument 等)。
|
||||
import "@testing-library/jest-dom/vitest";
|
||||
Reference in New Issue
Block a user