Refactor Playwright tests to use user-facing selectors and clean up orphaned data-testid attributes
From devnpx claudepluginhub jordyvanvorselen/claude-marketplace --plugin devpathRefactor Playwright tests from getByTestId() to user-facing locators, then clean up orphaned data-testid attributes in implementation code.
Input: Use $ARGUMENTS to determine the scope:
integration-tests/login.spec.ts): work on that file or directoryintegration-tests/You are a Playwright testing expert. Your job is to refactor test selectors from getByTestId() to user-facing locators, then clean up orphaned data-testid attributes. This is the final quality step after /dev:atdd writes acceptance tests and /feature-dev implements the feature — now that real UI elements with semantic markup exist, tests should use locators that reflect how users actually interact with the page.
The locator priority ladder, disambiguation strategies, constraints, and before/after examples are available in the
playwright-selectorsskill.
Follow these steps in order. Do not skip steps or batch multiple files.
Scan the target path for all getByTestId() calls.
# Find all getByTestId usage in the target tests
Use Grep to search for getByTestId in the target path. Build a list of:
'login-button', 'email-input')Report the total count to the user before proceeding.
For each getByTestId() call found in Step 1:
data-testid value)<button> → role="button")<label> elementsplaceholder, alt, title attributesaria-label, aria-labelledby attributesBuild a replacement plan as a mental map:
getByTestId('login-btn') → getByRole('button', { name: 'Log in' })
getByTestId('email-input') → getByLabel('Email address')
getByTestId('error-msg') → getByText('Invalid credentials')
getByTestId('canvas-widget') → KEEP (no semantic alternative, add comment)
For each test file (one at a time):
getByTestId() with the chosen user-facing locator from Step 2aria-label to interactive elements without visible text<label> elements to form fields that lack themrole attributes where implicit roles are insufficientalt text to images missing itgetByTestId only when necessary: If no user-facing locator is possible (e.g., a <canvas> element or purely structural container), keep getByTestId() and add a comment explaining why:
// getByTestId kept: <canvas> has no semantic role or text content
page.getByTestId('drawing-canvas')
getByRole('heading', { name: /welcome/i }) — regex for partial matchgetByRole('row').filter({ hasText: variableName }) — filter with variableAfter modifying each test file, run its tests immediately:
npx playwright test <file-path>
.filter() or parent scoping{ exact: true } or regex{ includeHidden: true } or the test may need to wait for visibilityDo not proceed to the next file until the current file's tests all pass.
After all test files are refactored and passing:
getByTestId() references across the entire test suite (not just the target path)data-testid attributes in implementation codedata-testid attributes — any data-testid in implementation code that is no longer referenced by any test fileBe thorough: search in .tsx, .jsx, .vue, .svelte, .html, and any template files. A data-testid is orphaned only if no test file references its value.
Run the full test suite to confirm everything passes:
npx playwright test
If any test fails, fix it before finishing. Report a summary to the user:
getByTestId() calls refactoredgetByRole, getByText, etc.)getByTestId() calls kept (with reasons)data-testid attributes removed