Migrate to Playwright

Migrate from Cypress or Selenium to Playwright.

How to use it

Claude Code
  1. Run the line below. It pulls the whole folder into ~/.claude/skills/migrate, including the files SKILL.md points to.
  2. Describe your job in plain words. Claude Code follows the skill from there.
Claude Code — installs the whole folder, not just SKILL.md
npx degit alirezarezvani/claude-skills/engineering-team/playwright-pro/skills/migrate#main ~/.claude/skills/migrate

For one project only, change the path to .claude/skills/migrate. This skill also uses package.json, cypress-mapping.md, selenium-mapping.md — copying SKILL.md alone won't be enough. See the folder on GitHub.

Claude (web or desktop app)
  1. On this page open ⋯ → Download .md.
  2. Save it as SKILL.md in a folder, zip the folder, then Customize → Skills → + → Create skill → Upload a skill.
  3. Pick the file and Save. Claude shows the name and description and runs a security scan.
  4. Check the skill is switched on.
  5. Start a new chat and describe your job in plain words. The AI follows the skill from there.
ChatGPT or another app
  1. ChatGPT: make a Project and paste it into Instructions.
  2. Neither? Paste it at the top of a new chat — it works for that chat.
Not working?
  • Check which app you pasted it into — the steps above name the right one.
  • Some skills need the paid tier of Claude or ChatGPT.
Step-by-step guide with screenshots · Ask in the forum

Paste into Claude, ChatGPT or Cursor.

Source of Migrate to Playwright

Show the full text136 lines
namedescription
migrate>- Migrate from Cypress or Selenium to Playwright. Use when user mentions cypress", "selenium", "migrate tests", "convert tests", "switch to playwright", "move from cypress", or "replace selenium".

Migrate to Playwright

Interactive migration from Cypress or Selenium to Playwright with file-by-file conversion.

Input

$ARGUMENTS can be:

  • "from cypress" — migrate Cypress test suite
  • "from selenium" — migrate Selenium/WebDriver tests
  • A file path: convert a specific test file
  • Empty: auto-detect source framework

Steps

1. Detect Source Framework

Use Explore subagent to scan:

  • cypress/ directory or cypress.config.ts → Cypress
  • selenium, webdriver in package.json deps → Selenium
  • .py test files with selenium imports → Selenium (Python)
2. Assess Migration Scope

Count files and categorize:

Migration Assessment:
- Total test files: X
- Cypress custom commands: Y
- Cypress fixtures: Z
- Estimated effort: [small|medium|large]
Size Files Approach
Small (1-10) Convert sequentially Direct conversion
Medium (11-30) Batch in groups of 5 Use sub-agents
Large (31+) Use /batch Parallel conversion with /batch
3. Set Up Playwright (If Not Present)

Run /pw:pw-init first if Playwright isn't configured.

4. Convert Files

For each file, apply the appropriate mapping:

Cypress → Playwright

Load cypress-mapping.md for complete reference.

Key translations:

cy.visit(url)           → page.goto(url)
cy.get(selector)        → page.locator(selector) or page.getByRole(...)
cy.contains(text)       → page.getByText(text)
cy.find(selector)       → locator.locator(selector)
cy.click()              → locator.click()
cy.type(text)           → locator.fill(text)
cy.should('be.visible') → expect(locator).toBeVisible()
cy.should('have.text')  → expect(locator).toHaveText(text)
cy.intercept()          → page.route()
cy.wait('@alias')       → page.waitForResponse()
cy.fixture()            → JSON import or test data file

Cypress custom commands → Playwright fixtures or helper functions Cypress plugins → Playwright config or fixtures before/beforeEach → test.beforeAll() / test.beforeEach()

Selenium → Playwright

Load selenium-mapping.md for complete reference.

Key translations:

driver.get(url)                    → page.goto(url)
driver.findElement(By.id('x'))     → page.locator('#x') or page.getByTestId('x')
driver.findElement(By.css('.x'))   → page.locator('.x') or page.getByRole(...)
element.click()                    → locator.click()
element.sendKeys(text)             → locator.fill(text)
element.getText()                  → locator.textContent()
WebDriverWait + ExpectedConditions → expect(locator).toBeVisible()
driver.switchTo().frame()          → page.frameLocator()
Actions                            → locator.hover(), locator.dragTo()
5. Upgrade Locators

During conversion, upgrade selectors to Playwright best practices:

  • #id → getByTestId() or getByRole()
  • .class → getByRole() or getByText()
  • [data-testid] → getByTestId()
  • XPath → role-based locators
6. Convert Custom Commands / Utilities
  • Cypress custom commands → Playwright custom fixtures via test.extend()
  • Selenium page objects → Playwright page objects (keep structure, update API)
  • Shared helpers → TypeScript utility functions
7. Verify Each Converted File

After converting each file:

npx playwright test <converted-file> --reporter=list

Fix any compilation or runtime errors before moving to the next file.

8. Clean Up

