Playwright Testing
chongdashu/vibejam-starter-pack
Plan, implement, and debug frontend tests: unit/integration/E2E/visual/a11y.
Bulk-regenerate broken test selectors after a UI refactor or redesign.
$ npx skills add petrkindlmann/qa-skills --skill selector-drift-recovery -a claude-codeProject install by default; add -g for ~/.claude/skills/.
$ gh skill install petrkindlmann/qa-skills selector-drift-recovery --agent claude-codeProject scope by default; add --scope user for a personal install. Needs GitHub CLI 2.90.0 or later (public preview).
$ git clone --depth 1 https://github.com/petrkindlmann/qa-skills.git skills-src && mkdir -p .claude/skills && cp -r skills-src/skills/selector-drift-recovery .claude/skills/selector-drift-recovery && rm -rf skills-srcUse ~/.claude/skills/ instead of .claude/skills for a personal install. The folder must contain SKILL.md.
Claude Code skills documentation · loads skills from .claude/skills/
Install the "selector-drift-recovery" agent skill from https://github.com/petrkindlmann/qa-skills/tree/main/skills/selector-drift-recovery into .claude/skills/selector-drift-recovery/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "selector-drift-recovery", then confirm the skill loads.Claude Code copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$skill-installer install https://github.com/petrkindlmann/qa-skills/tree/main/skills/selector-drift-recoveryType this inside Codex. $skill-installer <name> installs a curated skill from openai/skills. The installer writes to $CODEX_HOME/skills (default ~/.codex/skills). Restart Codex if the skill does not show up.
$ npx skills add petrkindlmann/qa-skills --skill selector-drift-recovery -a codexProject install goes to .agents/skills/; add -g for ~/.codex/skills/.
$ gh skill install petrkindlmann/qa-skills selector-drift-recovery --agent codexProject scope by default (.agents/skills/); add --scope user for a personal install.
$ git clone --depth 1 https://github.com/petrkindlmann/qa-skills.git skills-src && mkdir -p .agents/skills && cp -r skills-src/skills/selector-drift-recovery .agents/skills/selector-drift-recovery && rm -rf skills-srcUse ~/.agents/skills/ instead of .agents/skills for a personal install.
Codex skills documentation · loads skills from .agents/skills/
Install the "selector-drift-recovery" agent skill from https://github.com/petrkindlmann/qa-skills/tree/main/skills/selector-drift-recovery into .agents/skills/selector-drift-recovery/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "selector-drift-recovery", then confirm the skill loads.Codex copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$ npx skills add petrkindlmann/qa-skills --skill selector-drift-recovery -a cursorProject install goes to .agents/skills/; add -g for ~/.cursor/skills/.
$ gh skill install petrkindlmann/qa-skills selector-drift-recovery --agent cursorProject scope by default (.agents/skills/); add --scope user for a personal install.
$ git clone --depth 1 https://github.com/petrkindlmann/qa-skills.git skills-src && mkdir -p .cursor/skills && cp -r skills-src/skills/selector-drift-recovery .cursor/skills/selector-drift-recovery && rm -rf skills-srcUse ~/.cursor/skills/ instead of .cursor/skills for a personal install.
Cursor skills documentation · loads skills from .cursor/skills/, .agents/skills/, .claude/skills/, .codex/skills/
Install the "selector-drift-recovery" agent skill from https://github.com/petrkindlmann/qa-skills/tree/main/skills/selector-drift-recovery into .cursor/skills/selector-drift-recovery/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "selector-drift-recovery", then confirm the skill loads.Cursor copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$ gemini skills install https://github.com/petrkindlmann/qa-skills.git --path skills/selector-drift-recovery--scope user (default) or --scope workspace; --path is the subfolder of the repo that holds the skill; --consent skips the security confirmation prompt.
$ npx skills add petrkindlmann/qa-skills --skill selector-drift-recovery -a gemini-cliProject install goes to .agents/skills/; add -g for ~/.gemini/skills/.
$ gh skill install petrkindlmann/qa-skills selector-drift-recovery --agent gemini-cliProject scope by default (.agents/skills/); add --scope user for a personal install.
$ git clone --depth 1 https://github.com/petrkindlmann/qa-skills.git skills-src && mkdir -p .gemini/skills && cp -r skills-src/skills/selector-drift-recovery .gemini/skills/selector-drift-recovery && rm -rf skills-srcUse ~/.gemini/skills/ instead of .gemini/skills for a personal install, then run /skills reload.
Gemini CLI skills documentation · loads skills from .gemini/skills/, .agents/skills/
Install the "selector-drift-recovery" agent skill from https://github.com/petrkindlmann/qa-skills/tree/main/skills/selector-drift-recovery into .gemini/skills/selector-drift-recovery/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "selector-drift-recovery", then confirm the skill loads.Gemini CLI copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$ gh skill install petrkindlmann/qa-skills selector-drift-recoveryInstalls for Copilot at project scope by default; add --scope user for a personal install. Preview a skill first with gh skill preview. Needs GitHub CLI 2.90.0 or later (public preview).
$ npx skills add petrkindlmann/qa-skills --skill selector-drift-recovery -a github-copilotProject install goes to .agents/skills/; add -g for ~/.copilot/skills/.
$ git clone --depth 1 https://github.com/petrkindlmann/qa-skills.git skills-src && mkdir -p .github/skills && cp -r skills-src/skills/selector-drift-recovery .github/skills/selector-drift-recovery && rm -rf skills-srcUse ~/.copilot/skills/ instead of .github/skills for a personal install. Commit .github/skills so cloud agent and code review can use it.
GitHub Copilot skills documentation · loads skills from .github/skills/, .claude/skills/, .agents/skills/
Install the "selector-drift-recovery" agent skill from https://github.com/petrkindlmann/qa-skills/tree/main/skills/selector-drift-recovery into .github/skills/selector-drift-recovery/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "selector-drift-recovery", then confirm the skill loads.GitHub Copilot copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$ npx skills add petrkindlmann/qa-skills --skill selector-drift-recovery -a opencodeOpenCode documents no install command of its own. Project install goes to .agents/skills/; add -g for ~/.config/opencode/skills/.
$ gh skill install petrkindlmann/qa-skills selector-drift-recovery --agent opencodeProject scope by default (.agents/skills/); add --scope user for a personal install.
$ git clone --depth 1 https://github.com/petrkindlmann/qa-skills.git skills-src && mkdir -p .opencode/skills && cp -r skills-src/skills/selector-drift-recovery .opencode/skills/selector-drift-recovery && rm -rf skills-srcUse ~/.config/opencode/skills/ instead of .opencode/skills for a personal install.
OpenCode skills documentation · loads skills from .opencode/skills/, .claude/skills/, .agents/skills/
Install the "selector-drift-recovery" agent skill from https://github.com/petrkindlmann/qa-skills/tree/main/skills/selector-drift-recovery into .opencode/skills/selector-drift-recovery/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "selector-drift-recovery", then confirm the skill loads.OpenCode copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
selector-drift-recoveryBulk-regenerate broken test selectors after a UI refactor or redesign.
Selector Drift Recovery is an agent skill from petrkindlmann/qa-skills. Bulk-regenerate broken test selectors after a UI refactor or redesign. Detects drift between old and new DOM with an aria-snapshot diff, maps old locators to new equivalents using role-first + region scoping, validates against the new build, and produces a single PR with grouped per-file selector updates and per-change evidence. Assumes Playwright = 1.50 (trace viewer DOM-snapshot panel, getByRole filtering, ariaSnapshot). Use when: "UI refactor broke tests," "redesign broke tests," "bulk update selectors,"…
Its SKILL.md is about 5.1k tokens, which your agent loads only when the skill is triggered. The skill folder holds 3 other files, including reference files (for example `references/recovery-scripts.md`).
It sits in Testing & QA, covering Browser testing, Refactoring and Accessibility. It works with Playwright and Selenium. The repository describes itself as: 50 QA and test-automation skills for Claude Code, Codex, Cursor, and any Agent Skills Standard runtime. The licence is MIT.
6 steps, taken from the step headings in SKILL.md.
Read from SKILL.md and the folder at commit b3bb61b. It shows what the files ask for, not the result of running them.
Pre-approves nothing: there is no allowed-tools line, so your agent's usual permission prompts apply.
From allowed-tools in the SKILL.md frontmatter.
Ships script files (JavaScript), which the agent can run.
Shell commands in SKILL.md call:
npxjqghnodegitFrom the folder's file list and the shell code blocks in SKILL.md.
No URLs in SKILL.md. Its commands use npx, gh and git, which can reach the network depending on how they are called.
From URLs in SKILL.md, links to its own repository left out.
Names no API keys, tokens, secrets or passwords.
From names ending in _API_KEY, _TOKEN, _SECRET, _KEY or _PASSWORD in SKILL.md.
Selector Drift Recovery loads about 5.1k tokens when it runs, and up to ~9.4k if it reads all its reference files. Until then it costs about 244 tokens; SKILL.md has 2,559 words of instructions outside code blocks.
Estimates: characters ÷ 4, the usual rule of thumb; real counts depend on the model's tokenizer. Scripts and assets cost tokens only if the agent reads them.
The automated check found no risky patterns in SKILL.md.
Automated static check — not a guarantee. Review scripts before installing. It scans the text of SKILL.md for risky patterns (piping downloads into a shell, reading credential files, hidden Unicode, destructive commands); files beside SKILL.md are not scanned.
The full file from petrkindlmann/qa-skills at commit b3bb61b, republished under its MIT licence (© petrkindlmann). 2,559 words, ~5,075 tokens.
.claude/skills/selector-drift-recovery/SKILL.md (or your agent's skills folder). This skill also uses 2 other files; get the full folder from GitHub.<objective>
A redesign shipped and 23 tests now fail with `TimeoutError: locator.* exceeded` — the DOM moved, not the product. This skill closes that maintenance loop: it diffs the old DOM against the new one, regenerates the broken selectors role-first against the new build, validates the whole suite, and ships the diff as one reviewable PR with a confidence score and screenshot per change. The trigger is an event (a refactor merged), not a flake. The output is a PR a human signs off on — not a silent runtime auto-heal.
This is the bulk, offline, batch counterpart to test-reliability. They share the multi-attribute locator + confidence scoring primitives but run in opposite directions: test-reliability heals one selector at runtime behind a guarded threshold; selector-drift-recovery regenerates N selectors offline against the new DOM and bundles them into a PR. If you are doing the second workflow inside test-reliability, switch here.
</objective>
| Situation | Go to |
|---|---|
| One broken test, not a refactor | Stop — use test-reliability instead |
| 200+ broken selectors across many files | Split by area first (one PR per page/dir), then Phase 1 |
| Refactor changed flows/semantics, not just structure | Stop — rewrite from specs with playwright-automation |
| Framework switch (Selenium → Playwright) | Stop — use test-migration, not drift recovery |
| No old-DOM reference exists anywhere | Capture one (Phase 1) or scope down — without it this is "rewrite tests" |
| Have old + new DOM, ready to map | Phase 1 → 6 below |
Check .agents/qa-project-context.md first — if it exists, use it and skip anything answered there. It identifies your E2E framework, selector strategy, and known fragile areas. Then:
data-testid and the refactor preserved testids, recovery is trivial. If they are CSS-class or XPath based, expect 30–60% to need a new strategy, not just a new locator.error.location points at the failing line. For inline locators that is the locator itself; for POM-wrapped locators it points at the POM helper, not the test. Know this before you trust the auto-extracted line numbers (see Failure Modes).Recovery is event-driven, not failure-driven. Run this when a refactor is planned or just shipped, not when one test goes flaky. One broken test → test-reliability. Ten or more from the same event → this skill.
Old DOM, new DOM, mapped pair. The whole skill rests on a snapshot before the refactor and one after. Everything else is bookkeeping around that pair. Capture both as aria snapshots (await page.locator('body').ariaSnapshot()), not raw HTML — a role-tree diff is exactly the signal role-first recovery needs and ignores the cosmetic churn (class renames, wrapper divs) that a raw-HTML diff drowns in. If you cannot produce both snapshots, fix that first.
Role-first replacement, every time. Even when the old test used CSS, the regenerated selector should prefer getByRole + accessible name, then getByLabel for form fields, then getByTestId when the refactor added one. The recovery PR is your chance to ratchet the average selector stability score up (0–5 rubric below, shared with test-reliability).
Disambiguate by region scoping, not layout selectors. When role+name is ambiguous (two "Submit" buttons), narrow with getByRole('region', { name }).getByRole('button', …) or getByRole(...).filter({ hasText }). Do not reach for :near() / :right-of() — see the Avoid note. A score-3 candidate is one where region scoping has been applied and the locator now matches exactly one element.
One PR, grouped by file, with per-change evidence. Reviewers cannot eyeball 47 selector changes spread across 30 commits. Bundle into one PR, group hunks by test file, attach a confidence score + DOM screenshot per change.
The suite must pass before merge, and dead tests get deleted. A regenerated selector that doesn't run is a worse version of the original problem; the skill ends with green CI, not a generated diff. And if the refactor removed a feature, prune its tests — do not regenerate selectors for elements that no longer exist.
Avoid: Playwright layout selectors
:near(),:right-of(),:left-of(),:above(),:below()as disambiguators — officially deprecated and "may be removed," because a 1px layout shift changes the match (Playwright docs, 2026). They also contradict the role-first thesis. Use region scoping /getByRole().filter()instead.
Six phases, each gated by a check before the next.
You need a snapshot of every page or component the affected tests touch, in its pre-refactor state. Sources, in preference order:
trace: 'on-first-retry'). Download the green-run artifact, open a trace with npx playwright show-trace traces/checkout.zip, select an action, and read the per-action DOM snapshot panel for each surface. (The viewer no longer has a "Copy HTML at this step" menu item; you read the snapshot panel or, for a programmatic dump, replay with page.content() / ariaSnapshot().)git checkout <PRE_REFACTOR_SHA>, start Storybook, and dump each story with a tiny page.content() / ariaSnapshot() script.Output: .drift-recovery/old/<page-or-component>.aria.yml (and .html if you also need raw markup) per affected unit.
Gate: You can answer "what did this page look like when the tests last passed?" from a snapshot file, not from memory.
Run the same surfaces in the post-refactor build — a Vercel/Netlify preview deploy is ideal, or a local dev server / the PR branch in CI. Wait for hydration (await page.waitForLoadState('networkidle')) before snapshotting, or SSR pages give you the pre-hydration tree and you miss client-rendered elements.
Output: .drift-recovery/new/<page-or-component>.aria.yml matching the old set.
Gate: Every old snapshot has a matching new one. If a route 404s in the new build, that flow was deleted — mark its tests for the deletion pile in Phase 6.
For each test file, run against the new build with the JSON reporter, then parse it. Capture, per failure: file, line, old locator string, error type (timeout vs assertion), and inferred intent. Group the results by test file.
TimeoutError: locator.* exceeded. Distinguish it from an assertion failure (expect(...).toBe) so you don't try to re-select a locator that resolved fine but failed a value check..drift-recovery/new/*.aria.yml) so Phase 4 can load the right new DOM.The result is a per-file table:
| Test file | Line | Old locator | Error type | Page route | Inferred intent |
|---|---|---|---|---|---|
tests/checkout.spec.ts | 42 | getByTestId('submit-btn') | timeout | /checkout | Submit the order |
tests/checkout.spec.ts | 87 | locator('.summary > h2') | timeout | /checkout | Read the order total |
See references/recovery-scripts.md for identify-drift.ts, which produces exactly these rows (with the intent/route fields populated, not stubbed).
Gate: Every broken locator has an inferred intent and a page route. If you cannot infer intent, ask the test author or read the original PR — do not guess.
For each row, generate candidates against the new DOM snapshot and score each on the 0–5 rubric (shared with test-reliability). Strategy ladder, best first:
data-testid added by the refactor team — the most stable choice they made. Score 5.getByRole + accessible name, unique on the page. Score 4.getByLabel for a form field, when the intent is an input and a label exists. Score 4 (use over a bare role when the field has no name otherwise).getByRole('region', { name }).getByRole(role, { name }) or .filter({ hasText }) — and confirm the scoped locator now matches exactly one. Only score 3 after scoping makes it unambiguous.getByText). Score 2 — fragile to copy changes.| Score | Replacement strategy | Auto-apply? |
|---|---|---|
| 5 | New data-testid exists | yes |
| 4 | getByRole + accessible name (or getByLabel), unique on page | yes |
| 3 | getByRole + name, region-scoped to exactly one match | yes |
| 2 | Visible-text-only | no |
| 1 | CSS class on changed structure | no |
| 0 | No safe replacement found | no — flag for human |
A candidate is score 3 only if scoping already resolved it to a single element. A still-ambiguous multi-match (count > 1, "needs scoping") is not a 3 — it is unfinished, and must not be auto-applied.
Output: .drift-recovery/candidates.json with { file, line, oldLocator, selector, score, rationale, screenshotPath } per change. See references/recovery-scripts.md for generate-candidates.ts.
Gate: Every row has a candidate scored ≥ 3 (and confirmed unique), or is flagged for human review. Score-0/1/2 are never auto-applied.
(file, line), not a content-wide string replace — the reporter's locator string is a rendered form (locator('.summary > h2')) that rarely matches the source expression verbatim, and a naive String.replace hits only the first occurrence and collides on identical locators. Edit the specific line; set applied: true on each candidate you actually wrote.Gate: Recovered tests pass the suite. Flagged tests are clearly marked, not silently included.
The PR is the deliverable. Title: chore(tests): selector recovery after <refactor description>. Body (generated from candidates.json, filtering on applied):
## Trigger
<Link to the refactor PR / describe the redesign>
## Summary
- N test files updated - M selectors changed
- K tests deleted (feature removed) - L tests flagged for manual review
## Per-file changes
<For each file: a table of line, old, new, score, screenshot URL>
## Flagged for review
<Tests where no candidate scored >= 3, with the inferred intent>
## How to review
- Check each screenshot: does `new` point at the element `old` pointed at?
- For score-3 candidates, verify the region scope is meaningful in the new design.
- For flagged tests, decide: rewrite, delete, or accept a manual selector update.Attach screenshots inline via your team's CI artifact URL pattern. See references/recovery-scripts.md for apply-recovery.ts (line-anchored) and build-pr-body.ts.
Gate: PR is reviewable in one sitting. Too large → split by area (one PR per page / component / test directory).
Auto-applying score-0, -1, or -2 candidates. A score-2 is "we found some element." That is gambling, not recovery — and it is the usual cause of a suite-wide stability score dropping after a recovery. Auto-apply only score ≥ 3.
Calling an ambiguous multi-match "score 3." If getByRole(...) returns >1 element it is not a 3 until region scoping narrows it to exactly one. Scoring it 3 and auto-applying ships a locator that resolves to the wrong element.
Skipping the screenshots. A score-4 candidate can still point at the wrong element when the page has two regions with the same role + name. The per-change screenshot is the only check that catches semantic drift; confidence scores alone do not.
Content-wide string replace instead of line-anchored edits. content.replace(oldLocator, …) hits the first occurrence only, collides on duplicate locators, and silently no-ops when the reporter's rendered string differs from the source expression. Edit the specific (file, line).
Trusting auto-extracted line numbers for POM-wrapped locators. The JSON reporter's error.location points at the failing line, which for a Page Object is the helper, not the test. Re-read the locator from the trace action or grep the POM source before applying.
Recovering tests for deleted features. The refactor may have removed flows. Map deleted routes in Phase 2 and prune those tests — do not regenerate selectors for elements that no longer exist.
Auto-merging the recovery PR in CI. The PR is the artifact; the whole point is a human eyeballing the per-change evidence. Auto-merge once tests pass defeats the purpose — a green suite with a selector pointing at the wrong-but-present element passes and erodes trust. Require a reviewer.
Treating the PR as urgent. A failed suite feels urgent; a correctly recovered one is what matters. Time pressure produces score-2 replacements that quietly degrade the suite.
| Symptom | Likely cause | Fix or check |
|---|---|---|
identify-drift.ts finds 0 failures despite red CI | Suite errored before producing the JSON report, or you parsed the wrong file | jq '.stats' .drift-recovery/results.json; confirm --reporter=json redirected to the file |
| Extracted line points at a POM file, not the test | Locator is wrapped in a Page Object | Read the locator from the trace action, or grep the POM source for the rendered string |
generate-candidates.ts reads undefined for intent/route | Phase 3 output missing the inferred-intent / page-route fields | Populate them in Phase 3 — they are not in the reporter; the generator cannot infer them |
| New-DOM snapshot is missing client-rendered elements | Snapshotted before hydration | Add await page.waitForLoadState('networkidle') before ariaSnapshot() |
| Average stability score dropped after recovery | Score-2/CSS candidates auto-applied | Revert candidates with score < 3 in candidates.json; only role/label/testid should land (see scorer below) |
Run these on the recovery branch before opening the PR, smallest first:
# 1. No applied candidate is below the stability floor (machine-checkable proxy for "ratcheted up")
node references/score-candidates.mjs .drift-recovery/candidates.json
# prints average score + count of applied rows with score < 3 — that count MUST be 0
# 2. The recovered suite is green against the new build
PLAYWRIGHT_TEST_BASE_URL=$PREVIEW_URL npx playwright test --reporter=json \
| jq '.stats.unexpected' # must be 0 (flagged tests excluded via grep/skip)
# 3. The PR exists with the evidence body
gh pr view --json title,body -q '.title' # contains "selector recovery"references/score-candidates.mjs reads candidates.json, prints the average applied score and the count of applied && score < 3 rows; a non-zero count means a low-confidence selector leaked in. Step 1 passing + step 2 returning 0 is the proof the recovery worked.
references/score-candidates.mjs candidates.json reports 0 applied candidates with score < 3.gh pr view succeeds) with per-change evidence: confidence score and screenshot per change, grouped by file.npx playwright test --reporter=json | jq '.stats.unexpected' returns 0 on the recovery branch..agents/qa-project-context.md describing the refactor and any new test patterns introduced.references/)identify-drift.ts (populates intent + route), generate-candidates.ts (region-scoping ladder, true score-3), line-anchored apply-recovery.ts, and build-pr-body.ts. Includes the Cypress-adaptation note.© petrkindlmann, MIT. Rendered from Markdown: HTML in the file is shown as text, images as links, and headings moved down two levels. Raw file
SKILL.md and 2 other files (references) in skills/selector-drift-recovery of petrkindlmann/qa-skills.
Open the folder on GitHubat commit b3bb61b
Selector Drift Recovery next to the 5 skills that share the most tags, products or categories with it. Stars are the repository's; “used in” counts other GitHub owners with a copy.
| Skill | Stars | Used in | Tokens | Auto-check | Licence | Repo updated |
|---|---|---|---|---|---|---|
| Selector Drift Recovery this skillpetrkindlmann/qa-skills | 170 | — | ~5.1k | Automated safety check: Pass | MIT | |
| Playwright Testingchongdashu/vibejam-starter-pack | 149 | — | ~2.2k | Automated safety check: Pass | None | |
| Testingradix-ng/primitives | 274 | — | ~3.3k | Automated safety check: Pass | MIT | |
| Web Testing with Playwright and Vitestwithkynam/vibecode-pro-max-kit | 1.1k | — | ~892 | Automated safety check: Pass | Apache-2.0 | |
| Playwright Proalirezarezvani/claude-skills | 28k | 1 repos | ~1.4k | Automated safety check: Pass | MIT | |
| Playwright Visual Testingmanagedcode/dotnet-skills | 486 | — | ~1.9k | Automated safety check: Pass | MIT |
chongdashu/vibejam-starter-pack
Plan, implement, and debug frontend tests: unit/integration/E2E/visual/a11y.
radix-ng/primitives
Test Radix NG primitives across every layer and pick the RIGHT one for a change: Vitest unit (zoneless), jest-axe a11y, Playwright browser regression (apps/visual-regression), SSR…
withkynam/vibecode-pro-max-kit
Covers web testing from unit to E2E, load, visual, accessibility and security checks, with Playwright, Vitest and k6 guides plus a Playwright setup script.
alirezarezvani/claude-skills
Production-grade Playwright testing toolkit. An agent skill from alirezarezvani/claude-skills.
managedcode/dotnet-skills
Add, repair, or review Playwright visual regression tests for browser-facing .NET apps, including screenshot baselines, Pixelmatch thresholds, deterministic rendering, and GitHub Actions artifacts.
borghei/Claude-Skills
End-to-end testing with Playwright: test generation, page objects, locator strategy, flaky- test diagnosis, visual regression, and CI integration.
petrkindlmann/qa-skills
Test for WCAG 2.2 AA compliance with axe-core + Playwright, keyboard navigation audits, screen reader testing, ARIA pattern validation, and legal compliance mapping (ADA, EAA, Section 508).
petrkindlmann/qa-skills
Goal-driven E2E testing where a browser agent (Playwright MCP / computer-use) reads a natural-language goal and explores the app via the accessibility tree to assert outcomes — no pre-written script.
petrkindlmann/qa-skills
Use AI to write NEW test code from specs, PRDs, user stories, code diffs, bug reports, or OpenAPI specs.
petrkindlmann/qa-skills
Test REST and GraphQL APIs with Playwright APIRequestContext, Supertest, or standalone HTTP clients.
petrkindlmann/qa-skills
Design CI/CD pipelines that run test suites. An agent skill from petrkindlmann/qa-skills.
petrkindlmann/qa-skills
Test for regulatory compliance: GDPR/CMP consent verification, Google Consent Mode v2, Global Privacy Control (GPC), CCPA/US state opt-out, EU AI Act Article 50 transparency, Better Ads Standards…
Works with
Categories
Bulk-regenerate broken test selectors after a UI refactor or redesign. Selector Drift Recovery is an agent skill from petrkindlmann/qa-skills. Bulk-regenerate broken test selectors after a UI refactor or redesign.
Selector Drift Recovery fits situations like: : UI refactor broke tests; redesign broke tests; bulk update selectors; regenerate selectors after refactor.
Run `npx skills add petrkindlmann/qa-skills --skill selector-drift-recovery -a claude-code`. Or copy the skill folder (skills/selector-drift-recovery in petrkindlmann/qa-skills) into .claude/skills/selector-drift-recovery in your project. Claude Code loads it when a task matches its description.
Run `npx skills add petrkindlmann/qa-skills --skill selector-drift-recovery -a codex`. Or copy the skill folder (skills/selector-drift-recovery in petrkindlmann/qa-skills) into .agents/skills/selector-drift-recovery in your project. Codex loads it when a task matches its description.
Cursor, Gemini CLI, GitHub Copilot and OpenCode also load SKILL.md folders. With the skills CLI, run `npx skills add petrkindlmann/qa-skills --skill selector-drift-recovery -a cursor` (or -a gemini-cli, github-copilot or opencode for the others). To copy it by hand, put the folder in .cursor/skills/selector-drift-recovery, .gemini/skills/selector-drift-recovery, .github/skills/selector-drift-recovery and .opencode/skills/selector-drift-recovery in your project.
Going by SKILL.md and its folder, Selector Drift Recovery needs JavaScript for the scripts in its folder and the command-line tools its instructions call (npx, jq, gh, node and git). Our summary lists: Node.js.
SKILL.md contains no URLs. Its commands use npx, gh and git, which can reach the network depending on how they are called. This is read from the text; nothing was executed.
Our automated static check of SKILL.md found no risky patterns, such as piping downloads into a shell, reading credential files or hidden Unicode. It is not a guarantee. Review the folder before installing.
Selector Drift Recovery is published under the MIT licence (declared in SKILL.md). It allows redistribution, so the full SKILL.md is shown on this page.
About 5.1k tokens (SKILL.md is roughly 20k characters). Agents keep only the skill's name and description in context until a task matches; then they load SKILL.md in full. Its references folder adds about 4.3k tokens, read only when the agent opens those files.
Skills that share tags, products or a category with Selector Drift Recovery: Playwright Testing (chongdashu/vibejam-starter-pack, 149 stars), Testing (radix-ng/primitives, 274 stars), Web Testing with Playwright and Vitest (withkynam/vibecode-pro-max-kit, 1.1k stars) and Playwright Pro (alirezarezvani/claude-skills, 28k stars). The comparison table on this page puts their stars, adoption, token cost, safety result and licence side by side.
petrkindlmann (a GitHub user) maintains it in petrkindlmann/qa-skills, which has 170 GitHub stars. The repository holds 45 skills in this directory. The repository was last updated on June 10, 2026.
Source: petrkindlmann/qa-skills on GitHub. Facts on this page come from the repository at the commit we read; the author's words are quoted as theirs.