Files
automaker/app/tests/claude-sdk-integration.spec.ts

295 lines
11 KiB
TypeScript

import { test, expect } from "@playwright/test";
test.describe("Claude SDK Integration - Autonomous Agent", () => {
test.describe("Step 1: Configure API Key", () => {
test("can navigate to settings and configure Anthropic API key", async ({ page }) => {
await page.goto("/");
// Navigate to settings
await page.getByTestId("settings-button").click();
await expect(page.getByTestId("settings-view")).toBeVisible();
// Verify Anthropic API key input is available
const apiKeyInput = page.getByTestId("anthropic-api-key-input");
await expect(apiKeyInput).toBeVisible();
await expect(apiKeyInput).toBeEditable();
// Enter a test API key
await apiKeyInput.fill("sk-ant-api03-test-key-for-integration-test");
// Save settings
await page.getByTestId("save-settings").click();
await expect(page.getByText("Saved!")).toBeVisible();
});
test("API key input has proper security features", async ({ page }) => {
await page.goto("/");
await page.getByTestId("settings-button").click();
// Verify password masking by default
await expect(page.getByTestId("anthropic-api-key-input")).toHaveAttribute("type", "password");
// Can toggle visibility
await page.getByTestId("toggle-anthropic-visibility").click();
await expect(page.getByTestId("anthropic-api-key-input")).toHaveAttribute("type", "text");
// Can toggle back to hidden
await page.getByTestId("toggle-anthropic-visibility").click();
await expect(page.getByTestId("anthropic-api-key-input")).toHaveAttribute("type", "password");
});
test("API key persists across page reloads", async ({ page }) => {
await page.goto("/");
await page.getByTestId("settings-button").click();
// Enter and save API key
const testKey = "sk-ant-api03-persistence-test-key";
await page.getByTestId("anthropic-api-key-input").fill(testKey);
await page.getByTestId("save-settings").click();
await expect(page.getByText("Saved!")).toBeVisible();
// Reload and verify persistence
await page.reload();
await page.getByTestId("settings-button").click();
// Make key visible and verify
await page.getByTestId("toggle-anthropic-visibility").click();
await expect(page.getByTestId("anthropic-api-key-input")).toHaveValue(testKey);
});
});
test.describe("Step 2: Send test prompt", () => {
test("test connection button is visible in settings", async ({ page }) => {
await page.goto("/");
await page.getByTestId("settings-button").click();
// Test connection button should be visible
const testButton = page.getByTestId("test-claude-connection");
await expect(testButton).toBeVisible();
await expect(testButton).toContainText("Test");
});
test("test connection button is disabled without API key", async ({ page }) => {
await page.goto("/");
await page.getByTestId("settings-button").click();
// Clear any existing API key
await page.getByTestId("anthropic-api-key-input").fill("");
// Test button should be disabled
await expect(page.getByTestId("test-claude-connection")).toBeDisabled();
});
test("test connection button is enabled with API key", async ({ page }) => {
await page.goto("/");
await page.getByTestId("settings-button").click();
// Enter API key
await page.getByTestId("anthropic-api-key-input").fill("sk-ant-test-key");
// Test button should be enabled
await expect(page.getByTestId("test-claude-connection")).toBeEnabled();
});
test("clicking test sends request to Claude API endpoint", async ({ page }) => {
// Setup API route mock
await page.route("**/api/claude/test", async (route) => {
await route.fulfill({
status: 200,
contentType: "application/json",
body: JSON.stringify({
success: true,
message: "Connection successful! Claude responded.",
model: "claude-sonnet-4-20250514",
}),
});
});
await page.goto("/");
await page.getByTestId("settings-button").click();
// Enter API key
await page.getByTestId("anthropic-api-key-input").fill("sk-ant-test-key");
// Click test button
await page.getByTestId("test-claude-connection").click();
// Should show loading state briefly then success
await expect(page.getByTestId("test-connection-result")).toBeVisible({ timeout: 10000 });
});
});
test.describe("Step 3: Verify response received", () => {
test("displays success message when connection succeeds", async ({ page }) => {
// Mock successful response
await page.route("**/api/claude/test", async (route) => {
await route.fulfill({
status: 200,
contentType: "application/json",
body: JSON.stringify({
success: true,
message: 'Connection successful! Response: "Claude SDK connection successful!"',
model: "claude-sonnet-4-20250514",
}),
});
});
await page.goto("/");
await page.getByTestId("settings-button").click();
await page.getByTestId("anthropic-api-key-input").fill("sk-ant-valid-key");
await page.getByTestId("test-claude-connection").click();
// Wait for result to appear
const result = page.getByTestId("test-connection-result");
await expect(result).toBeVisible({ timeout: 10000 });
// Verify success message is shown
const message = page.getByTestId("test-connection-message");
await expect(message).toContainText(/Connection successful/i);
});
test("displays error message when API key is invalid", async ({ page }) => {
// Mock authentication error
await page.route("**/api/claude/test", async (route) => {
await route.fulfill({
status: 401,
contentType: "application/json",
body: JSON.stringify({
success: false,
error: "Invalid API key. Please check your Anthropic API key.",
}),
});
});
await page.goto("/");
await page.getByTestId("settings-button").click();
await page.getByTestId("anthropic-api-key-input").fill("invalid-key");
await page.getByTestId("test-claude-connection").click();
// Wait for error result
const result = page.getByTestId("test-connection-result");
await expect(result).toBeVisible({ timeout: 10000 });
// Verify error message is shown
const message = page.getByTestId("test-connection-message");
await expect(message).toContainText(/Invalid API key|API key|error/i);
});
test("displays error message on network failure", async ({ page }) => {
// Mock network error
await page.route("**/api/claude/test", async (route) => {
await route.abort("connectionrefused");
});
await page.goto("/");
await page.getByTestId("settings-button").click();
await page.getByTestId("anthropic-api-key-input").fill("sk-ant-test-key");
await page.getByTestId("test-claude-connection").click();
// Wait for error result
const result = page.getByTestId("test-connection-result");
await expect(result).toBeVisible({ timeout: 10000 });
// Verify network error message
const message = page.getByTestId("test-connection-message");
await expect(message).toContainText(/Network error|connection|failed/i);
});
test("displays rate limit error message", async ({ page }) => {
// Mock rate limit error
await page.route("**/api/claude/test", async (route) => {
await route.fulfill({
status: 429,
contentType: "application/json",
body: JSON.stringify({
success: false,
error: "Rate limit exceeded. Please try again later.",
}),
});
});
await page.goto("/");
await page.getByTestId("settings-button").click();
await page.getByTestId("anthropic-api-key-input").fill("sk-ant-rate-limited");
await page.getByTestId("test-claude-connection").click();
// Wait for error result
const result = page.getByTestId("test-connection-result");
await expect(result).toBeVisible({ timeout: 10000 });
// Verify rate limit message
const message = page.getByTestId("test-connection-message");
await expect(message).toContainText(/Rate limit|try again/i);
});
test("shows loading state while testing connection", async ({ page }) => {
// Mock slow response
await page.route("**/api/claude/test", async (route) => {
await new Promise((resolve) => setTimeout(resolve, 1000));
await route.fulfill({
status: 200,
contentType: "application/json",
body: JSON.stringify({
success: true,
message: "Connection successful!",
}),
});
});
await page.goto("/");
await page.getByTestId("settings-button").click();
await page.getByTestId("anthropic-api-key-input").fill("sk-ant-test-key");
await page.getByTestId("test-claude-connection").click();
// Should show "Testing..." text while loading
await expect(page.getByText("Testing...")).toBeVisible();
});
});
test.describe("Full Integration Flow", () => {
test("complete Claude SDK integration flow - configure, test, verify", async ({ page }) => {
// Mock successful API response
await page.route("**/api/claude/test", async (route) => {
await route.fulfill({
status: 200,
contentType: "application/json",
body: JSON.stringify({
success: true,
message: 'Connection successful! Response: "Claude SDK connection successful!"',
model: "claude-sonnet-4-20250514",
}),
});
});
// Step 1: Navigate to app
await page.goto("/");
await expect(page).toHaveURL("/");
// Step 2: Go to settings and configure API key
await page.getByTestId("settings-button").click();
await expect(page.getByTestId("settings-view")).toBeVisible();
const apiKey = "sk-ant-api03-integration-test-key";
await page.getByTestId("anthropic-api-key-input").fill(apiKey);
await page.getByTestId("save-settings").click();
await expect(page.getByText("Saved!")).toBeVisible();
// Step 3: Test the connection
await page.getByTestId("test-claude-connection").click();
// Step 4: Verify response is received
await expect(page.getByTestId("test-connection-result")).toBeVisible({ timeout: 10000 });
await expect(page.getByTestId("test-connection-message")).toContainText(/Connection successful/i);
// Verify the UI shows success state (green styling indicates success)
const resultContainer = page.getByTestId("test-connection-result");
await expect(resultContainer).toBeVisible();
});
});
});