mirror of
https://github.com/bytedance/deer-flow.git
synced 2026-07-28 00:48:07 +00:00
* test(frontend): migrate unit tests to rstest * docs: updates AGENTS.md * test(frontend): fix rstest lint formatting
85 lines
2.3 KiB
TypeScript
85 lines
2.3 KiB
TypeScript
import { beforeEach, describe, expect, it, rs } from "@rstest/core";
|
|
import { QueryClient } from "@tanstack/react-query";
|
|
|
|
rs.mock("@/core/api/fetcher", () => ({
|
|
fetch: rs.fn(),
|
|
}));
|
|
|
|
import { fetch } from "@/core/api/fetcher";
|
|
import { MCPConfigRequestError, loadMCPConfig } from "@/core/mcp/api";
|
|
|
|
const mockedFetch = rs.mocked(fetch);
|
|
|
|
function makeClient() {
|
|
return new QueryClient({
|
|
defaultOptions: {
|
|
queries: {
|
|
retryDelay: 0,
|
|
},
|
|
},
|
|
});
|
|
}
|
|
|
|
describe("useMCPConfig retry policy", () => {
|
|
beforeEach(() => {
|
|
mockedFetch.mockReset();
|
|
});
|
|
|
|
it("does not retry when loadMCPConfig throws MCPConfigRequestError (403)", async () => {
|
|
mockedFetch.mockResolvedValue({
|
|
ok: false,
|
|
status: 403,
|
|
json: async () => ({ detail: "Forbidden" }),
|
|
} as Response);
|
|
|
|
const client = makeClient();
|
|
await expect(
|
|
client.fetchQuery({
|
|
queryKey: ["mcpConfig"],
|
|
queryFn: () => loadMCPConfig(),
|
|
retry: (count, error) =>
|
|
!(error instanceof MCPConfigRequestError) && count < 3,
|
|
}),
|
|
).rejects.toBeInstanceOf(MCPConfigRequestError);
|
|
|
|
expect(mockedFetch).toHaveBeenCalledTimes(1);
|
|
});
|
|
|
|
it("retries up to 3 times on generic errors", async () => {
|
|
mockedFetch.mockRejectedValue(new Error("network down"));
|
|
|
|
const client = makeClient();
|
|
await expect(
|
|
client.fetchQuery({
|
|
queryKey: ["mcpConfig"],
|
|
queryFn: () => loadMCPConfig(),
|
|
retry: (count, error) =>
|
|
!(error instanceof MCPConfigRequestError) && count < 3,
|
|
}),
|
|
).rejects.toThrow("network down");
|
|
|
|
// initial + 3 retries = 4 calls
|
|
expect(mockedFetch).toHaveBeenCalledTimes(4);
|
|
});
|
|
|
|
it("does not retry on MCPConfigRequestError 5xx either (deterministic typed error)", async () => {
|
|
mockedFetch.mockResolvedValue({
|
|
ok: false,
|
|
status: 500,
|
|
json: async () => ({ detail: "Boom" }),
|
|
} as Response);
|
|
|
|
const client = makeClient();
|
|
await expect(
|
|
client.fetchQuery({
|
|
queryKey: ["mcpConfig"],
|
|
queryFn: () => loadMCPConfig(),
|
|
retry: (count, error) =>
|
|
!(error instanceof MCPConfigRequestError) && count < 3,
|
|
}),
|
|
).rejects.toBeInstanceOf(MCPConfigRequestError);
|
|
|
|
expect(mockedFetch).toHaveBeenCalledTimes(1);
|
|
});
|
|
});
|