Swacblooms🦋

Making the Moves
Menu
  • Home
  • Motivation
  • Education
  • Programming
  • About
  • Contact
  • Privacy Policy
Home
Programming
What Is Playwright and Why Should You Care?
Programming

What Is Playwright and Why Should You Care?

Samson Amaugo March 23, 2026

Introduction

If you have ever shipped a feature that looked perfect in your local browser but broke immediately in production, you already understand why automated browser testing exists. Playwright is the answer to the question: “How do we make that kind of testing fast, reliable, and not painful to write?”

This first article walks you through what Playwright is, why it stands out from its competitors, how to install it, and how to read your very first test. By the end, you will have a working setup and a solid mental model of what each piece does.


What Is Playwright?

Playwright is an open-source end-to-end (E2E) testing framework built by Microsoft. “End-to-end” means it controls a real browser — Chrome, Firefox, or Safari — the same way a real user would: clicking links, filling forms, navigating pages, and checking that the right content appears.

Unlike unit tests (which test isolated functions) or integration tests (which test modules together), E2E tests validate the entire stack from the UI down to the database and back. They are the closest thing to “a human actually using your app.”

Playwright supports:

  • Chromium (Chrome / Edge)
  • Firefox
  • WebKit (Safari)
  • Mobile viewports
  • Multiple languages: JavaScript, TypeScript, Python, Java, .NET

This series uses JavaScript/TypeScript.


Why Playwright?

There are other browser automation tools out there — Selenium and Cypress being the most well-known. This series focuses on Playwright, and here is what makes it worth your time:

  • Supports all three major browser engines — Chromium, Firefox, and WebKit — out of the box
  • Auto-waits for elements to be ready before acting, so no manual sleeps or brittle waits
  • Runs tests in parallel across browsers simultaneously
  • First-class TypeScript support with no extra configuration
  • Built-in network interception, trace recording, and a visual debugger
  • Actively maintained by Microsoft with frequent releases

Installing Playwright

Playwright requires Node.js 20.x, 22.x, or 24.x. Check your version:

node --version

To scaffold a new Playwright project, run:

npm init playwright@latest

The CLI will ask a few questions:

  • TypeScript or JavaScript? (choose either — this series uses both)
  • Where to put your tests? (default: tests/)
  • Add a GitHub Actions workflow? (yes — we cover this in Part 11)
  • Install Playwright browsers? (yes)

That last step downloads Chromium, Firefox, and WebKit — about 300 MB total. Playwright ships its own browser binaries, so your system browsers never interfere.

After installation, your project looks like this:

your-project/
├── node_modules/
├── tests/
│   └── example.spec.js       ← your starter test
├── playwright.config.js      ← all configuration lives here
├── package.json
└── package-lock.json


Your First Test — Line by Line

Open tests/example.spec.js. Here is what it contains:

// @ts-check
import { test, expect } from '@playwright/test';

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

test('get started link', async ({ page }) => {
  await page.goto('https://playwright.dev/');
  await page.getByRole('link', { name: 'Get started' }).click();
  await expect(page.getByRole('heading', { name: 'Installation' })).toBeVisible();
});

Let’s break each part down.


// @ts-check

A JSDoc comment that tells VS Code to type-check this plain JavaScript file using TypeScript’s engine. You get autocomplete and inline errors without needing a tsconfig. Optional, but useful.


import { test, expect } from '@playwright/test'

Two things are imported:

  • test — the function you use to define a test case (like it() in Jest)
  • expect — the assertion library (like Jest’s expect, extended with browser-aware matchers)

test('has title', async ({ page }) => { ... })

  • The first argument is the test name — what shows up in the report.
  • The second argument is an async function that receives fixtures. The page fixture is Playwright’s central object: it represents a single browser tab.
  • Every browser interaction is async, so you use await throughout.

await page.goto('https://playwright.dev/')

Navigates the browser to a URL. Playwright waits for the page to reach a “load” state before moving on.


await expect(page).toHaveTitle(/Playwright/)

Asserts that the page’s <title> tag matches the regular expression /Playwright/. This is a web-first assertion — if the title is not there yet, Playwright retries the check for up to 5 seconds before failing. No manual waits needed.


await page.getByRole('link', { name: 'Get started' }).click()

Finds an <a> element whose accessible name is “Get started” and clicks it. getByRole is the preferred way to select elements — it mirrors how assistive technologies see your page and is far more resilient than CSS selectors.


