qa-copilot-lab
v0.3.0
Published
Local practice target site for the Playwright MCP for QA course — every common locator strategy, a chaos mode for self-healing practice, seeded bugs for exploratory testing, and a reset API for CI.
Readme
QA Copilot Lab
A local practice target site for the Playwright MCP for QA course. It is a small e-commerce app deliberately built so every common Playwright locator strategy has a real place to be exercised — plus a chaos mode, seeded bugs, and a reset API for self-healing and CI exercises.
Run it
Requires Node.js 22.13 or newer (uses the built-in node:sqlite module —
no native addon to download or compile, so npx qa-copilot-lab works the
same on any machine without build tools installed).
npm install
npm startThen open http://localhost:4173. Login with qa_student / Passw0rd!.
Flags:
npm start -- --fresh # wipe local data and reseed
npm start -- --port=5000 # run on a different port
npm start -- --host=0.0.0.0 # bind every interface (reachable from other devices on the LAN)Default binding is 127.0.0.1 (this machine only). Use --host=0.0.0.0
(or HOST=0.0.0.0 npm start) if you need to reach the app from another
device on the same network — e.g. testing from a phone, VM, or a
Playwright run inside a container. Anyone on that network can then reach
it, so only do this on networks you trust.
Where your data lives
All data is stored in a single SQLite file at ~/.qa-copilot-lab/data.db
(printed on every startup). Restarting the app does not erase it —
only an explicit reset does:
curl -X POST http://localhost:4173/api/__resetDev / test control API
| Method | Route | Purpose |
| --- | --- | --- |
| POST | /api/__reset | Restore seed data, clear cart, turn off chaos/bugs |
| POST | /api/__chaos/:mode | off | mild (class names drift) | aggressive (class and testid drift) |
| POST | /api/__seed-bugs/:setId | off | 1 | 2 — inject a known defect for exploratory testing |
| POST | /api/__flaky/:mode | slow | off — checkout randomly (coin flip) responds fast or takes 3s, so a tight timeout flakes on timing alone |
| GET | /api/__health | Readiness check for CI |
Locator practice
Visit /locators for thirty-six isolated examples: sixteen general locator
strategies (role, label, placeholder, alt text, title, testid, text match,
CSS attribute, XPath axes, chained filter, nth, frame locator, shadow DOM,
ARIA state, disabled state, native dialog) plus twenty ARIA roles for
getByRole (textbox, checkbox, combobox, slider, switch, navigation,
heading, list, listitem, table, row, cell, columnheader, dialog, alert,
progressbar, status, img, tab/tabpanel, search) — the same strategies used
throughout the real storefront pages.
Why these choices
- Node.js + Express + EJS — no build step and nothing to compile at all;
storage uses Node's built-in
node:sqliteinstead of a native addon, so there's no prebuilt-binary/toolchain mismatch to hit on a fresh machine. - SQLite in the user's home directory — survives restarts, and
--freshgives an explicit, deliberate way to wipe it. - No Docker, no bundled browser — the app is a webpage; Playwright brings its own browser.
