Three tiny, self-contained Playwright projects that reproduce real bug patterns discussed in interview prep: lost UTM parameters, missing legal disclosure text, and flaky tests. No external services, no API keys, no real network calls. Everything runs against local HTML fixtures.
npm install
npx playwright install --with-deps chromiumnpm testnpm run test:utm # Project 1
npm run test:disclosure # Project 2
npm run test:flaky # Project 3What it simulates: A campaign email link redirects through a tracking script before landing on the final offer page. Somewhere in that chain, one UTM parameter silently disappears.
What you'll see: The test fails. Open fixtures/redirect-buggy.html,
read the bug comment, uncomment the missing line, save, and run
npm run test:utm again. Watch it go from red to green.
What this teaches: How to follow a redirect with page.waitForURL(),
how to parse query parameters out of the final URL with the built-in
URL and URLSearchParams objects, and what it actually looks like when
a test catches a real attribution-breaking bug.
What it simulates: A vacation ownership company sends a discounted package email that legally requires disclosure language about a mandatory sales presentation. A templating bug strips that disclosure block from one version of the email.
What you'll see: Two tests run. The "correct email" test passes. The "buggy email" test fails on purpose, demonstrating exactly how this kind of check would catch a real compliance risk before a campaign ships.
What this teaches: Text-content assertions with toContainText(),
and how to think about QA checks that protect against legal exposure,
not just broken buttons.
What it simulates: A page where content loads after a 1.5 second delay, just like a real API call or network response.
What you'll see: The "BAD pattern" test uses an artificially short 100ms timeout and fails almost every time. The "GOOD pattern" test uses Playwright's default timeout, which polls and retries automatically, and passes reliably every time.
What this teaches: Why flaky tests happen (checking before the condition is true) and the actual fix (let Playwright's built-in retry behavior do the waiting instead of guessing a fixed delay).
Run Project 3 first. It's the easiest to understand at a glance and teaches the single most common interview topic: "tell me about a flaky test you've fixed."
Run Project 1 second. It directly mirrors the UTM tracking question from interview prep.
Run Project 2 last. It's the most specific to the HGV-style compliance angle and the most likely to set you apart from other candidates if it comes up.
Once all three pass, try converting tests/flaky-fix.spec.ts to Python
as a side exercise. The Playwright Python API is nearly a line-for-line
translation:
from playwright.sync_api import Page, expect
def test_good_pattern_waits_for_the_actual_condition(page: Page):
page.goto("file:///path/to/fixtures/async-loader.html")
page.click("#loadBtn")
expect(page.locator("#result")).to_have_text("Offer Details Loaded")That's the whole gap between the two languages: camelCase becomes
snake_case, semicolons disappear, and expect() comes from a different
import. You don't need to relearn how testing works, just the syntax.