3ccd1262f9
基于 Vitest 搭建测试基础设施,覆盖后端纯函数、API 路由、 前端 hooks、UI 组件和页面级集成测试。
92 lines
2.4 KiB
TypeScript
92 lines
2.4 KiB
TypeScript
import { describe, it, expect, vi, beforeEach, afterEach } from "vitest";
|
|
import { renderHook, waitFor, act } from "@testing-library/react";
|
|
|
|
let esInstances: { onmessage?: (e: MessageEvent) => void; onerror?: () => void; onopen?: () => void; close: ReturnType<typeof vi.fn> }[] = [];
|
|
|
|
class MockEventSource {
|
|
onmessage: ((e: MessageEvent) => void) | null = null;
|
|
onerror: (() => void) | null = null;
|
|
onopen: (() => void) | null = null;
|
|
close = vi.fn();
|
|
|
|
constructor(_url: string) {
|
|
esInstances.push(this);
|
|
}
|
|
}
|
|
|
|
vi.stubGlobal("EventSource", MockEventSource);
|
|
|
|
vi.mock("swr", () => ({
|
|
default: vi.fn().mockReturnValue({
|
|
data: {
|
|
roomId: "ROOM01",
|
|
userCount: 2,
|
|
match: null,
|
|
matchType: null,
|
|
matchLikes: 0,
|
|
runnerUps: [],
|
|
likeCounts: {},
|
|
swipeCounts: {},
|
|
restaurants: [],
|
|
creatorId: "user-1",
|
|
locked: false,
|
|
users: ["user-1", "user-2"],
|
|
userProfiles: {},
|
|
scene: "eat",
|
|
},
|
|
error: null,
|
|
isLoading: false,
|
|
mutate: vi.fn(),
|
|
}),
|
|
}));
|
|
|
|
import { useRoomPolling } from "./useRoomPolling";
|
|
|
|
beforeEach(() => {
|
|
esInstances = [];
|
|
});
|
|
|
|
afterEach(() => {
|
|
vi.clearAllMocks();
|
|
});
|
|
|
|
describe("useRoomPolling", () => {
|
|
it("returns room data from SWR", () => {
|
|
const { result } = renderHook(() => useRoomPolling("ROOM01"));
|
|
|
|
expect(result.current.userCount).toBe(2);
|
|
expect(result.current.users).toEqual(["user-1", "user-2"]);
|
|
expect(result.current.scene).toBe("eat");
|
|
});
|
|
|
|
it("creates EventSource connection", () => {
|
|
renderHook(() => useRoomPolling("ROOM01"));
|
|
expect(esInstances.length).toBeGreaterThan(0);
|
|
});
|
|
|
|
it("returns defaults when no roomId", () => {
|
|
const { result } = renderHook(() => useRoomPolling(undefined));
|
|
expect(result.current.userCount).toBe(2);
|
|
});
|
|
|
|
it("returns notFound from error state", async () => {
|
|
const useSWR = vi.mocked((await import("swr")).default);
|
|
useSWR.mockReturnValue({
|
|
data: undefined,
|
|
error: new Error("NOT_FOUND"),
|
|
isLoading: false,
|
|
mutate: vi.fn(),
|
|
} as never);
|
|
|
|
const { result } = renderHook(() => useRoomPolling("ROOM01"));
|
|
expect(result.current.notFound).toBe(true);
|
|
});
|
|
|
|
it("cleans up EventSource on unmount", () => {
|
|
const { unmount } = renderHook(() => useRoomPolling("ROOM01"));
|
|
const es = esInstances[esInstances.length - 1];
|
|
unmount();
|
|
expect(es.close).toHaveBeenCalled();
|
|
});
|
|
});
|