test: 添加完整测试套件(52 个文件,326 个用例)

基于 Vitest 搭建测试基础设施,覆盖后端纯函数、API 路由、
前端 hooks、UI 组件和页面级集成测试。
This commit is contained in:
2026-02-28 20:19:14 +08:00
parent 11eeec868e
commit 3ccd1262f9
59 changed files with 8131 additions and 3 deletions
+74
View File
@@ -0,0 +1,74 @@
import { describe, it, expect, vi, beforeEach } from "vitest";
import { createRequest, parseJsonResponse } from "@/__tests__/helpers/api-test-utils";
vi.mock("@/lib/prisma", () => ({ prisma: {} }));
vi.mock("@/lib/amap", () => ({
requireAmapApiKey: vi.fn().mockReturnValue("test-key"),
}));
const mockFetch = vi.fn();
vi.stubGlobal("fetch", mockFetch);
import { GET } from "./route";
const mockCtx = { params: Promise.resolve({}) };
beforeEach(() => {
vi.clearAllMocks();
});
describe("GET /api/location/search", () => {
it("returns search results", async () => {
mockFetch.mockResolvedValue({
json: () =>
Promise.resolve({
status: "1",
pois: [
{
id: "poi-1",
name: "星巴克",
address: "南京路1号",
location: "121.4,31.2",
business: { rating: "4.5", cost: "40" },
},
],
}),
});
const req = createRequest("/api/location/search?keywords=星巴克");
const res = await GET(req, mockCtx);
const { status, data } = await parseJsonResponse(res);
expect(status).toBe(200);
expect(data).toHaveLength(1);
expect(data[0].name).toBe("星巴克");
expect(data[0].lat).toBe(31.2);
expect(data[0].lng).toBe(121.4);
});
it("returns empty when no results", async () => {
mockFetch.mockResolvedValue({
json: () => Promise.resolve({ status: "1", pois: [] }),
});
const req = createRequest("/api/location/search?keywords=不存在的地方");
const res = await GET(req, mockCtx);
const { data } = await parseJsonResponse(res);
expect(data).toEqual([]);
});
it("returns 400 when keywords missing", async () => {
const req = createRequest("/api/location/search");
const res = await GET(req, mockCtx);
expect(res.status).toBe(400);
});
it("returns 503 when API unavailable", async () => {
mockFetch.mockRejectedValue(new Error("network error"));
const req = createRequest("/api/location/search?keywords=test");
const res = await GET(req, mockCtx);
expect(res.status).toBe(503);
});
});