After all files are converted:

  • Remove Cypress/Selenium dependencies from package.json
  • Remove old config files (cypress.config.ts, etc.)
  • Update CI workflow to use Playwright
  • Update README with new test commands

Ask user before deleting anything.

Output

  • Conversion summary: files converted, total tests migrated
  • Any tests that couldn't be auto-converted (manual intervention needed)
  • Updated CI config
  • Before/after comparison of test run results
1---
2name: "migrate"
3description: >-
4 Migrate from Cypress or Selenium to Playwright. Use when user mentions
5 "cypress", "selenium", "migrate tests", "convert tests", "switch to
6 playwright", "move from cypress", or "replace selenium".
7---
8 
9# Migrate to Playwright
10 
11Interactive migration from Cypress or Selenium to Playwright with file-by-file conversion.
12 
13## Input
14 
15`$ARGUMENTS` can be:
16- `"from cypress"` — migrate Cypress test suite
17- `"from selenium"` — migrate Selenium/WebDriver tests
18- A file path: convert a specific test file
19- Empty: auto-detect source framework
20 
21## Steps
22 
23### 1. Detect Source Framework
24 
25Use `Explore` subagent to scan:
26- `cypress/` directory or `cypress.config.ts` → Cypress
27- `selenium`, `webdriver` in `package.json` deps → Selenium
28- `.py` test files with `selenium` imports → Selenium (Python)
29 
30### 2. Assess Migration Scope
31 
32Count files and categorize:
33 
34```
35Migration Assessment:
36- Total test files: X
37- Cypress custom commands: Y
38- Cypress fixtures: Z
39- Estimated effort: [small|medium|large]
40```
41 
42| Size | Files | Approach |
43|---|---|---|
44| Small (1-10) | Convert sequentially | Direct conversion |
45| Medium (11-30) | Batch in groups of 5 | Use sub-agents |
46| Large (31+) | Use `/batch` | Parallel conversion with `/batch` |
47 
48### 3. Set Up Playwright (If Not Present)
49 
50Run `/pw:pw-init` first if Playwright isn't configured.
51 
52### 4. Convert Files
53 
54For each file, apply the appropriate mapping:
55 
56#### Cypress → Playwright
57 
58Load `cypress-mapping.md` for complete reference.
59 
60Key translations:
61```
62cy.visit(url) → page.goto(url)
63cy.get(selector) → page.locator(selector) or page.getByRole(...)
64cy.contains(text) → page.getByText(text)
65cy.find(selector) → locator.locator(selector)
66cy.click() → locator.click()
67cy.type(text) → locator.fill(text)
68cy.should('be.visible') → expect(locator).toBeVisible()
69cy.should('have.text') → expect(locator).toHaveText(text)
70cy.intercept() → page.route()
71cy.wait('@alias') → page.waitForResponse()
72cy.fixture() → JSON import or test data file
73```
74 
75**Cypress custom commands** → Playwright fixtures or helper functions
76**Cypress plugins** → Playwright config or fixtures
77**`before`/`beforeEach`** → `test.beforeAll()` / `test.beforeEach()`
78 
79#### Selenium → Playwright
80 
81Load `selenium-mapping.md` for complete reference.
82 
83Key translations:
84```
85driver.get(url) → page.goto(url)
86driver.findElement(By.id('x')) → page.locator('#x') or page.getByTestId('x')
87driver.findElement(By.css('.x')) → page.locator('.x') or page.getByRole(...)
88element.click() → locator.click()
89element.sendKeys(text) → locator.fill(text)
90element.getText() → locator.textContent()
91WebDriverWait + ExpectedConditions → expect(locator).toBeVisible()
92driver.switchTo().frame() → page.frameLocator()
93Actions → locator.hover(), locator.dragTo()
94```
95 
96### 5. Upgrade Locators
97 
98During conversion, upgrade selectors to Playwright best practices:
99- `#id` → `getByTestId()` or `getByRole()`
100- `.class` → `getByRole()` or `getByText()`
101- `[data-testid]` → `getByTestId()`
102- XPath → role-based locators
103 
104### 6. Convert Custom Commands / Utilities
105 
106- Cypress custom commands → Playwright custom fixtures via `test.extend()`
107- Selenium page objects → Playwright page objects (keep structure, update API)
108- Shared helpers → TypeScript utility functions
109 
110### 7. Verify Each Converted File
111 
112After converting each file:
113 
114```bash
115npx playwright test <converted-file> --reporter=list
116```
117 
118Fix any compilation or runtime errors before moving to the next file.
119 
120### 8. Clean Up
121 
122After all files are converted:
123- Remove Cypress/Selenium dependencies from `package.json`
124- Remove old config files (`cypress.config.ts`, etc.)
125- Update CI workflow to use Playwright
126- Update README with new test commands
127 
128Ask user before deleting anything.
129 
130## Output
131 
132- Conversion summary: files converted, total tests migrated
133- Any tests that couldn't be auto-converted (manual intervention needed)
134- Updated CI config
135- Before/after comparison of test run results
136 

Discussion