Skip to main content

Module 8 · Automation foundations

A first Playwright test

Write and run an end-to-end test against the training shop on your own machine.

About 12 min reading and 30 min practice (estimates)

Loading progress…

Read

Learning objectives

  • Set up Playwright Test in a small project.
  • Locate elements by role and accessible name.
  • Use web-first assertions that wait automatically.

Explanation

Playwright drives real browsers and comes with a test runner. Each test gets a fresh, isolated browser context — its own cookies and storage — so tests don't affect each other. Locators such as getByRole find elements the way assistive technology does, and assertions like toBeVisible or toContainText keep retrying until they pass or time out, so you rarely need manual waits.

mkdir shop-tests && cd shop-tests
npm init -y
npm install --save-dev @playwright/test@1.64.0
npx playwright install chromium   # or use installed Chrome (see config)
Setup, tested with Playwright 1.64.0 on Node.js 24.
// playwright.config.ts
import { defineConfig } from "@playwright/test";

export default defineConfig({
  testDir: "./tests",
  use: {
    baseURL: "http://localhost:3000",
    // Uses the Chrome already installed on this machine.
    // Without this line, run `npx playwright install chromium` once instead.
    channel: "chrome",
  },
});

Example: the cart updates after adding two products

// tests/cart.spec.ts
import { test, expect } from "@playwright/test";

test("adding two products updates the cart", async ({ page }) => {
  await page.goto("/en/qa-lab/bug-arena/commerce");

  // A fresh browser context opens the mission brief first.
  await page.getByRole("button", { name: "Start mission" }).click();

  await page.getByRole("button", { name: "Add to cart: Pocket sketchbook" }).click();
  await page.getByRole("button", { name: "Add to cart: Palm-leaf basket" }).click();

  const shopNav = page.getByRole("navigation", { name: "Shop navigation" });
  await shopNav.getByRole("button", { name: /Cart/ }).click();

  await expect(page.getByRole("heading", { name: "Your cart" })).toBeVisible();
  const summary = page.getByRole("region", { name: "Order summary" });
  // 2.250 + 4.750 = 7.000 OMR merchandise subtotal
  await expect(summary).toContainText("7.000 OMR");
});
Runnable against this site on your machine (http://localhost:3000). Run it with: npx playwright test

The test checks the merchandise subtotal only. It's a starting example, not a full checkout test, and it doesn't reveal any of the shop's planted defects.

Common mistakes

  • Selecting elements with long CSS paths that break when the layout changes.
  • Adding page.waitForTimeout(…) instead of using auto-waiting assertions.
  • Writing one giant test for a whole journey instead of focused tests.
  • Running UI tests against production with real accounts.

Try

Practise what you just read. Answers are checked here; nothing is graded publicly or counts toward Bug Arena.

Exercise

Write a second test: open the training shop, choose the Notebooks category, and assert that the result count says 3 products and that "Leather journal" is listed. (The shop's text: "3 products".)

Write your answer first, then compare it with the sample solution. It stays on this page only and isn't sent anywhere.

Review

Check yourself — you should now be able to:

  • Set up Playwright Test in a small project.
  • Locate elements by role and accessible name.
  • Use web-first assertions that wait automatically.

References

Continue

When you’re ready, mark the lesson complete in the Try step and move on.

Marked as read when you reach the end of the lesson.