Skip to content

About

Playwright + Page Object Model + Agent-Driven Test Automation

Resources

Stars

0 stars

Watchers

0 watching

Forks

Repository files navigation

Playwright + Page Object Model + Agent-Driven Test Automation

A Playwright TypeScript test suite built around the Page Object Model, a small local sample app with seed data to test against, and a workflow for turning Jira tickets into reviewed test plans and publishing results to TestRail.

Contents


Project structure

playwright-agent/
├── .claude/agents/            # Playwright Planner/Generator/Healer agent definitions
├── .github/workflows/
│   ├── playwright.yml         # runs the suite, reports results to TestRail on push
│   └── jira-plan.yml          # PR trigger that fetches a Jira description into a plan
├── .mcp.json                  # registers the Playwright MCP server for Claude Code
├── app/                       # local sample app under test (static HTML/CSS/JS)
├── data/                      # sample data (users, products, coupons) — seeds the app AND the tests
├── pages/                     # Page Object Model classes
├── components/                # shared widgets composed into page objects (e.g. NavBar)
├── fixtures/                  # Playwright fixtures that inject page objects + sample test data
├── scripts/
│   ├── jira/                  # Jira → test plan fetcher
│   └── testrail/              # test results → TestRail publisher
├── tests/
│   ├── seed.spec.ts           # authenticated start state, copied by generated tests
│   ├── plans/                 # Markdown test plans (human/Planner/Jira-sourced input for the Generator)
│   └── e2e/                   # the actual .spec.ts test files
├── server.js                  # zero-dependency static file server for app/
├── playwright.config.ts
└── .env.example                # required env vars for the Jira/TestRail scripts

The sample app

There's no external site to point this suite at, so app/ is a small, dependency-free static app (login → products → cart → checkout → confirmation) served locally by server.js. It exists purely as something realistic to test — swap it for your real app by changing baseURL and the webServer command in playwright.config.ts, and update the page objects' selectors to match.

