Files
WallMuse/packages/provider-adapters/src/__tests__/provider-adapters.test.ts
2026-05-09 09:12:41 +00:00

179 lines
5.6 KiB
TypeScript

import { describe, expect, it, vi } from "vitest";
import {
createDefaultProviderRegistry,
MockImageProviderAdapter,
normalizeImageAssets,
normalizeProviderError,
OpenAICompatibleImageProviderAdapter,
SiliconFlowImageProviderAdapter
} from "../index";
describe("provider adapter registry", () => {
it("creates implemented and reserved adapters", () => {
const registry = createDefaultProviderRegistry();
expect(registry.mock.provider).toBe("mock");
expect(registry["openai-compatible"].provider).toBe("openai-compatible");
expect(registry.siliconflow.provider).toBe("siliconflow");
expect(registry.dashscope.provider).toBe("dashscope");
expect(registry.volcengine.provider).toBe("volcengine");
expect(registry.zhipu.provider).toBe("zhipu");
expect(registry["custom-template"].provider).toBe("custom-template");
});
});
describe("mock provider", () => {
it("returns deterministic URL assets with mapped dimensions", async () => {
const adapter = new MockImageProviderAdapter();
const result = await adapter.generateTextToImage(
{
model: "mock-wallpaper",
prompt: "misty mountain wallpaper",
size: { aspectRatio: "16:9", resolution: "2k" },
seed: 42
},
{}
);
expect(result.assets[0]).toMatchObject({
kind: "url",
width: 2560,
height: 1440,
seed: 42
});
expect(result.usage?.imageCount).toBe(1);
});
it("can return base64 assets for local tests", async () => {
const adapter = new MockImageProviderAdapter();
const result = await adapter.generateTextToImage(
{
model: "mock-wallpaper",
prompt: "phone wallpaper",
responseFormat: "base64",
size: { aspectRatio: "9:16", resolution: "1k" }
},
{}
);
expect(result.assets[0]?.kind).toBe("base64");
expect(result.assets[0]?.mimeType).toBe("image/png");
expect(result.assets[0]?.width).toBe(720);
expect(result.assets[0]?.height).toBe(1280);
});
});
describe("OpenAI compatible provider", () => {
it("posts to configurable image endpoint and normalizes base64 response", async () => {
const fetch = vi.fn(async (_url: URL | RequestInfo, init?: RequestInit) => {
expect(_url).toBe("https://new-api.example.com/v1/images/generations");
expect(JSON.parse(String(init?.body))).toMatchObject({
model: "gpt-image-1",
prompt: "desktop wallpaper",
n: 1,
size: "1536x1024",
response_format: "b64_json"
});
return jsonResponse({
data: [{ b64_json: "data:image/png;base64,abc123" }],
usage: { input_tokens: 12, output_tokens: 0 }
});
});
const adapter = new OpenAICompatibleImageProviderAdapter();
const result = await adapter.generateTextToImage(
{
baseUrl: "https://new-api.example.com",
model: "gpt-image-1",
prompt: "desktop wallpaper",
responseFormat: "base64",
size: { aspectRatio: "16:9", resolution: "4k" }
},
{ auth: { apiKey: "test-key" }, fetch }
);
expect(result.assets[0]).toMatchObject({
kind: "base64",
value: "abc123",
mimeType: "image/png",
width: 1536,
height: 1024
});
expect(result.usage?.inputTokens).toBe(12);
});
});
describe("SiliconFlow provider", () => {
it("uses image_size and normalizes URL response", async () => {
const fetch = vi.fn(async (_url: URL | RequestInfo, init?: RequestInit) => {
expect(_url).toBe("https://api.siliconflow.cn/v1/images/generations");
expect(JSON.parse(String(init?.body))).toMatchObject({
model: "black-forest-labs/FLUX.2-pro",
prompt: "portrait wallpaper",
image_size: "720x1280",
batch_size: 1,
seed: 7
});
return jsonResponse({ data: [{ url: "https://cdn.example.com/result.png" }] });
});
const adapter = new SiliconFlowImageProviderAdapter();
const result = await adapter.generateTextToImage(
{
model: "black-forest-labs/FLUX.2-pro",
prompt: "portrait wallpaper",
size: { aspectRatio: "9:16", resolution: "1k" },
seed: 7
},
{ auth: { apiKey: "sf-key" }, fetch }
);
expect(result.assets[0]).toMatchObject({
kind: "url",
value: "https://cdn.example.com/result.png",
width: 720,
height: 1280
});
});
});
describe("normalization helpers", () => {
it("normalizes common provider errors", () => {
expect(normalizeProviderError("siliconflow", { status: 429, message: "rate limit exceeded" })).toMatchObject({
category: "rate_limit",
retryable: true,
statusCode: 429
});
expect(normalizeProviderError("openai-compatible", { status: 401, message: "invalid api key" })).toMatchObject({
category: "authentication",
retryable: false
});
expect(normalizeProviderError("openai-compatible", { status: 504, message: "gateway timeout" })).toMatchObject({
category: "timeout",
retryable: true
});
});
it("normalizes URL and base64 image payloads", () => {
expect(normalizeImageAssets({ data: [{ url: "https://example.com/a.png" }] })[0]).toMatchObject({
kind: "url",
value: "https://example.com/a.png"
});
expect(normalizeImageAssets({ images: [{ image_base64: "data:image/jpeg;base64,zzz" }] })[0]).toMatchObject({
kind: "base64",
value: "zzz",
mimeType: "image/jpeg"
});
});
});
function jsonResponse(body: unknown, status = 200): Response {
return new Response(JSON.stringify(body), {
status,
headers: { "content-type": "application/json" }
});
}