test(deepinfra): simplify catalog test fixtures (#143680)

This commit is contained in:
Peter Steinberger 2026-09-09 21:40:16 -07:00 • committed by GitHub
parent 3ffdc1bfcc
commit 731acb8053
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 29 additions and 90 deletions

View file

@ -40,21 +40,13 @@ function makeAgentModelEntry(id = "profile/live-model") {
};
}
function jsonResponse(payload: unknown, init: ResponseInit = {}): Response {
return new Response(JSON.stringify(payload), {
status: 200,
headers: { "Content-Type": "application/json" },
...init,
});
}
function mockDiscoveryFetch(id = "profile/live-model") {
return vi.fn(async (url: string) => {
if (url === DEEPINFRA_MODELS_URL) {
return jsonResponse({ data: [makeAgentModelEntry(id)] });
return Response.json({ data: [makeAgentModelEntry(id)] });
}
expect(url).toBe("https://api.deepinfra.com/models/list");
return jsonResponse([
return Response.json([
{
model_name: id,
pricing: {
@ -98,7 +90,7 @@ describe("deepinfra capability registration", () => {
const mockFetch = vi.fn(async (url: string) => {
const metadata = url === DEEPINFRA_MODELS_URL;
if (scenario === "empty" && metadata) {
return jsonResponse({ data: [] });
return Response.json({ data: [] });
}
if (
(scenario === "metadata" && metadata) ||

View file

@ -43,14 +43,6 @@ function makeAgentModelEntry(overrides: Record<string, unknown> = {}) {
};
}
function jsonResponse(payload: unknown, init: ResponseInit = {}): Response {
return new Response(JSON.stringify(payload), {
status: 200,
headers: { "Content-Type": "application/json" },
...init,
});
}
function expectedStaticChatCatalog() {
// Mirror the production mapping (provider-catalog.ts / discoverDeepInfraModels)
// so per-family compat tagging (e.g. thinkingFormat) stays in one place.
@ -82,7 +74,7 @@ afterEach(() => {
function mockProjectionFetch(projection: () => Promise<Response> | Response) {
return vi.fn(async (url: string) => {
if (url === "https://api.deepinfra.com/models/list") {
return jsonResponse([
return Response.json([
{
model_name: "fixture/native-only",
pricing: { type: "tokens", cents_per_input_token: 0.0002, cents_per_output_token: 0.001 },
@ -146,7 +138,7 @@ describe("DeepInfra pre-auth discovery", () => {
{ key: " ", live: false },
{ key: undefined, live: false },
])("discovers only with a configured environment key: $live", async ({ key, live }) => {
const mockFetch = mockProjectionFetch(() => jsonResponse({ data: [makeAgentModelEntry()] }));
const mockFetch = mockProjectionFetch(() => Response.json({ data: [makeAgentModelEntry()] }));
await withFetchPathTest(mockFetch, {}, async () => {
expect((await discoverDeepInfraSurfaces({ env: { DEEPINFRA_API_KEY: key } })).live).toBe(
live,
@ -160,7 +152,7 @@ describe("DeepInfra pre-auth discovery", () => {
it("discovers with a saved profile when the environment has no key", async () => {
isProviderApiKeyConfiguredMock.mockReturnValue(true);
const mockFetch = mockProjectionFetch(() => jsonResponse({ data: [makeAgentModelEntry()] }));
const mockFetch = mockProjectionFetch(() => Response.json({ data: [makeAgentModelEntry()] }));
await withFetchPathTest(mockFetch, {}, async () => {
expect(
(await discoverDeepInfraSurfaces({ env: {}, agentDir: "/tmp/openclaw-agent" })).live,
@ -176,20 +168,18 @@ describe("DeepInfra pre-auth discovery", () => {
describe("discoverDeepInfraModels", () => {
it("returns static catalog without credentials", async () => {
const models = await discoverDeepInfraModels({ hasApiKey: false });
const modelIds = models.map((m) => m.id);
const streamingUsageIncompatibleModelIds = models
.filter((m) => !m.compat?.supportsUsageInStreaming)
.map((m) => m.id);
expect(DEEPINFRA_DEFAULT_MODEL_REF).toBe("deepinfra/deepseek-ai/DeepSeek-V4-Flash");
expect(models).toStrictEqual(expectedStaticChatCatalog());
expect(modelIds).toStrictEqual(expectedStaticChatCatalog().map((model) => model.id));
expect(streamingUsageIncompatibleModelIds).toStrictEqual([]);
});
it("fetches the openclaw-projection endpoint and parses chat-surface entries when an API key is configured", async () => {
const mockFetch = mockProjectionFetch(
vi.fn().mockResolvedValue(jsonResponse({ data: [makeAgentModelEntry()] })),
vi.fn().mockResolvedValue(Response.json({ data: [makeAgentModelEntry()] })),
);
await withFetchPathTest(mockFetch, { DEEPINFRA_API_KEY: "sk-test" }, async () => {
@ -260,7 +250,7 @@ describe("discoverDeepInfraModels", () => {
},
}),
];
const mockFetch = mockProjectionFetch(vi.fn().mockResolvedValue(jsonResponse({ data: rows })));
const mockFetch = mockProjectionFetch(vi.fn().mockResolvedValue(Response.json({ data: rows })));
DEEPINFRA_MODEL_CATALOG.push(DEEPINFRA_MODEL_CATALOG[0]!);
try {
@ -303,7 +293,7 @@ describe("discoverDeepInfraModels", () => {
it("skips entries with no metadata or no surface tag, and deduplicates ids", async () => {
const mockFetch = mockProjectionFetch(
vi.fn().mockResolvedValue(
jsonResponse({
Response.json({
data: [
{ id: "BAAI/bge-m3", object: "model", metadata: null },
makeAgentModelEntry({
@ -319,20 +309,7 @@ describe("discoverDeepInfraModels", () => {
await withFetchPathTest(mockFetch, { DEEPINFRA_API_KEY: "sk-test" }, async () => {
const models = await discoverDeepInfraModels();
expect(models.map((m) => m.id)).toEqual(
[
{
id: "openai/gpt-oss-120b",
name: "openai/gpt-oss-120b",
reasoning: true,
input: ["text", "image"],
contextWindow: 131072,
maxTokens: 65536,
cost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 },
compat: { supportsUsageInStreaming: true },
},
].map((model) => model.id),
);
expect(models.map((m) => m.id)).toEqual(["openai/gpt-oss-120b"]);
});
});
@ -390,28 +367,15 @@ describe("discoverDeepInfraModels", () => {
const mockFetch = mockProjectionFetch(
vi
.fn()
.mockResolvedValueOnce(jsonResponse(payload))
.mockResolvedValueOnce(Response.json(payload))
.mockResolvedValueOnce(
jsonResponse({ data: [makeAgentModelEntry({ id: "recovered/model" })] }),
Response.json({ data: [makeAgentModelEntry({ id: "recovered/model" })] }),
),
);
await withFetchPathTest(mockFetch, { DEEPINFRA_API_KEY: "sk-test" }, async () => {
await expect(discoverDeepInfraModels()).rejects.toThrow(error);
expect((await discoverDeepInfraModels()).map((m) => m.id)).toEqual(
[
{
id: "recovered/model",
name: "recovered/model",
reasoning: true,
input: ["text", "image"],
contextWindow: 131072,
maxTokens: 65536,
cost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 },
compat: { supportsUsageInStreaming: true },
},
].map((model) => model.id),
);
expect((await discoverDeepInfraModels()).map((m) => m.id)).toEqual(["recovered/model"]);
expect(mockFetch).toHaveBeenCalledTimes(3);
});
});
@ -420,25 +384,16 @@ describe("discoverDeepInfraModels", () => {
const mockFetch = mockProjectionFetch(
vi
.fn()
.mockResolvedValueOnce(jsonResponse({ data: [makeAgentModelEntry({ id: "first/model" })] }))
.mockResolvedValueOnce(
jsonResponse({ data: [makeAgentModelEntry({ id: "second/model" })] }),
Response.json({ data: [makeAgentModelEntry({ id: "first/model" })] }),
)
.mockResolvedValueOnce(
Response.json({ data: [makeAgentModelEntry({ id: "second/model" })] }),
),
);
await withFetchPathTest(mockFetch, { DEEPINFRA_API_KEY: "sk-test" }, async () => {
const expectedIds = [
{
id: "first/model",
name: "first/model",
reasoning: true,
input: ["text", "image"],
contextWindow: 131072,
maxTokens: 65536,
cost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 },
compat: { supportsUsageInStreaming: true },
},
].map((model) => model.id);
const expectedIds = ["first/model"];
expect((await discoverDeepInfraModels()).map((m) => m.id)).toEqual(expectedIds);
expect((await discoverDeepInfraModels()).map((m) => m.id)).toEqual(expectedIds);
expect(mockFetch).toHaveBeenCalledTimes(2);
@ -449,9 +404,9 @@ describe("discoverDeepInfraModels", () => {
const mockFetch = mockProjectionFetch(
vi
.fn()
.mockResolvedValueOnce(jsonResponse({ data: [] }))
.mockResolvedValueOnce(Response.json({ data: [] }))
.mockResolvedValueOnce(
jsonResponse({ data: [makeAgentModelEntry({ id: "recovered/model" })] }),
Response.json({ data: [makeAgentModelEntry({ id: "recovered/model" })] }),
),
);
@ -466,7 +421,7 @@ describe("discoverDeepInfraModels", () => {
describe("discoverDeepInfraSurfaces (per-surface bucketing)", () => {
it("buckets dynamic entries by short-alias surface tag", async () => {
const mockFetch = vi.fn().mockResolvedValue(
jsonResponse({
Response.json({
data: [
makeAgentModelEntry({
id: "anthropic/claude-sonnet-4-6",
@ -543,7 +498,7 @@ describe("discoverDeepInfraSurfaces (per-surface bucketing)", () => {
it("drops malformed live numeric metadata", async () => {
const mockFetch = vi.fn().mockResolvedValue(
jsonResponse({
Response.json({
data: [
makeAgentModelEntry({
id: "bad/chat",

View file

@ -49,14 +49,6 @@ const surfaceEntry = (id: string, surfaceTag: string, extra: Record<string, unkn
},
});
function jsonResponse(payload: unknown, init: ResponseInit = {}): Response {
return new Response(JSON.stringify(payload), {
status: 200,
headers: { "Content-Type": "application/json" },
...init,
});
}
async function withLiveFetch(mockFetch: ReturnType<typeof vi.fn>, run: () => Promise<void>) {
vi.stubEnv("DEEPINFRA_API_KEY", "sk-test");
vi.stubGlobal("fetch", mockFetch);
@ -78,7 +70,7 @@ describe("DeepInfra generation catalogs", () => {
describe("listDeepInfraImageGenCatalog", () => {
it("returns null when live discovery succeeds but the response has zero image-gen entries", async () => {
const mockFetch = vi.fn().mockResolvedValue(
jsonResponse({
Response.json({
data: [
surfaceEntry("anthropic/claude-sonnet-4-6", "chat", {
context_length: 200000,
@ -105,7 +97,7 @@ describe("listDeepInfraImageGenCatalog", () => {
it("projects discovered image-gen entries when a key is configured and discovery is live", async () => {
const mockFetch = vi.fn().mockResolvedValue(
jsonResponse({
Response.json({
data: [
surfaceEntry("black-forest-labs/FLUX-2-pro", "image-gen", {
pricing: { per_image_unit: 0.08 },
@ -149,7 +141,7 @@ describe("listDeepInfraVideoGenCatalog", () => {
// provider's static fallback list is consulted instead of an empty
// "live" answer.
const mockFetch = vi.fn().mockResolvedValue(
jsonResponse({
Response.json({
data: [
surfaceEntry("anthropic/claude-sonnet-4-6", "chat", {
context_length: 200000,
@ -171,7 +163,7 @@ describe("listDeepInfraVideoGenCatalog", () => {
it("projects discovered video-gen entries with capability shape", async () => {
const mockFetch = vi.fn().mockResolvedValue(
jsonResponse({
Response.json({
data: [
surfaceEntry("Wan-AI/Wan2.6-T2V", "video-gen", {
pricing: { output_seconds: 0.05 },
@ -202,7 +194,7 @@ describe("listDeepInfraVideoGenCatalog", () => {
describe("resolveDeepInfraVideoModelCapabilities", () => {
it("returns capabilities for a discovered video-gen model", async () => {
const mockFetch = vi.fn().mockResolvedValue(
jsonResponse({
Response.json({
data: [
surfaceEntry("Wan-AI/Wan2.6-T2V", "video-gen", {
pricing: { output_seconds: 0.05 },
@ -222,7 +214,7 @@ describe("resolveDeepInfraVideoModelCapabilities", () => {
it("strips the deepinfra/ prefix when matching", async () => {
const mockFetch = vi.fn().mockResolvedValue(
jsonResponse({
Response.json({
data: [
surfaceEntry("Wan-AI/Wan2.6-T2V", "video-gen", {
pricing: { output_seconds: 0.05 },
@ -241,7 +233,7 @@ describe("resolveDeepInfraVideoModelCapabilities", () => {
it("returns undefined for an unknown model", async () => {
const mockFetch = vi.fn().mockResolvedValue(
jsonResponse({
Response.json({
data: [
surfaceEntry("Wan-AI/Wan2.6-T2V", "video-gen", {
pricing: { output_seconds: 0.05 },