Sample data lives in data/*.json and is used by both the app (fetched over HTTP at runtime) and the tests (imported directly in fixtures/test-data.ts), so there's a single source of truth:

File Contents
data/users.json One valid user, one locked-out user
data/products.json Four sample products
data/coupons.json Two coupon codes (SAVE10, SAVE20)

The checkout form also recognizes a hardcoded decline test card (4000000000000002, the standard Stripe test-decline number) to exercise the payment-failure path.

Getting started

npm install
npx playwright install --with-deps   # first time only, installs browser binaries
cp .env.example .env                 # only needed for the Jira/TestRail scripts — see below

Running tests

npm test              # headless, all projects — starts app/ automatically via webServer
npm run test:headed   # same, with a visible browser
npm run report        # opens the last HTML report

You don't need to start the app yourself — playwright.config.ts has a webServer entry that runs node server.js and waits for http://127.0.0.1:4173 before tests start (and reuses an already-running server locally). npm run serve starts it standalone if you want to poke at the app manually.

Playwright UI mode

npm run test:ui

This opens Playwright's interactive UI mode — the fastest way to work on this suite day to day:

  • Test list on the left, grouped by file/describe block; click any test to run just that one.
  • Watch mode: leave it open while editing a .spec.ts or a page object — it reruns automatically on save.
  • Timeline scrubber: step through every action in a run (click, fill, navigation) and see the DOM snapshot at that instant, alongside network and console logs.
  • Pick locator: hover the page preview to get a suggested Playwright locator for anything on screen — useful when extending a page object.
  • Trace viewer built in: failed tests show their full trace (screenshots, network, actions) without needing npx playwright show-trace separately.

Run a single file or grep a title from the CLI instead if you don't need the UI:

npx playwright test tests/e2e/checkout.spec.ts
npx playwright test -g "coupon"

Page Object Model

  • pages/*.page.ts — one class per page (LoginPage, ProductsPage, CartPage, CheckoutPage), extending pages/base.page.ts. Locators use getByRole / getByLabel / getByTestId only — no CSS or XPath — so they stay resilient and stay legible to the agents that generate/heal tests.
  • components/nav-bar.component.ts — the nav bar is identical across pages, so it's a composed component (page.nav) rather than duplicated locators in every page object.
  • Page objects hold no assertions — they expose locators and actions; the expect() calls live in the test files.
  • fixtures/page-fixtures.ts injects loginPage / productsPage / cartPage / checkoutPage into test() via fixtures, so specs never do new LoginPage(page) by hand.
  • fixtures/auth-fixtures.ts overrides the page fixture to sign in as the sample valid user first — use this (import { test, expect } from '../../fixtures/auth-fixtures') for any test that needs to start already logged in, instead of repeating the login flow.
  • fixtures/test-data.ts re-exports data/*.json as typed sample data (validUser, sampleProducts, validCoupon, declinedCardNumber, …) for tests to consume directly.

Agent-driven test generation

.claude/agents/ and .mcp.json were generated by npx playwright init-agents --loop=claude and wire up Playwright's official Planner / Generator / Healer agents through the Playwright MCP server:

  1. Planner (@playwright-test-planner) explores a flow and writes a Markdown plan to specs/ (or tests/plans/ — see the Jira integration below, which writes there too).
  2. Generator (@playwright-test-generator) turns an approved plan into a real .spec.ts file using the existing page objects and fixtures.
  3. Healer (@playwright-test-healer) inspects a failing test against the live app and patches selectors/assertions, or marks it fixme if the app itself is broken.

Always review Planner output before generating, and review Generator/Healer output like a PR before merging

Jira integration

npm run jira:fetch -- PROJ-123 pulls an issue's summary and description straight from Jira and writes it as Planner input.

Setup — add to .env (or CI secrets):

JIRA_BASE_URL=https://your-team.atlassian.net
JIRA_EMAIL=you@example.com
JIRA_API_TOKEN=            # Atlassian API token, not your password

Generate an API token at id.atlassian.com → Security → API tokens.

What it does:

  1. Calls GET /rest/api/3/issue/{key} with Basic auth (email:token).
  2. Converts the description from Jira's Atlassian Document Format (rich-text JSON) to Markdown — headings, bold/italic/code, links, bullet/ordered lists, code blocks, and blockquotes are all handled (scripts/jira/adf-to-markdown.js).
  3. Writes tests/plans/PROJ-123.md, formatted the same way as tests/plans/checkout-flow.md, with a ## Description section and an empty ## Scenarios section left for a human (or the Planner agent) to fill in.

This is intentionally a fetch, not a full plan — the description alone isn't enough to write good test scenarios from, so the Scenarios section is left for review, matching the "always review Planner output" rule above.

Automatic PR trigger — .github/workflows/jira-plan.yml runs on every PR open/edit/sync:

  1. Extracts a Jira key (pattern [A-Z][A-Z0-9]+-[0-9]+) from the PR title, falling back to the branch name.
  2. If found, runs the same fetch script and uploads the result as a workflow artifact (jira-plan-PROJ-123).
  3. Posts (or updates, on subsequent pushes) a single PR comment containing the fetched plan.

It deliberately does not commit the plan file back to the branch — a human downloads it from the artifact/comment and commits it under tests/plans/ once they've reviewed it, keeping the same review gate as manually-run Planner output.

Requires repo secrets JIRA_BASE_URL, JIRA_EMAIL, JIRA_API_TOKEN to be set for the workflow to actually fetch anything; without them the step still runs but the Jira request will fail (the workflow doesn't currently no-op gracefully on missing secrets the way the TestRail script does).

TestRail integration

npm run report:testrail reads Playwright's JSON report and publishes results to a new TestRail run.

Setup — add to .env (or CI secrets):

TESTRAIL_BASE_URL=https://your-team.testrail.io
TESTRAIL_USERNAME=you@example.com
TESTRAIL_API_KEY=          # generate under My Settings → API Keys
TESTRAIL_PROJECT_ID=
TESTRAIL_SUITE_ID=         # only needed if the project has multiple suites

Case-ID convention: tag each test title with its TestRail case ID, prefixed C:

test('C1001 user can sign in with valid credentials', async ({ loginPage, page }) => {
  ...
});

All 12 reportable tests in tests/e2e/ are already tagged this way (C1001–C1012) as a working example — these are placeholder IDs; replace them with real case IDs from your TestRail project before relying on the report. tests/seed.spec.ts is deliberately left untagged since it's setup, not a reportable case — untagged tests are silently skipped by the reporter, so tag only the tests that map to real TestRail cases.

What it does (scripts/testrail/report-results.js):

  1. Reads test-results/results.json (written by the json reporter configured in playwright.config.ts — this only exists if you ran playwright test with the default reporters, not --reporter=list).
  2. Walks the suite tree, extracts the C<id> from each test's title, and maps its last attempt's status to a TestRail status: passed → 1, failed/timedOut/interrupted → 5. Tests without a C<id> tag, or with no mapped status (e.g. skipped), are left out of the report.
  3. Creates a new run via add_run scoped to just the case IDs seen in this execution (include_all: false), then bulk-submits results via add_results_for_cases, including duration and any error message as the result comment.

If any of the four required env vars are missing, the script logs a message and exits 0 instead of failing — so it's safe to leave in a pipeline before secrets are configured.

CI wiring — .github/workflows/playwright.yml runs this after the test step, but only on push (not on every PR), so TestRail doesn't fill up with in-progress PR runs. It reads the same four (plus optional fifth) vars from repository secrets.

CI/CD

  • .github/workflows/playwright.yml — installs dependencies and browsers, runs playwright test, reports to TestRail on push, and uploads the HTML report as a build artifact regardless of outcome.
  • .github/workflows/jira-plan.yml — see Jira integration above.

playwright-agent

About

Playwright + Page Object Model + Agent-Driven Test Automation

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages