142 lines
4.1 KiB
TypeScript
142 lines
4.1 KiB
TypeScript
/**
|
|
* useContentData Hook 单元测试
|
|
*/
|
|
|
|
import { describe, it, expect, vi, beforeEach } from "vitest";
|
|
import { renderHook, waitFor } from "@testing-library/react";
|
|
import { SWRConfig } from "swr";
|
|
import type { ReactNode } from "react";
|
|
|
|
vi.mock("@/lib/api/client", () => ({
|
|
fetchWithAuth: vi.fn(),
|
|
}));
|
|
|
|
import { fetchWithAuth } from "@/lib/api/client";
|
|
const mockFetchWithAuth = vi.mocked(fetchWithAuth);
|
|
|
|
import { useContentData } from "@/lib/hooks/use-content-data";
|
|
import type { Content } from "@/lib/api/contents";
|
|
import type { KnowledgeBase } from "@/lib/api/knowledge";
|
|
|
|
const noRetryOptions = { shouldRetryOnError: false };
|
|
|
|
function createWrapper() {
|
|
return ({ children }: { children: ReactNode }) =>
|
|
SWRConfig({ value: { provider: () => new Map() }, children });
|
|
}
|
|
|
|
describe("useContentData", () => {
|
|
beforeEach(() => {
|
|
vi.clearAllMocks();
|
|
});
|
|
|
|
const mockContents: Content[] = [
|
|
{
|
|
id: "content-1",
|
|
title: "测试内容",
|
|
body: "内容正文",
|
|
content_type: "article",
|
|
status: "draft",
|
|
author_id: "user-1",
|
|
tags: ["test"],
|
|
created_at: "2024-01-01",
|
|
updated_at: "2024-01-01",
|
|
},
|
|
];
|
|
|
|
const mockKnowledgeBases: KnowledgeBase[] = [
|
|
{
|
|
id: "kb-1",
|
|
name: "测试知识库",
|
|
type: "enterprise",
|
|
document_count: 5,
|
|
status: "ready",
|
|
created_at: "2024-01-01",
|
|
},
|
|
];
|
|
|
|
it("应同时获取内容列表和知识库列表", async () => {
|
|
mockFetchWithAuth.mockImplementation((url: string) => {
|
|
if (url.includes("/api/v1/contents/")) return Promise.resolve(mockContents);
|
|
if (url.includes("/api/v1/knowledge/bases")) return Promise.resolve(mockKnowledgeBases);
|
|
return Promise.resolve([]);
|
|
});
|
|
|
|
const { result } = renderHook(
|
|
() => useContentData({ swrOptions: noRetryOptions }),
|
|
{ wrapper: createWrapper() }
|
|
);
|
|
|
|
await waitFor(() => {
|
|
expect(result.current.isLoading).toBe(false);
|
|
});
|
|
|
|
expect(result.current.contents).toEqual(mockContents);
|
|
expect(result.current.knowledgeBases).toEqual(mockKnowledgeBases);
|
|
});
|
|
|
|
it("应正确暴露 isLoading 状态", async () => {
|
|
mockFetchWithAuth.mockImplementation((url: string) => {
|
|
if (url.includes("/api/v1/contents/")) return Promise.resolve(mockContents);
|
|
if (url.includes("/api/v1/knowledge/bases")) return Promise.resolve(mockKnowledgeBases);
|
|
return Promise.resolve([]);
|
|
});
|
|
|
|
const { result } = renderHook(
|
|
() => useContentData({ swrOptions: noRetryOptions }),
|
|
{ wrapper: createWrapper() }
|
|
);
|
|
|
|
await waitFor(() => {
|
|
expect(result.current.isLoading).toBe(false);
|
|
});
|
|
});
|
|
|
|
it("应正确暴露 error 状态", async () => {
|
|
mockFetchWithAuth.mockRejectedValue(new Error("数据加载失败"));
|
|
|
|
const { result } = renderHook(
|
|
() => useContentData({ swrOptions: noRetryOptions }),
|
|
{ wrapper: createWrapper() }
|
|
);
|
|
|
|
await waitFor(() => {
|
|
expect(result.current.error).toBeDefined();
|
|
expect(result.current.error?.message).toBe("数据加载失败");
|
|
});
|
|
});
|
|
|
|
it("应提供 refresh 方法", async () => {
|
|
mockFetchWithAuth.mockImplementation((url: string) => {
|
|
if (url.includes("/api/v1/contents/")) return Promise.resolve(mockContents);
|
|
if (url.includes("/api/v1/knowledge/bases")) return Promise.resolve(mockKnowledgeBases);
|
|
return Promise.resolve([]);
|
|
});
|
|
|
|
const { result } = renderHook(
|
|
() => useContentData({ swrOptions: noRetryOptions }),
|
|
{ wrapper: createWrapper() }
|
|
);
|
|
|
|
await waitFor(() => {
|
|
expect(result.current.isLoading).toBe(false);
|
|
});
|
|
|
|
expect(typeof result.current.refreshContents).toBe("function");
|
|
expect(typeof result.current.refreshKnowledgeBases).toBe("function");
|
|
});
|
|
|
|
it("数据加载失败时 error 应包含错误信息", async () => {
|
|
mockFetchWithAuth.mockRejectedValue(new Error("网络异常"));
|
|
|
|
const { result } = renderHook(
|
|
() => useContentData({ swrOptions: noRetryOptions }),
|
|
{ wrapper: createWrapper() }
|
|
);
|
|
|
|
await waitFor(() => {
|
|
expect(result.current.error?.message).toBe("网络异常");
|
|
});
|
|
});
|
|
});
|