Now liveThe Skillselion MCP - thousands of ranked skills, loaded into your agent mid-task. No install.Get it →
dungluonghoang avatar

Selector Healing

  • 1 installs
  • Updated May 12, 2026
  • dungluonghoang/k-fresh-02026

Heal broken Playwright locators after DOM changes by diagnosing the drift, proposing a stable getByRole/data-test replacement, and patching the centralized locators class.

About

Diagnoses Playwright locator drift and replaces brittle selectors with stable role or test-id locators in the centralized locators class, then reruns the spec. A developer uses it when a test fails because the DOM changed.

  • Priority ladder from getByRole down to XPath
  • Edits only centralized locators classes, never specs

Selector Healing by the numbers

  • 1 all-time installs (skills.sh)
  • Ranked #1,750 of 2,153 Testing & QA skills by installs in the Skillselion catalog
  • Data as of Jul 8, 2026 (Skillselion catalog sync)
npx skills add https://github.com/dungluonghoang/k-fresh-02026 --skill selector-healing

Add your badge

Show developers this skill is listed on Skillselion. Paste this into your README.

Listed on Skillselion
Installs1
Last updatedMay 12, 2026
Repositorydungluonghoang/k-fresh-02026

What it does

Heal broken Playwright locators after DOM changes by diagnosing the drift, proposing a stable getByRole/data-test replacement, and patching the centralized locators class.

Files

SKILL.mdMarkdownGitHub ↗

Selector Healing

Locator drift is the #1 source of "test failed but nothing changed in our code" tickets. This skill diagnoses the drift, proposes a stable replacement, and applies it in the right place — which in this repo is the centralized `locators/` classes, never the spec.

---

When to use this skill

Trigger on:

  • "Fix the broken locator"
  • "Heal selectors in <page>"
  • "Update the page object — the DOM changed"
  • After `failure-analyzer` returns class locator

Do not use when:

  • The page hasn't actually changed → it's flake; use `flaky-test-triage`.
  • The selector worked but found the wrong element (assertion mismatch, not locator timeout) → it's a real bug; use `defect-report`.
  • The test uses raw page.locator(...) inside a spec → fix the architecture first per `pom-architect`, then heal.

---

How to use it

Phase 1 — Confirm the drift

1. Read the failing spec; find the locator field (e.g. cartLocators.btnUpdate). 2. Open locators/cart-locators.ts to see the current selector. 3. Open the live page in the same env (QA / UAT / Staging) — npx playwright codegen <baseUrl> or the trace-analyzer DOM snapshot. 4. Confirm the element exists but the current selector misses it (e.g. .btn-primary.update.update-cart-button).

If the element no longer exists at all → this is a defect, not drift. Stop and use defect-report.

Phase 2 — Propose a stable replacement

Apply the priority ladder from `prompts/core/locators-naming.md` and `prompts/advanced/selector-healing.md`:

1. getByRole + accessible name           ← strongly preferred
2. getByTestId / [data-test=…]
3. getByLabel / getByPlaceholder         ← form fields
4. getByText (exact, case-insensitive)
5. CSS — only when stable structural classes exist
6. XPath — last resort; document why

Examples:

Brittle (before)Stable (after)Why
.btn-primary:nth-child(3)getByRole('button', { name: /update cart/i })survives DOM reshuffles
div.row > span > agetByTestId('cart-item-name')survives layout changes
//button[contains(@class,'remove')]getByRole('button', { name: 'Remove' })survives class renames

Phase 3 — Patch the locators class

Edit ONLY the centralized class (e.g. locators/cart-locators.ts). Never edit the spec.

// locators/cart-locators.ts
override locatorInitialization(): void {
  super.locatorInitialization();
  // before: this.btnUpdateCart = this.page.locator('.btn-primary:nth-child(3)');
  this.btnUpdateCart = this.page.getByRole('button', { name: /update cart/i });
}

Phase 4 — Verify

npx playwright test tests/ui/test-cart.spec.ts -g "TC-CART-04"

If green, also run the broader suite for the affected feature tag:

npx playwright test --grep "@cart"

If still red → the failure isn't drift; route back to `failure-analyzer`.

Phase 5 — Document

In the commit message, note:

  • Which locator changed
  • Why the old one broke (e.g. "DOM shipped a new wrapper div")
  • Which spec was the canary

If multiple locators broke from the same change, file an internal note so the SUT team can stabilise selectors with data-test attributes upstream.

---

Best practices

  • Heal in the locators class, never in the spec. This repo's POM contract is in `pom-generator.md` — violators get reverted in code review.
  • Prefer accessible roles over data-test. Roles double as a11y signal; data-test is a fallback.
  • Keep selectors language-agnostic when possible. Use regex (/update cart/i) for text matchers so localisation doesn't break the suite.
  • Never use `:nth-child` on dynamic lists. Match by content (.filter({ hasText: ... })), not position.
  • Don't heal silently. Always re-run the spec and one neighbour to catch over-fits.

---

Related

  • `prompts/advanced/selector-healing.md` — full prompt
  • `prompts/core/locators-naming.md` — naming convention
  • `prompts/core/pom-generator.md` — POM contract this skill obeys
  • `.agents/skills/failure-analyzer/SKILL.md` — upstream classifier
  • `.agents/skills/pom-architect/SKILL.md` — for fixing architectural violations before healing
  • `.agents/skills/test-fixing/SKILL.md` — when the fix is more than a selector swap

Related skills

Testing & QAtestingfrontend

This week in AI coding

Five minutes, every Monday - the tools, releases and tactics for developers.

unsubscribe anytime.