await expect(page.getByRole('heading', { name: 'Installation' })).toBeVisible()

After clicking, the test navigates to the installation page. This assertion checks that a heading with the text “Installation” becomes visible. Again, Playwright retries this automatically.


Understanding the playwright.config.js File

The playwright.config.js file controls how your entire test suite runs. The default configuration sets up three test projects — one for each browser engine.

export default defineConfig({
  testDir: './tests',
  fullyParallel: true,
  forbidOnly: !!process.env.CI,
  retries: process.env.CI ? 2 : 0,
  workers: process.env.CI ? 1 : undefined,
  reporter: 'html',
  use: {
    trace: 'on-first-retry',
  },
  projects: [
    { name: 'chromium', use: { ...devices['Desktop Chrome'] } },
    { name: 'firefox',  use: { ...devices['Desktop Firefox'] } },
    { name: 'webkit',   use: { ...devices['Desktop Safari'] } },
  ],
});

Key settings to know right now:

OptionWhat it does
testDirWhere Playwright looks for test files (*.spec.js / *.test.js)
fullyParallelRun all tests in all files at the same time — faster, but tests must not share state
retriesHow many times to retry a failing test. Set to 2 on CI to reduce flakiness noise
reporter"html" generates a rich clickable report in playwright-report/
traceRecords screenshots, network, and console logs on the first retry of a failure
projectsEach project runs the full suite in one browser — your tests automatically run 3×

We will explore every option in detail in Part 5.


Running Your Tests

# Run the full suite across all browsers
npx playwright test

# Run only in one browser
npx playwright test --project=chromium

# Run a specific file
npx playwright test tests/example.spec.js

# Watch the browser open (headed mode)
npx playwright test --headed

# Open the interactive HTML report after a run
npx playwright show-report

# Open UI Mode — live debugging with a built-in browser and test explorer
npx playwright test --ui

When tests pass, you will see:

Running 6 tests using 3 workers
  6 passed (8.3s)

That “6 tests” comes from 2 test cases × 3 browser projects.


Reading a Failure

Break one of the assertions intentionally:

await expect(page).toHaveTitle(/NotARealTitle/);

Run again. Playwright will print:

Error: expect(page).toHaveTitle(expected)

Expected pattern: /NotARealTitle/
Received string:  "Fast and reliable end-to-end testing for modern web apps | Playwright"

The diff is clear and actionable. The HTML report adds a screenshot of the page at the moment of failure, and if tracing is enabled, a full step-by-step replay.


Summary

Here is what you learned in Part 1:

  • Playwright is an E2E testing framework that drives real browsers
  • It supports Chromium, Firefox, and WebKit with auto-waiting built in
  • npm init playwright@latest scaffolds a working project in seconds
  • A test is an async function that receives a page fixture
  • expect() assertions are web-first: they retry until they pass or time out
  • playwright.config.js controls browsers, parallelism, retries, and more
  • npx playwright test runs everything; --project and --headed are useful flags

What’s Next

In Part 2, we dive deep into locators — the API you will use in every single test to find elements on the page. You will learn why getByRole is almost always the right choice, and when to reach for other strategies.

Prev Article
Next Article

Related Articles

creating root level files or folders in vscode
Creating a root-level file or folder in vscode can be …

VSCODE Creating Root Level Files or Folders In VsCode

Hello y’all, in this post I would be writing on …

Case Statement: Ruby

About The Author

Samson Amaugo

I am Samson Amaugo. I am a full-stack developer and I specialize in DotNet and the MERN stack.

Search Site

Recent Posts

  • Cloudflare Tunnel to Postgres, plus Swarm’s static IP problem
  • The Topological Sort
  • Building a Perceptron in .NET
  • Part 4 — Assertions: Verifying What You See
  • Part 3 — Actions and Auto-Waiting: Putting Locators to Work

Categories

  • EDUCATION
  • Motivation
  • Programming
  • Uncategorized

Get more stuff

Subscribe to our mailing list and get interesting stuff and updates to your email inbox.

Thank you for subscribing.

Something went wrong.

we respect your privacy and take protecting it seriously

RSS feed: Swacblooms Swacblooms

Swacblooms🦋

Making the Moves
Copyright © 2026 Swacblooms🦋
Swacblooms - Making the Moves