Files
automaker/app/tests/gemini-sdk.spec.ts

257 lines
9.0 KiB
TypeScript

import { test, expect } from "@playwright/test";
test.describe("Gemini SDK Integration", () => {
test.describe("Step 1: Configure Gemini API Key", () => {
test("can navigate to settings and see Gemini API key input", async ({ page }) => {
await page.goto("/");
// Navigate to settings
await page.getByTestId("settings-button").click();
// Should see settings view
await expect(page.getByTestId("settings-view")).toBeVisible();
// Should see Google/Gemini API key input
await expect(page.getByTestId("google-api-key-input")).toBeVisible();
await expect(page.getByText("Google API Key (Gemini)")).toBeVisible();
});
test("can enter and save Gemini API key", async ({ page }) => {
await page.goto("/");
await page.getByTestId("settings-button").click();
// Enter Gemini API key
const testKey = "AIzaSyTestGeminiKey123";
await page.getByTestId("google-api-key-input").fill(testKey);
// Save settings
await page.getByTestId("save-settings").click();
// Should show saved confirmation
await expect(page.getByText("Saved!")).toBeVisible();
// Reload and verify persistence
await page.reload();
await page.getByTestId("settings-button").click();
// Toggle visibility to verify saved key
await page.getByTestId("toggle-google-visibility").click();
await expect(page.getByTestId("google-api-key-input")).toHaveValue(testKey);
});
test("Gemini API key input is password type by default for security", async ({ page }) => {
await page.goto("/");
await page.getByTestId("settings-button").click();
// Check input type is password (secure)
await expect(page.getByTestId("google-api-key-input")).toHaveAttribute("type", "password");
});
test("can toggle Gemini API key visibility", async ({ page }) => {
await page.goto("/");
await page.getByTestId("settings-button").click();
// Initially password type
await expect(page.getByTestId("google-api-key-input")).toHaveAttribute("type", "password");
// Toggle to show
await page.getByTestId("toggle-google-visibility").click();
await expect(page.getByTestId("google-api-key-input")).toHaveAttribute("type", "text");
// Toggle back to hide
await page.getByTestId("toggle-google-visibility").click();
await expect(page.getByTestId("google-api-key-input")).toHaveAttribute("type", "password");
});
});
test.describe("Step 2: Send image/design prompt", () => {
test("test Gemini connection button exists", async ({ page }) => {
await page.goto("/");
await page.getByTestId("settings-button").click();
// Should see the test Gemini connection button
await expect(page.getByTestId("test-gemini-connection")).toBeVisible();
});
test("test Gemini connection button is disabled without API key", async ({ page }) => {
await page.goto("/");
await page.getByTestId("settings-button").click();
// Clear any existing key
await page.getByTestId("google-api-key-input").clear();
// Button should be disabled
await expect(page.getByTestId("test-gemini-connection")).toBeDisabled();
});
test("test Gemini connection button is enabled with API key", async ({ page }) => {
await page.goto("/");
await page.getByTestId("settings-button").click();
// Enter an API key
await page.getByTestId("google-api-key-input").fill("AIzaSyTestKey123");
// Button should be enabled
await expect(page.getByTestId("test-gemini-connection")).toBeEnabled();
});
test("clicking test button shows loading state", async ({ page }) => {
await page.goto("/");
await page.getByTestId("settings-button").click();
// Enter API key
await page.getByTestId("google-api-key-input").fill("AIzaSyTestKey123");
// Mock the API response with a delay to catch loading state
await page.route("/api/gemini/test", async (route) => {
// Delay to show loading state
await new Promise((resolve) => setTimeout(resolve, 500));
await route.fulfill({
status: 200,
contentType: "application/json",
body: JSON.stringify({
success: true,
message: "Connection successful!",
model: "gemini-1.5-flash",
}),
});
});
// Click test button
await page.getByTestId("test-gemini-connection").click();
// Should show loading state
await expect(page.getByText("Testing...")).toBeVisible();
});
});
test.describe("Step 3: Verify response received", () => {
test("shows success message on successful Gemini API test", async ({ page }) => {
await page.goto("/");
await page.getByTestId("settings-button").click();
// Enter API key
await page.getByTestId("google-api-key-input").fill("AIzaSyTestKey123");
// Mock successful response
await page.route("/api/gemini/test", async (route) => {
await route.fulfill({
status: 200,
contentType: "application/json",
body: JSON.stringify({
success: true,
message: 'Connection successful! Response: "Gemini SDK connection successful!"',
model: "gemini-1.5-flash",
hasImage: false,
}),
});
});
// Click test button
await page.getByTestId("test-gemini-connection").click();
// Should show success result
await expect(page.getByTestId("gemini-test-connection-result")).toBeVisible();
await expect(page.getByTestId("gemini-test-connection-message")).toContainText("Connection successful");
});
test("shows error message on failed Gemini API test", async ({ page }) => {
await page.goto("/");
await page.getByTestId("settings-button").click();
// Enter API key
await page.getByTestId("google-api-key-input").fill("invalid-key");
// Mock error response
await page.route("/api/gemini/test", async (route) => {
await route.fulfill({
status: 401,
contentType: "application/json",
body: JSON.stringify({
success: false,
error: "Invalid API key. Please check your Google API key.",
}),
});
});
// Click test button
await page.getByTestId("test-gemini-connection").click();
// Should show error result
await expect(page.getByTestId("gemini-test-connection-result")).toBeVisible();
await expect(page.getByTestId("gemini-test-connection-message")).toContainText("Invalid API key");
});
test("shows network error message on connection failure", async ({ page }) => {
await page.goto("/");
await page.getByTestId("settings-button").click();
// Enter API key
await page.getByTestId("google-api-key-input").fill("AIzaSyTestKey123");
// Mock network error
await page.route("/api/gemini/test", async (route) => {
await route.abort("connectionfailed");
});
// Click test button
await page.getByTestId("test-gemini-connection").click();
// Should show error result
await expect(page.getByTestId("gemini-test-connection-result")).toBeVisible();
await expect(page.getByTestId("gemini-test-connection-message")).toContainText("Network error");
});
});
test.describe("Gemini API Route - Image/Design Prompt Support", () => {
test("API route accepts and processes image data for design prompts", async ({ page }) => {
await page.goto("/");
// Directly test the API endpoint with image data
const response = await page.request.post("/api/gemini/test", {
data: {
apiKey: "test-key-for-mock",
imageData: "iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mNk+M9QDwADhgGAWjR9awAAAABJRU5ErkJggg==", // 1x1 transparent PNG
mimeType: "image/png",
prompt: "Describe this image",
},
});
// We expect some response (even if error due to invalid key)
const data = await response.json();
// The endpoint should process the request (not crash)
expect(data).toHaveProperty("success");
});
test("API route handles text-only prompts", async ({ page }) => {
await page.goto("/");
// Test the API endpoint with text-only prompt
const response = await page.request.post("/api/gemini/test", {
data: {
apiKey: "test-key",
prompt: "Hello Gemini",
},
});
// Should return a valid response structure
const data = await response.json();
expect(data).toHaveProperty("success");
});
test("API route returns error when no API key provided", async ({ page }) => {
await page.goto("/");
// Test the API endpoint without API key
const response = await page.request.post("/api/gemini/test", {
data: {},
});
// Should return error about missing API key
const data = await response.json();
expect(data.success).toBe(false);
expect(data.error).toContain("No API key");
});
});
});