DEV Community

Alex Spinov
Alex Spinov

Posted on

Playwright Has a Free API — Here's How to Test Web Apps End-to-End

Playwright is Microsoft's browser automation framework for end-to-end testing. It supports Chromium, Firefox, and WebKit with auto-waits, parallel execution, and powerful selectors.

Installation

npm init playwright@latest
Enter fullscreen mode Exit fullscreen mode

Writing Tests

import { test, expect } from "@playwright/test";

test("homepage has title", async ({ page }) => {
  await page.goto("https://playwright.dev");
  await expect(page).toHaveTitle(/Playwright/);
});

test("search works", async ({ page }) => {
  await page.goto("https://playwright.dev");
  await page.getByRole("link", { name: "Get started" }).click();
  await expect(page).toHaveURL(/intro/);
});
Enter fullscreen mode Exit fullscreen mode

Locators — Finding Elements

// By role (recommended)
page.getByRole("button", { name: "Submit" });
page.getByRole("heading", { level: 1 });
page.getByRole("link", { name: "Sign up" });

// By text
page.getByText("Welcome back");
page.getByLabel("Email address");
page.getByPlaceholder("Enter your name");

// By test ID
page.getByTestId("submit-button");

// CSS and XPath (fallback)
page.locator(".product-card");
page.locator("[data-product-id]");
Enter fullscreen mode Exit fullscreen mode

Actions

// Click, fill, select
await page.getByLabel("Email").fill("user@example.com");
await page.getByLabel("Password").fill("secret");
await page.getByRole("button", { name: "Login" }).click();

// Select dropdown
await page.getByLabel("Country").selectOption("US");

// Upload file
await page.getByLabel("Upload").setInputFiles("./test.pdf");

// Drag and drop
await page.locator("#source").dragTo(page.locator("#target"));
Enter fullscreen mode Exit fullscreen mode

Assertions

// Page assertions
await expect(page).toHaveTitle("Dashboard");
await expect(page).toHaveURL(/dashboard/);

// Element assertions
await expect(page.getByText("Success")).toBeVisible();
await expect(page.getByRole("button")).toBeEnabled();
await expect(page.locator(".items")).toHaveCount(5);
await expect(page.getByTestId("total")).toHaveText("$42.00");
Enter fullscreen mode Exit fullscreen mode

API Testing

test("API returns users", async ({ request }) => {
  const response = await request.get("/api/users");
  expect(response.ok()).toBeTruthy();
  const users = await response.json();
  expect(users.length).toBeGreaterThan(0);
});
Enter fullscreen mode Exit fullscreen mode

Configuration

// playwright.config.ts
import { defineConfig } from "@playwright/test";

export default defineConfig({
  testDir: "./tests",
  fullyParallel: true,
  retries: process.env.CI ? 2 : 0,
  workers: process.env.CI ? 1 : undefined,
  reporter: "html",
  use: {
    baseURL: "http://localhost:3000",
    trace: "on-first-retry",
    screenshot: "only-on-failure"
  },
  projects: [
    { name: "chromium", use: { browserName: "chromium" } },
    { name: "firefox", use: { browserName: "firefox" } },
    { name: "webkit", use: { browserName: "webkit" } }
  ]
});
Enter fullscreen mode Exit fullscreen mode

Need to extract or automate web content at scale? Check out my web scraping tools on Apify — no coding required. Or email me at spinov001@gmail.com for custom solutions.

Top comments (0)