Install
$ agentstack add skill-igorsolop0-qa-claude-skills-pw-pom-generator ✓ scanned · ✓ verified — works with Claude Code, Cursor, and more.
Security review
✓ PassedNo issues found. Passed automated security review. · v0.1.0 How review works →
- ✓ Prompt-injection patterns
- ✓ Secret / credential exfiltration
- ✓ Dangerous shell & filesystem operations
- ✓ Untrusted network calls
- ✓ Known-malicious package signatures
What it can access
- ✓ Network access No
- ✓ Filesystem access No
- ✓ Shell / process execution No
- ● Environment & secrets Used
- ✓ Dynamic code execution No
From automated source analysis of v0.1.0. “Used” means the capability is present in the source — more access means more to trust, not that it’s unsafe.
About
pw-pom-generator
Scaffold a per-flow Playwright suite that follows the Page Object Model + typed presets pattern. The skill emits three files (Page Object, presets, spec) plus optional constants, all consistent with each other and ready to run after the user fills in placeholders for auth/setup.
When to trigger
Trigger when the user asks to:
- "Scaffold Playwright tests for ``"
- "Generate a POM / page object for this page"
- "Create page object + presets + spec"
- "Write a Playwright spec from these exploration notes"
- Any time they hand you a list of locators / scenarios and want runnable scaffold code
Do not trigger for:
- Reviewing existing tests (use
pw-test-reviewinstead) - Running tests / debugging failures
- Setting up a new Playwright project from scratch (no
playwright.config.tshere — assume one exists)
Inputs to collect
Ask once, then proceed. Don't drag the user through a form.
- Flow slug — kebab-case (
buy-position,checkout,login). Becomes the folder name and file prefix. - Locators — list of things to interact with on the page. Any format the user gives you is fine (bullet list, paste from exploration doc, JSON). Each locator needs at least a human name (
submit button) and a recognizable identifier (role+name, label, placeholder, text, or as a last resort CSS). - Scenarios — minimum one happy path. Negative / gap-coverage / validation cases are optional but recommended.
- Project conventions (if not obvious from a quick scan): fixture path (
tests/fixtures/*.ts), module system (ESM with.jssuffix on TS imports, or plain CJS/no-suffix), TypeScript or JS. - Auth/setup hooks (optional) — if the flow needs login, wallet connect, API seeding, etc. Capture where they happen (before the form, mid-flow) so placeholders land in the right spot.
If the user has an exploration report or notes doc, accept it as-is. Don't require a specific schema.
Output layout
tests//
├── .page.ts # Page Object — locators + high-level actions
├── .presets.ts # Typed test data presets
└── .spec.ts # Test cases — no raw selectors
If the project already has a tests/components/ or tests/fixtures/ folder, compose shared components (header, modal, toast) from there instead of redefining them in the POM. See [references/layout-guide.md](references/layout-guide.md) for the full convention (shared src/, constants split, ESM .js suffix gotcha).
Workflow
Step 1 — Classify each input
Before writing files, sort the user's notes into buckets:
| Belongs in... | What goes there | |----------------------------------------|---------------------------------------------------------------------------------| | tests//.page.ts | Flow-specific locators + high-level actions; composes shared components | | tests//.presets.ts | Strongly-typed test-data fixtures (named consts: minimumPreset, fullPreset) | | tests//.spec.ts | Test cases. No raw selectors. | | src/constants/.ts (if exists) | URL regexes, copy regexes (button labels, success headings), enum-like maps | | tests/components/ | UI primitives shared with other flows (header, tx modal, toasts, sidebar) |
If a constant or component already exists, reuse it. Do not duplicate.
Step 2 — Write the Page Object
See [references/page-object-template.md](references/page-object-template.md).
Key rules:
- Constructor takes
Page, assigns fields in the body (avoidconstructor(public readonly page)— fails on Node 24 strip-only TS) - One getter per locator, camelCase names
- Locator priority:
getByRole→getByLabel→getByPlaceholder→getByText({ exact: true })→getByTestId→ CSS (anchored on[name]/[data-*], nevernth(i)) - High-level actions compose multiple locators (
fillFromPreset(preset),expand(section),submit()) goto()method for the entry URL — acceptbaseUrlas a parameter, don't hard-code it
Step 3 — Write the presets
See [references/presets-template.md](references/presets-template.md).
- Define a
Presettype that mirrors the form/inputs the user described - Export at least one named const (
minimumPreset); add more if the user gave multiple scenarios - If two preset fields are coupled (e.g. "Field B only valid when Field A is X"), encode the constraint with a
// TODO:comment, not a runtime check
Step 4 — Write the spec
See [references/spec-template.md](references/spec-template.md).
- Default fixture import is
@playwright/testunless the project has a custom fixture (tests/fixtures/*.ts) — if so, ask the user which one and use it - Auth / wallet / login steps are marked with
// SETUP_REQUIRED:placeholders the user fills in. Never emit fake auth code (mock tokens, hardcoded sessions,localStorage.setItemhacks) — placeholders are honest, fakes break in CI - Use web-first assertions:
expect(...).toBeVisible(),.toHaveText(),.toBeEnabled(),.toHaveURL() - No
page.waitForTimeout(...),networkidle(for non-navigation waits),force: trueclicks, ortoContainTexton numeric values (false-positive risk —"1"contains"") - Pull timeouts from config / constants if the project has them; otherwise rely on Playwright's defaults
- Don't add browser teardown — fixtures own that
Step 5 — Optional: constants file
If the user's notes contain repeated regexes (URL patterns, success-modal headings, button label variants), extract them to src/constants/.ts (or wherever the project keeps constants). If no such folder exists, inline them at the top of the spec as const declarations.
Step 6 — Suggest the npm script
Tell the user (do not silently edit package.json) to add:
"test:": "playwright test tests/"
If the project uses dotenv or another loader (visible from existing scripts), match that pattern.
Step 7 — Print a summary
✓ tests//.spec.ts — X tests across Y describe blocks
✓ tests//.page.ts — Z locators, N actions[, composes , ]
✓ tests//.presets.ts — M presets exported
✓ src/constants/.ts — K constants (if new; otherwise list reused)
Coverage breakdown:
- Happy path: ...
- Validation: ...
- Gap / negative: ...
SETUP_REQUIRED markers: N (lines: ...)
Suggested npm script: "test:": "playwright test tests/"
Stop after this. Do not execute the tests — the user runs them.
Hard rules
- No raw selectors in spec files. Always go through the Page Object or a shared component.
- No
test.skipto hide unimplemented setup. Usetest.fixme()with a comment explaining what's missing. - No teardown that closes the browser — fixtures own lifecycle.
- No
expect(...).toContainText('1')— substring on numeric strings false-positives ("10"contains"1"). UsetoHaveTextor anchored regex. - No comments explaining the obvious. Names should carry the meaning.
References (load on demand)
- [
references/layout-guide.md](references/layout-guide.md) — project layout conventions, ESM.jssuffix gotcha, sharedsrc/vstests/components/decision tree - [
references/page-object-template.md](references/page-object-template.md) — full POM template with composition example - [
references/presets-template.md](references/presets-template.md) — typed presets template - [
references/spec-template.md](references/spec-template.md) — spec template withSETUP_REQUIREDplaceholder pattern
Source & license
This open-source skill is cataloged on AgentStack and links to its original source — we do not rehost the code.
- Author: Igorsolop0
- Source: Igorsolop0/qa-claude-skills
- License: MIT
Install and usage instructions live in the source repository linked above.
Reviews
No reviews yet — be the first.
Write a review
Versions
- v0.1.0 Imported from the upstream source.