import { describe, it, expect, vi, beforeEach, afterEach } from "vitest";
const mockGenerateResponse = {
created: "2025-01-15T10:00:00Z",
data: [{
url: "https://ideogram.ai/assets/image/mock-123.png",
prompt: "test prompt",
resolution: "1024x1024",
is_image_safe: true,
seed: 42,
style_type: "DESIGN",
}],
};
describe("Ideogram Generate", () => {
let fetchSpy: any;
beforeEach(() => {
fetchSpy = vi.spyOn(globalThis, "fetch").mockResolvedValue(
new Response(JSON.stringify(mockGenerateResponse), {
status: 200,
headers: { "Content-Type": "application/json" },
})
);
});
afterEach(() => fetchSpy.mockRestore());
it("sends correct headers", async () => {
await fetch("https://api.ideogram.ai/generate", {
method: "POST",
headers: { "Api-Key": "test-key", "Content-Type": "application/json" },
body: JSON.stringify({ image_request: { prompt: "test" } }),
});
expect(fetchSpy).toHaveBeenCalledWith(
"https://api.ideogram.ai/generate",
expect.objectContaining({
headers: expect.objectContaining({ "Api-Key": "test-key" }),
})
);
});
it("parses response correctly", async () => {
const response = await fetch("https://api.ideogram.ai/generate", {
method: "POST",
headers: { "Api-Key": "test-key", "Content-Type": "application/json" },
body: JSON.stringify({ image_request: { prompt: "test" } }),
});
const result = await response.json();
expect(result.data[0].seed).toBe(42);
expect(result.data[0].is_image_safe).toBe(true);
});
it("handles 429 rate limit", async () => {
fetchSpy.mockResolvedValueOnce(new Response("Rate limited", { status: 429 }));
const response = await fetch("https://api.ideogram.ai/generate", {
method: "POST",
headers: { "Api-Key": "test-key", "Content-Type": "application/json" },
body: JSON.stringify({ image_request: { prompt: "test" } }),
});
expect(response.status).toBe(429);
});
});
import { describe, it, expect } from "vitest";
const VALID_STYLES = ["AUTO", "GENERAL", "REALISTIC", "DESIGN", "RENDER_3D", "ANIME"];
const VALID_ASPECTS = [
"ASPECT_1_1", "ASPECT_16_9", "ASPECT_9_16", "ASPECT_3_2", "ASPECT_2_3",
"ASPECT_4_3", "ASPECT_3_4", "ASPECT_10_16", "ASPECT_16_10", "ASPECT_1_3", "ASPECT_3_1",
];
function validateIdeogramRequest(req: any): string[] {
const errors: string[] = [];
if (!req.prompt || req.prompt.length === 0) errors.push("Prompt is required");
if (req.prompt?.length > 10000) errors.push("Prompt exceeds 10,000 char limit");
if (req.style_type && !VALID_STYLES.includes(req.style_type)) {
errors.push(`Invalid style_type: ${req.style_type}`);
}
if (req.aspect_ratio && !VALID_ASPECTS.includes(req.aspect_ratio)) {
errors.push(`Invalid aspect_ratio: ${req.aspect_ratio}`);
}
if (req.num_images && (req.num_images < 1 || req.num_images > 4)) {
errors.push("num_images must be 1-4");
}
return errors;
}
describe("Prompt Validation", () => {
it("accepts valid request", () => {
const errors = validateIdeogramRequest({
prompt: "A sunset over mountains",
style_type: "REALISTIC",
aspect_ratio: "ASPECT_16_9",
});
expect(errors).toHaveLength(0);
});
it("rejects empty prompt", () => {
const errors = validateIdeogramRequest({ prompt: "" });
expect(errors).toContain("Prompt is required");
});
it("rejects invalid style", () => {
const errors = validateIdeogramRequest({ prompt: "test", style_type: "INVALID" });
expect(errors[0]).toContain("Invalid style_type");
});
});
import { describe, it, expect } from "vitest";
describe.skipIf(!process.env.IDEOGRAM_API_KEY)("Ideogram Live API", () => {
it("generates an image successfully", async () => {
const response = await fetch("https://api.ideogram.ai/generate", {
method: "POST",
headers: {
"Api-Key": process.env.IDEOGRAM_API_KEY!,
"Content-Type": "application/json",
},
body: JSON.stringify({
image_request: {
prompt: "CI test: simple geometric shape",
model: "V_2_TURBO",
magic_prompt_option: "OFF",
},
}),
});
expect(response.status).toBe(200);
const result = await response.json();
expect(result.data).toHaveLength(1);
expect(result.data[0].url).toContain("http");
expect(result.data[0].is_image_safe).toBe(true);
}, 30000);
});