Production testing patterns with Playwright for Google Antigravity IDE
# Playwright E2E Testing Guide for Google Antigravity
Master end-to-end testing with Playwright in Google Antigravity IDE. This comprehensive guide covers page object models, fixtures, API mocking, visual regression testing, and advanced patterns for building reliable, maintainable test suites that catch real bugs.
## Configuration
Configure your Antigravity environment for Playwright:
```typescript
// .antigravity/playwright.ts
export const playwrightConfig = {
patterns: ["page-objects", "fixtures", "api-mocking"],
parallelization: true,
visualRegression: true,
tracing: "on-failure"
};
```
## Playwright Configuration
Set up your playwright.config.ts:
```typescript
import { defineConfig, devices } from "@playwright/test";
export default defineConfig({
testDir: "./e2e",
fullyParallel: true,
forbidOnly: !!process.env.CI,
retries: process.env.CI ? 2 : 0,
workers: process.env.CI ? 1 : undefined,
reporter: [
["html"],
["json", { outputFile: "test-results.json" }]
],
use: {
baseURL: "http://localhost:3000",
trace: "on-first-retry",
screenshot: "only-on-failure",
video: "on-first-retry"
},
projects: [
{
name: "chromium",
use: { ...devices["Desktop Chrome"] }
},
{
name: "firefox",
use: { ...devices["Desktop Firefox"] }
},
{
name: "mobile",
use: { ...devices["iPhone 14"] }
}
],
webServer: {
command: "npm run dev",
url: "http://localhost:3000",
reuseExistingServer: !process.env.CI
}
});
```
## Page Object Model
Create maintainable page objects:
```typescript
// e2e/pages/LoginPage.ts
import { Page, Locator, expect } from "@playwright/test";
export class LoginPage {
readonly page: Page;
readonly emailInput: Locator;
readonly passwordInput: Locator;
readonly submitButton: Locator;
readonly errorMessage: Locator;
constructor(page: Page) {
this.page = page;
this.emailInput = page.getByLabel("Email");
this.passwordInput = page.getByLabel("Password");
this.submitButton = page.getByRole("button", { name: "Sign In" });
this.errorMessage = page.getByRole("alert");
}
async goto() {
await this.page.goto("/login");
}
async login(email: string, password: string) {
await this.emailInput.fill(email);
await this.passwordInput.fill(password);
await this.submitButton.click();
}
async expectError(message: string) {
await expect(this.errorMessage).toContainText(message);
}
async expectLoggedIn() {
await expect(this.page).toHaveURL("/dashboard");
}
}
```
## Custom Fixtures
Create reusable test fixtures:
```typescript
// e2e/fixtures.ts
import { test as base, expect } from "@playwright/test";
import { LoginPage } from "./pages/LoginPage";
import { DashboardPage } from "./pages/DashboardPage";
type Fixtures = {
loginPage: LoginPage;
dashboardPage: DashboardPage;
authenticatedPage: Page;
};
export const test = base.extend<Fixtures>({
loginPage: async ({ page }, use) => {
const loginPage = new LoginPage(page);
await use(loginPage);
},
dashboardPage: async ({ page }, use) => {
const dashboardPage = new DashboardPage(page);
await use(dashboardPage);
},
authenticatedPage: async ({ page }, use) => {
await page.goto("/login");
await page.getByLabel("Email").fill("test@example.com");
await page.getByLabel("Password").fill("password123");
await page.getByRole("button", { name: "Sign In" }).click();
await page.waitForURL("/dashboard");
await use(page);
}
});
export { expect };
```
## API Mocking
Mock API responses for reliable tests:
```typescript
import { test, expect } from "./fixtures";
test("displays user data from API", async ({ page }) => {
await page.route("/api/users/*", async (route) => {
await route.fulfill({
status: 200,
contentType: "application/json",
body: JSON.stringify({
id: "123",
name: "John Doe",
email: "john@example.com"
})
});
});
await page.goto("/users/123");
await expect(page.getByText("John Doe")).toBeVisible();
});
test("handles API errors gracefully", async ({ page }) => {
await page.route("/api/users/*", async (route) => {
await route.fulfill({
status: 500,
body: "Internal Server Error"
});
});
await page.goto("/users/123");
await expect(page.getByText("Something went wrong")).toBeVisible();
});
```
## Visual Regression Testing
Capture and compare screenshots:
```typescript
test("homepage visual regression", async ({ page }) => {
await page.goto("/");
await expect(page).toHaveScreenshot("homepage.png", {
fullPage: true,
maxDiffPixelRatio: 0.01
});
});
test("component visual regression", async ({ page }) => {
await page.goto("/components/button");
const button = page.getByRole("button", { name: "Primary" });
await expect(button).toHaveScreenshot("button-default.png");
await button.hover();
await expect(button).toHaveScreenshot("button-hover.png");
});
```
## Best Practices
Follow these guidelines for Playwright testing:
1. **Use page objects** - Encapsulate selectors and actions
2. **Prefer user-visible locators** - getByRole, getByLabel, getByText
3. **Mock external APIs** - Ensure test reliability
4. **Use fixtures** - Share setup across tests
5. **Enable tracing** - Debug failures easily
6. **Run parallel** - Speed up test execution
Google Antigravity IDE provides intelligent test scaffolding and selector suggestions for comprehensive E2E coverage.This Testing prompt is ideal for developers working on:
By using this prompt, you can save hours of manual coding and ensure best practices are followed from the start. It's particularly valuable for teams looking to maintain consistency across their testing implementations.
Yes! All prompts on Antigravity AI Directory are free to use for both personal and commercial projects. No attribution required, though it's always appreciated.
This prompt works excellently with Claude, ChatGPT, Cursor, GitHub Copilot, and other modern AI coding assistants. For best results, use models with large context windows.
You can modify the prompt by adding specific requirements, constraints, or preferences. For Testing projects, consider mentioning your framework version, coding style, and any specific libraries you're using.