Skip to content

Playwright 2025 New Features

We've recently rolled out Playwright 2025 features in our team and accumulated a good deal of experience. Sharing it here as a reference, hoping it helps others tackling similar challenges.

Quick Start

Let's start by looking at the basic implementation:

javascript
import { test, expect } from "@playwright/test";
import { render, screen, fireEvent } from "@testing-library/react";
import userEvent from "@testing-library/user-event";

test("button click", async ({ page }) => {
  await page.goto("/buttons");
  await page.getByRole("button", { name: "提交" }).click();
  await expect(page.getByText("提交成功")).toBeVisible();
});

This snippet illustrates the fundamental usage. In real projects you'll also need to account for error handling and edge cases.

Advanced Usage

Building on this foundation, we can further optimize:

javascript
import { test, expect } from "@playwright/test";
import { render, screen, fireEvent } from "@testing-library/react";
import userEvent from "@testing-library/user-event";

test("form submission", async ({ page }) => {
  await page.goto("/form");
  await page.getByLabel("邮箱").fill("test@example.com");
  await page.getByLabel("密码").fill("password123");
  await page.getByRole("button", { name: "登录" }).click();
  await expect(page).toHaveURL("/dashboard");
});

This approach improves both the testability and scalability of the code.

Case Studies

Here is a complete example:

javascript
import { test, expect } from "@playwright/test";
import { render, screen, fireEvent } from "@testing-library/react";
import userEvent from "@testing-library/user-event";

test.describe("Shopping cart", () => {
  test("add item to cart", async ({ page }) => {
    await page.goto("/products");
    await page
      .getByTestId("product-1")
      .getByRole("button", { name: "加入购物车" })
      .click();
    await expect(page.getByTestId("cart-count")).toHaveText("1");
  });
});

Pay attention to edge-case handling—this is crucial in production environments.

Common Pitfalls

1. Avoid hard-coded waits (waitForTimeout)
   → Use waitForSelector, waitForResponse instead

2. Use page.getByRole instead of page.locator
   → Better accessibility semantics and more stable

3. Isolate test data
   → Each test should create/clean up its own data

4. Parallelize test execution
   → worker: 4; fullyParallel: true in playwright.config.ts

Summary

  • Always verify compatibility before using in production
  • In team collaboration, conventions and documentation matter more than the technology itself
  • Stay up-to-date with community trends; technical solutions require continuous iteration

MIT Licensed