Custom steps let you create your own test step patterns that generate code automatically.
Example: Instead of writing multiple steps, create one custom step:
- ❌ Before:
type john into #username,type secret into #password,click #login - ✅ After:
login as john with password secret→ generates all three actions
1. Click "Custom Steps" button (⚙️ icon)
↓
2. Enter Pattern: login as {username} with password {password}
↓
3. Enter Code: await page.fill('#username', '{username}');
await page.fill('#password', '{password}');
await page.click('#login-btn');
↓
4. Click "Add Template"
↓
5. Done! Use it: login as [email protected] with password mypass123
✅ DO:
• Use {curly braces} for parameters: login as {username}
• Use natural language: click on {button}
• Be descriptive: fill {field} with {value}
❌ DON'T:
• Use abbreviations: clk {btn}
• Skip words: login {user} {pass}
• Mix frameworks in one pattern
Pattern: refresh page
Code: await page.reload();
Pattern: go back
Code: await page.goBack();
Pattern: hover over {selector}
Code: await page.hover('{selector}');
Pattern: check {selector}
Code: await page.check('{selector}');
Pattern: select {option} from {selector}
Code: await page.selectOption('{selector}', '{option}');
Pattern: login as {username} with password {password}
Code: await page.fill('#username', '{username}');
await page.fill('#password', '{password}');
await page.click('#login-btn');
Your Pattern: login as {username} with password {password}
User Types: login as john with password secret123
Generates:
await page.fill('#username', 'john');
await page.fill('#password', 'secret123');
await page.click('#login-btn');
Rules:
- ✅ Case-insensitive:
Login As John=login as john - ✅ Flexible spacing:
login as johnworks - ❌ Word order matters:
login as {username}≠{username} login
-
Framework-Specific: Your code must match the selected framework
- Playwright:
await page.action() - Cypress:
cy.action() - TestCafe:
await t.action()
- Playwright:
-
Session Only: Custom steps are lost when you refresh the page
- Write them down or share with your team
-
Parameter Names: Must match exactly in pattern and code
- Pattern:
login as {username} - Code: Must use
{username}, not{user}
- Pattern:
// Navigation
await page.goto('{url}');
await page.reload();
// Actions
await page.click('{selector}');
await page.fill('{selector}', '{text}');
await page.hover('{selector}');
// Verification
await expect(page.locator('{selector}')).toBeVisible();
await expect(page.locator('{selector}')).toContainText('{text}');// Navigation
cy.visit('{url}');
cy.reload();
// Actions
cy.get('{selector}').click();
cy.get('{selector}').type('{text}');
cy.get('{selector}').trigger('mouseover');
// Verification
cy.get('{selector}').should('be.visible');
cy.contains('{text}').should('be.visible');// Navigation
await t.navigateTo('{url}');
await t.eval(() => location.reload());
// Actions
await t.click(Selector('{selector}'));
await t.typeText(Selector('{selector}'), '{text}');
await t.hover(Selector('{selector}'));
// Verification
await t.expect(Selector('{selector}').exists).ok();
await t.expect(Selector('body').innerText).contains('{text}');| Problem | Solution |
|---|---|
| Pattern doesn't match | Check word order and spelling |
| Code not generating | Verify parameter names match {parameter} |
| Wrong framework code | Ensure code syntax matches selected framework |
| Template disappeared | Custom steps reset on page refresh |
For detailed information, see:
- CUSTOM_STEPS.md - Complete guide with all examples