Type something to search...
Next.js Setting up Playwright

Next.js Setting up Playwright

Given how often this series has pointed toward "use E2E testing" as the answer for whatever a given unit-testing tool doesn't yet support — async Server Components, chiefly — it's worth having Playwright's own setup covered in real depth, since it's frequently the tool actually doing that E2E work in a modern App Router test suite. Its defining feature relative to the alternatives: genuine cross-browser automation — Chromium, Firefox, and WebKit — driven from one consistent API, rather than committing to just one rendering engine.

The fastest path

npx create-next-app@latest --example with-playwright with-playwright-app

Setting it up manually

npm init playwright

This is a genuinely interactive setup — it walks you through a series of prompts (which browsers to install, whether to add a GitHub Actions workflow, TypeScript or JavaScript) and produces a playwright.config.ts reflecting your choices. Playwright's own installation guide is worth a look directly if you want a fuller walkthrough of every prompt's implications beyond what's summarized here.

Writing your first test

The same two-page navigation example used throughout this testing series:

// app/page.tsx
import Link from "next/link";

export default function Page() {
  return (
    <div>
      <h1>Home</h1>
      <Link href="/about">About</Link>
    </div>
  );
}
// app/about/page.tsx
import Link from "next/link";

export default function Page() {
  return (
    <div>
      <h1>About</h1>
      <Link href="/">Home</Link>
    </div>
  );
}
// tests/example.spec.ts
import { test, expect } from "@playwright/test";

test("should navigate to the about page", async ({ page }) => {
  await page.goto("http://localhost:3000/");
  await page.click("text=About");
  await expect(page).toHaveURL("http://localhost:3000/about");
  await expect(page.locator("h1")).toContainText("About");
});

Setting baseURL: 'http://localhost:3000' in playwright.config.ts lets you write the shorter page.goto('/') throughout your suite instead of repeating the full URL in every test — a small convenience worth adopting immediately rather than retrofitting later once you have dozens of tests already written the longer way.

Running against a real build

The same principle from the Cypress article applies here with equal force: Playwright genuinely drives real browsers against your running app, and testing against a production build more closely matches what actual users experience than testing against the dev server does.

npm run build
npm run start

Then, in a separate terminal:

npx playwright test

If juggling two terminals manually feels like unnecessary friction — and it especially does in CI, where there's no human available to coordinate the timing — Playwright's own webServer config option lets Playwright itself start the dev server and wait until it's genuinely ready before running tests, collapsing the two-terminal dance into one command.

What "cross-browser, one API" actually buys you

This is worth dwelling on rather than treating as a marketing checkbox, because it's the single biggest practical differentiator between Playwright and the other tools in this series. The exact same test file above runs, unmodified, against Chromium, Firefox, and WebKit — Playwright handles the considerable complexity of automating each engine's own quirks internally, so your test code stays engine-agnostic. WebKit specifically is worth calling attention to, since it's the closest automatable approximation available to Safari's actual rendering behavior — a class of bug that only manifests in Safari (a CSS quirk, a JS API difference) is one that Chromium-only E2E testing would never catch at all, and WebKit coverage through Playwright is a genuinely practical way to close exactly that gap without needing an actual Mac and actual Safari in your CI pipeline.

Running in CI

Playwright runs headless by default — no separate flag needed the way Cypress requires cypress run versus cypress open. The one setup step CI environments specifically need that local development machines usually don't: installing the browser binaries and their OS-level dependencies explicitly.

npx playwright install-deps

Skip this in a fresh CI container image, and tests fail with missing-system-dependency errors that have nothing to do with your actual test code or application logic — worth recognizing immediately as an environment-setup issue rather than assuming your tests themselves are broken.

Key Takeaways

TaskCommand
Quickstartnpx create-next-app@latest --example with-playwright
Manual installnpm init playwright (interactive setup)
Test file locationtests/*.spec.ts
Run against productionnpm run build && npm run start, then npx playwright test
Let Playwright manage the serverwebServer option in playwright.config.ts
CI browser dependenciesnpx playwright install-deps
Biggest differentiatorGenuine Chromium + Firefox + WebKit coverage from one API

Playwright's real value in a Next.js test suite isn't just "another E2E tool" — it's specifically the WebKit coverage that closes a real, otherwise-hard-to-test gap (genuine Safari-adjacent behavior, without needing actual Safari), combined with being the recommended fallback wherever this series' other testing tools hit the async-Server-Component ceiling. If your app has any meaningful Safari user base, Playwright is worth choosing for that reason alone, independent of anything else it offers.

Tags :
Share :

Related Posts

Can Next.js Be Used with GraphQL?

Can Next.js Be Used with GraphQL?

Next.js and GraphQL are two powerful technologies that have gained significant traction in the web development community. Next.js, a React-based fram

Dive Deeper
How does Next.js differ from Create React App?

How does Next.js differ from Create React App?

In the world of modern web development, React.js has emerged as a dominant force due to its flexibility, performance, and extensive ecosystem. Two po

Dive Deeper
How does Next.js handle image optimization?

How does Next.js handle image optimization?

In modern web development, image optimization plays a critical role in enhancing user experience and improving site performance. Large, unoptimized i

Dive Deeper