plugins/migrating-tests-to-playwright/skills/migrating-tests-to-playwright/SKILL.md
Migrates Cypress, Selenium, WebdriverIO, or Protractor suites to Playwright in staged slices, each with a parity gate before the old test is deleted. Use when porting a legacy browser suite, when deciding which tests are not worth porting, when a half-finished migration has stalled with two suites running in parallel, or when a suite migration needs a plan before anyone starts translating files.
npx skillsauth add jaktestowac/awesome-copilot-for-testers migrating-tests-to-playwrightInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
Security scan pending...
This skill is queued for security scanning. Results will appear when the scan completes.
Use this skill when an existing browser suite is moving to Playwright and the migration needs to finish.
The characteristic failure is not a hard translation problem. It is a migration that stalls at 60 percent, leaving two suites, two CI jobs, two sets of conventions, and nobody willing to delete the old one because nobody can prove the new one covers the same ground. Everything below is arranged to prevent that: slices with parity gates, and a deletion at the end of every slice.
The second thing this skill insists on: a migration is the cheapest opportunity you will ever get to not port the tests that should not exist. A line-by-line translation preserves the old suite's flakiness, its weak assertions, and its coverage gaps, and adds a migration's worth of risk on top.
Do not open a test file to translate until this is finished.
Classify every test in the source suite:
| Class | Signal | Action | | --- | --- | --- | | Port | Covers real risk, passes reliably, assertions are meaningful | Migrate | | Rewrite | Covers real risk, but is flaky, over-mocked, or asserts nothing | Migrate the intent, write the test fresh | | Merge | Duplicates another test's coverage | Fold into one | | Drop | Tests a removed feature, or proves nothing, or is permanently skipped | Delete, with a note | | Defer | Real coverage, low risk, expensive to port | Backlog, and say so out loud |
Record the counts. "We are porting 140 tests" and "we are porting 90, rewriting 20, dropping 30" are different projects with different estimates.
Run unslop-tests over the source suite to make the drop and rewrite decisions on evidence rather than impression. A suite where 30 percent of tests pass with the feature deleted is a suite where the migration should be a rewrite.
Decide the Playwright conventions before the first file, or the first ten files set them accidentally.
storageState set up once, not a login in every testDecide this deliberately rather than letting the first ten files settle it. The designing-test-automation-architecture skill (planned) will own this decision; until it exists, make the calls above explicitly and record them.
Write it as a decision record; see documenting-test-suites. In eight months someone will ask why the migration did not just keep the old page objects.
A slice is a vertical journey, not a directory. "Checkout" is a slice; "all the tests in specs/forms/" is not.
Order slices by:
For each slice record: the source tests, the target tests, the parity evidence, and the deletion commit.
Per-construct mappings are in ./resources/cypress-to-playwright-map.md and ./resources/selenium-to-playwright-map.md, including the constructs that have no direct equivalent and need a different approach.
Rules while translating:
cy-shaped wrapper over Playwright pays the migration cost, keeps the old model, and adds an abstraction nobody else will understand.The gate that makes deletion safe. For each slice, work through ./resources/parity-gate-checklist.md. The load-bearing checks:
Without the deliberate-break check, parity means "both suites are green", which is compatible with the new suite testing nothing.
Same pull request as the parity evidence, or the next one. Not "later".
Every slice that ends without a deletion adds to the maintenance burden the migration was supposed to remove.
When the last slice lands: remove the source framework from package.json, delete its config, its plugins, and its CI job. A dependency left behind gets updated by a bot forever.
Keep the plan visible using ./resources/migration-plan-template.md:
A stalled migration is usually a migration nobody was reporting on.
./resources/cypress-to-playwright-map.md - construct-by-construct mapping, including custom commands, intercepts, and the constructs with no equivalent./resources/selenium-to-playwright-map.md - Selenium and WebdriverIO mapping, waits, page objects, and grid to project matrix./resources/migration-plan-template.md - slice plan, inventory counts, progress tracking, and the report format./resources/parity-gate-checklist.md - the per-slice gate, including the deliberate-break check and the deletion stepdesigning-test-automation-architecture (planned) - to decide the target shape before the first file is translatedunslop-tests - to triage the source suite so weak tests are rewritten rather than portedui-playwright-test-developer (planned) - for how the ported tests should be writtenmocking-network-and-time - when the source suite's intercepts and stubs need re-expressingstabilizing-flaky-tests (planned) - for the source tests classified as rewrite because of flakinessautomating-ci-test-pipelines (planned) - for the CI transition and running both suites during the overlapdocumenting-test-suites - to record the migration decision and the new conventionsThis skill is complete when:
testing
Tests the customization assets themselves - skills, prompts, custom agents, instructions - the way a product is tested: activation cases that check an asset fires when it should and stays quiet when it should not, output-contract cases, safety cases, collision cases between assets competing for the same trigger, a weighted rubric scored blind, and a baseline-versus-candidate gate before an edit ships. Use when a skill is edited and nobody knows whether behaviour changed, when two skills fight over the same request, when a description is being tuned for discoverability, when a collection has grown past manual spot-checking, or when the request mentions skill evals, prompt regression, or "does this skill actually work".
development
Shapes QA output for the person who has to act on it: result and blocker in the first two lines, one decision per report, findings ordered by what they cost, the long artifact in a file and the decisions in the message, and magnitude stated in units the reader can count. Use when a report is accurate but nobody acts on it, when a finding set is too long to read under time pressure, when the same findings must be retold for a developer, a release manager, and an on-call engineer, or when the request mentions "too long", "make this readable", "just tell me what to do", "so what", or "summarize this for stakeholders". Pairs with unslop-answers, which makes the same report honest.
testing
Verifies that the lines and branches a change actually touched are executed by tests, using LCOV or Cobertura diff coverage instead of whole-repo percentages, and escalates uncovered high-risk changes into a blocking finding. Use when a pull request needs a coverage gate that unrelated tests cannot satisfy, when total coverage looks healthy but the diff is untested, when wiring diff coverage into CI, or when someone claims a change is covered because the suite is green.
development
Cuts AI tells from test code: tests that pass without proving anything, tautological assertions, mock-only tests, hardcoded waits, coverage theater, vague names, swallowed errors, retries used as fixes. Use whenever test code is written, changed, or reviewed, including tests produced as a side effect of a feature task, and when the request mentions "review these tests", "are these tests any good", "this test always passes", "this suite is flaky", or "clean up these tests". Must always apply to test code.