Skip to content
Independent guides for QA & test automationRSSEditorial policy
QA Vibes

Practice · about 5 minutes

Would your AI-generated tests catch these bugs?

Inspect a passing test suite. Find what it misses. Improve it with the AI tools you already use.

1. Read the ticket and the tests

Ticket SHOP-112 · Checkout: details, totals and refusals

  1. The overview shows a Subtotal (the sum of the item prices), Tax (8% of the subtotal, rounded to the cent) and a Total (subtotal plus tax).
  2. First name, last name and postal code are required. A missing field shows “Error: <field> is required”, naming that field, and checkout doesn't continue.
  3. An empty cart can't be checked out.
  4. Every checkout field has a visible label connected to its input.

Picture the two tests below coming back from an assistant asked to test this ticket. Both pass on the correct shop, and our Playwright test reviewer finds nothing of high or medium severity in them: no fixed waits, no missing awaits, user-facing locators.

We wrote this suite ourselves, in the shape of a quick first draft: it walks the happy path and checks that things appear. It isn't the output of a particular AI tool. To see what yours writes, use the prompt at the end.

test("user can complete checkout", async ({ page }) => {
  await addToCart(page, "Assertion Mug");
  await page.getByTestId("cart-link").click();
  await page.getByRole("button", { name: "Checkout" }).click();
  await page.getByLabel("First name").fill("John");
  await page.getByLabel("Last name").fill("Doe");
  await page.getByLabel("Postal code").fill("12345");
  await page.getByRole("button", { name: "Continue" }).click();
  await expect(page.getByTestId("subtotal")).toBeVisible();
  await expect(page.getByTestId("total")).toContainText("$");
  await page.getByRole("button", { name: "Place order" }).click();
  await expect(page.getByTestId("complete-message")).toBeVisible();
});
test("shows an error for missing fields", async ({ page }) => {
  await addToCart(page, "Assertion Mug");
  await page.getByTestId("cart-link").click();
  await page.getByRole("button", { name: "Checkout" }).click();
  await page.getByRole("button", { name: "Continue" }).click();
  await expect(page.getByTestId("error")).toBeVisible();
});
The top of the spec file: login and helpers

Every test on this page runs under this header, the same one Why did this test pass? uses.

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

// The practice shop's published demo password (see /practice). It unlocks nothing else.
const SHOP_PASSWORD = "practice-only";

test.beforeEach(async ({ page }) => {
  await page.goto("/practice/shop");
  await page.getByLabel("Username").fill("shopper");
  await page.getByLabel("Password").fill(SHOP_PASSWORD);
  await page.getByRole("button", { name: "Log in" }).click();
});

async function addToCart(page, name) {
  await page.getByTestId("product").filter({ hasText: name }).getByRole("button", { name: "Add to cart" }).click();
}

async function checkOut(page, names) {
  for (const name of names) await addToCart(page, name);
  await page.getByTestId("cart-link").click();
  await page.getByRole("button", { name: "Checkout" }).click();
  await page.getByTestId("firstName").fill("Ada");
  await page.getByTestId("lastName").fill("Lovelace");
  await page.getByTestId("postalCode").fill("10115");
  await page.getByRole("button", { name: "Continue" }).click();
}

2. Predict

Each bug below lives in one build of the practice shop. Would this suite fail on that build? Decide from the code, or open the build and try it by hand. Then pick the changes you would ask for.

Your answers stay in this browser only, so you can open a build and come back. Nothing is sent anywhere.

  1. v04With two or more items, the subtotal drops the cents from every price.
    Open v04 in the shop
  2. v05Tax is calculated on the first item only, not on the subtotal.
    Open v05 in the shop
  3. v06The postal code isn't required: checkout continues without one.
    Open v06 in the shop
  4. v07A missing last name shows "Error: First name is required".
    Open v07 in the shop
  5. v09Checkout is possible with an empty cart, and the order goes through with a total of $0.00.
    Open v09 in the shop
  6. v10The postal code label isn't connected to its input, so the field has no accessible name.
    Open v10 in the shop
Which of these changes would catch at least one bug the suite misses? Pick all that do.
The test
test("exact totals for one item", async ({ page }) => {
  await checkOut(page, ["Assertion Mug"]);
  await expect(page.getByTestId("subtotal")).toHaveText("$12.99");
  await expect(page.getByTestId("tax")).toHaveText("$1.04");
  await expect(page.getByTestId("total")).toHaveText("$14.03");
});
The test
test("exact totals for two items", async ({ page }) => {
  await checkOut(page, ["Assertion Mug", "Locator Hoodie"]);
  await expect(page.getByTestId("subtotal")).toHaveText("$62.98");
  await expect(page.getByTestId("tax")).toHaveText("$5.04");
  await expect(page.getByTestId("total")).toHaveText("$68.02");
});
The test
test("totals are shown for two items", async ({ page }) => {
  await checkOut(page, ["Assertion Mug", "Locator Hoodie"]);
  await expect(page.getByTestId("subtotal")).not.toBeEmpty();
  await expect(page.getByTestId("tax")).not.toBeEmpty();
  await expect(page.getByTestId("total")).not.toBeEmpty();
});
The test
test("each missing field is named", async ({ page }) => {
  await addToCart(page, "Assertion Mug");
  await page.getByTestId("cart-link").click();
  await page.getByRole("button", { name: "Checkout" }).click();
  const error = page.getByTestId("error");
  await page.getByRole("button", { name: "Continue" }).click();
  await expect(error).toHaveText("Error: First name is required");
  await page.getByTestId("firstName").fill("Ada");
  await page.getByRole("button", { name: "Continue" }).click();
  await expect(error).toHaveText("Error: Last name is required");
  await page.getByTestId("lastName").fill("Lovelace");
  await page.getByRole("button", { name: "Continue" }).click();
  await expect(error).toHaveText("Error: Postal code is required");
});
The test
test("an empty cart cannot check out", async ({ page }) => {
  await page.getByTestId("cart-link").click();
  await expect(page.getByTestId("cart-empty")).toBeVisible();
  await expect(page.getByRole("button", { name: "Checkout" })).toBeDisabled();
});

0 of 6 bugs predicted

Where the results come from

We ran every test on this page with Playwright 1.63.0 in Chromium on 26 September 2026, against this site's correct shop and the six builds with a checkout bug, using the practice lab's config unchanged. Each test ran twice on each build, with the same result both times. Errors are Playwright's own, cut to the lines that explain the result.

Our first run of the first test also failed on v04 and v05: the login page didn't load within the test timeout, before the shop was asked anything. That is a failure but not a catch, so we ran it again rather than count it.

Every test here is run against the shop again each time this site changes, and the site's own test suite fails if any pass or fail shown on this page stops being true.

Limits

The page checks which options you picked, not your reasoning, and it doesn't run code you write. The practice lab does: run your own suite there and it tells you which bugs it catches.

The bugs are in the shop's JavaScript, which your browser downloads, and the practice lab lists them with an answer key. This challenge is for checking your own judgement, not for proving anything to anyone else.

Answering takes a few minutes on a phone. Running the prompt's tests needs a computer with Node.js.