playwright-cucumber-ts-steps
v1.3.4
Published
A collection of reusable Playwright step definitions for Cucumber in TypeScript, designed to streamline end-to-end testing across web, API, and mobile applications.
Maintainers
Readme
🎭 Playwright Cucumber TS Steps
A collection of reusable Playwright step definitions for Cucumber in TypeScript, designed to streamline end-to-end testing across web, API, and mobile applications.
Note: This package is designed for advanced Cucumber+Playwright+TypeScript setups. For basic Playwright usage, see the official Playwright docs.
The "Low-Code" BDD Framework for Playwright.
Write powerful end-to-end tests in plain English using Gherkin syntax, without managing complex glue code. playwright-cucumber-ts-steps provides a pre-built library of robust steps for UI, API, and Authentication testing, running natively inside Playwright.
🚀 Features
- Zero Boilerplate: Install and start writing
.featurefiles immediately. - Hybrid Testing: Mix UI, API, and Database steps in a single scenario.
- Smart Auth: Login once, save the session, and reuse it across thousands of tests.
- Native Performance: Runs purely on Playwright (no heavy Cucumber-JS wrapper), giving you Parallelism, Tracing, and Retries out of the box.
- Tag Filtering: Run specific tests like
@smokeor@regressioneasily. - Auto-Reporting: Built-in helper for HTML and Slack reports with screenshots on failure.
📦 Installation
npm install playwright-cucumber-ts-steps @playwright/testor
yarn add playwright-cucumber-ts-steps @playwright/testnpx playwright install📘 Step Definition Documentation
👉 View Steps Documentation and examples.
⚡ Quick Start Guide
1. Configure Playwright
Update playwright.config.ts to use the built-in reporting helper.
import { defineConfig } from "@playwright/test";
import { getReporters, setFixtureConfig } from "playwright-cucumber-ts-steps";
// Optional: Configure custom fixture directory and file names
setFixtureConfig({
fixturesDir: "fixtures", // Default: "fixtures"
selectorsFile: "selectors.json", // Custom selectors file name
textsFile: "texts.json", // Custom texts file name
valuesFile: "values.json", // Custom values file name
// ... other fixture files
});
export default defineConfig({
testDir: "./tests",
// Sets up HTML report + Console list automatically
reporter: getReporters({ on: ["html"] }),
use: {
// We handle screenshots manually in the runner,
// but this is good as a backup
screenshot: "only-on-failure",
},
});Configurable Fixture Files:
fixturesDir- Base directory for all fixtures (default:"fixtures")selectorsFile- UI selectors fixture filetextsFile- Text content fixture filevaluesFile- Test values fixture fileoptionsFile- Dropdown options fixture fileendpointsFile- API endpoints fixture filefilesFile- File paths fixture filepathsFile- JSON paths fixture fileresponsesFile- API responses fixture filequeriesFile- Database queries fixture filecolumnsFile- Database columns fixture filetypesFile- Data types fixture filetitlesFile- Page titles fixture fileurlsFile- URLs fixture fileattributesFile- HTML attributes fixture filepromptsFile- Dialog prompts fixture file
2. Create the Runner
Create a file at tests/bdd.spec.ts. This is the entry point.
import { runTests } from "playwright-cucumber-ts-steps";
// Runs all feature files in the 'features' folder
runTests("features/*.feature");3. Write Your Feature
Create features/login.feature:
Feature: User Authentication
@smoke
Scenario: Successful Login
Given I pw visit "[https://the-internet.herokuapp.com/login](https://the-internet.herokuapp.com/login)"
When I pw fill "#username" with "tomsmith"
And I pw fill "#password" with "SuperSecretPassword!"
And I pw click "button[type='submit']"
Then I pw expect "#flash" to contain text "You logged into a secure area!"
4. Run Tests
npx playwright test🏷️ Tag Filtering (New!)
We support a Friendly Syntax for filtering tests via the TAGS environment variable.
| Logic | Symbol | Example | Description |
| ------- | ------ | ---------------- | ------------------------------------------------ |
| AND | , | @login,@signup | Run tests that have @login AND @signup. |
| |
| MIX | , | @a,@b, @c | Run tests with (@a AND @b) OR just @c. |
Usage:
# Run only smoke tests
TAGS='@smoke' npx playwright test
OR
npx playwright test -g "@smoke"
# Run smoke tests that are also critical
TAGS='@smoke,@critical' npx playwright test
OR
npx playwright test -g "@smoke|@critical"
(On Windows PowerShell, use $env:TAGS="@smoke"; npx playwright test)
In your Test Runner (tests/bdd.spec.ts):
import { runTests } from "playwright-cucumber-ts-steps";
// OPTION 1: Run Everything
// runTests('features/*.feature');
// OPTION 2: Run only Smoke tests
runTests("features/*.feature", { tags: "@smoke" });💡 Various Usage Examples
1. API Testing (Backend Validation)
You can validate your backend directly without opening a browser, or mix it with UI tests.
Feature: User API
@api
Scenario: Create and Verify User
When I pw make a POST request to "[https://reqres.in/api/users](https://reqres.in/api/users)" with body '{"name": "Morpheus", "job": "Leader"}'
Then I pw expect the response status to be 201
And I pw expect the response property "name" to be "Morpheus"
2. Advanced Elements (Iframes & Uploads)
Handling complex HTML elements is built-in.
Feature: File Upload and Iframes
Scenario: Upload Document inside Iframe
Given I pw visit "[https://example.com/upload](https://example.com/upload)"
# Switch context to the iframe
When I pw upload file "data/resume.pdf" to "#file-input" inside frame "#upload-iframe"
And I pw click "#submit-btn" inside frame "#upload-iframe"
Then I pw expect "div.success" inside frame "#upload-iframe" to be visible
3. The "Login Once" Pattern (Authentication)
Speed up your suite by 10x. Login once, save the cookies, and reuse them.
Step 1: Create a Setup Feature (features/setup.feature)
Feature: Setup
@setup
Scenario: Admin Login
Given I pw visit "/login"
When I pw fill "#user" with "admin"
And I pw fill "#pass" with "1234"
And I pw click "#login-btn"
And I pw expect "#dashboard" to be visible
# Saves session to ./auth/admin.json
And I pw save the browser state to "admin.json"
Step 2: Use in Daily Tests (features/admin.feature)
Feature: Admin Panel
Scenario: Check Reports
# Loads cookies instantly - No login UI needed!
Given I pw load the browser state from "admin.json"
When I pw visit "/admin/reports"
Then I pw expect "h1" to have text "Weekly Reports"
4. Data Tables (Forms)
Fill out entire forms in a single step using a Data Table. You can type, click, check, or assert visibility in one go.
Scenario: Registration
When I pw fill the following "Registration" form data:
| #first-name | John |
| #last-name | Doe |
| #email | [email protected] |
| #newsletter | check |
| #submit-btn | click |
| .success | assert:visible |5. API Testing (Tables & Files)
Validate your backend directly. You can send payloads via Tables or JSON Files.
Option A: Data Table Payload
Scenario: Create User (Table)
When I pw make a POST request to "[https://reqres.in/api/users](https://reqres.in/api/users)" with data:
| name | Neo |
| job | The Chosen |
Then I pw expect the response status to be 201
And I pw expect the response property "name" to be "Neo"Option B: File Payload
Scenario: Create User (File)
# Reads from 'data/user.json' in your project root
When I pw make a POST request to "/api/users" with payload from "data/user.json"
Then I pw expect the response status to be 2016. Network Mocking
Simulate backend responses to test UI behavior without relying on real APIs.
Scenario: Mocking User Profile
# Intercept calls to /api/user/1 and return fake data
Given I pw mock the API endpoint "*/**/api/user/1" with body '{"name": "Mocked User"}'
# When the UI calls the API, it gets our fake data
When I pw visit "/profile"
Then I pw expect "#username-display" to have text "Mocked User"
7. Database Testing (Adapter Pattern)
You can validate database states by injecting your own DB driver into the runner.
1. In your bdd.spec.ts:
import { runTests } from "playwright-cucumber-ts-steps";
import pg from "pg"; // Your driver (pg, mysql, mongo, etc)
// wrapper function
const queryDb = async (query: string) => {
const client = new pg.Client(process.env.DB_URL);
await client.connect();
const res = await client.query(query);
await client.end();
return res.rows; // Must return an array of objects
};
runTests("features/*.feature", { dbQuery: queryDb });2. In your Feature file:
Scenario: Create User
When I pw run the database query "INSERT INTO users (name) VALUES ('Bob')"
Then I pw expect the database to return 1 record
And I pw expect the first database record to contain:
| name | Bob |📖 Step Glossary (Cheat Sheet)
🖱️ Actions
| Step | Usage Example |
| ---------------- | ----------------------------------------- |
| Visit | I pw visit "https://google.com" |
| Click | I pw click "#submit-btn" |
| Force Click | I pw force click "#hidden-btn" |
| Double Click | I pw double click ".icon" |
| Fill Input | I pw fill "#email" with "[email protected]" |
| Press Key | I pw press "Enter" (or "Tab", "Escape") |
| Wait | I pw wait for 2000 milliseconds |
| Reload | I pw reload the page |
| Go Back | I pw go back |
✅ Assertions
| Step | Usage Example |
| ---------------- | ----------------------------------------------------------------- |
| Visibility | I pw expect "#modal" to be visible |
| Hidden | I pw expect "#loader" to be hidden |
| Exact Text | I pw expect "#header" to have text "Welcome" |
| Partial Text | I pw expect ".error" to contain text "Failed" |
| Input Value | I pw expect "#username" to have value "admin" |
| Exact URL | I pw expect the url to be "https://site.com/home" |
| Partial URL | I pw expect the url to contain "/dashboard" |
| Title | I pw expect the title to contain "Home Page" |
| Attribute | I pw expect "img" to have attribute "src" with value "logo.png" |
| Screenshot | I pw expect the page screenshot to match "home.png" |
🧩 Forms & Elements
| Step | Usage Example |
| --------------------- | ------------------------------------------------- |
| Select (Dropdown) | I pw select option "Canada" from "#country" |
| Check Box | I pw check "#terms-checkbox" |
| Uncheck | I pw uncheck "#newsletter" |
| Upload File | I pw upload file "data.csv" to "#upload" |
| Handle Alert | I pw accept the next dialog |
| Frame Click | I pw click "#btn" inside frame "#payment-frame" |
🌐 API
| Step | Usage Example |
| ---------------- | ---------------------------------------------------------------- |
| GET | I pw make a GET request to "/api/users" |
| DELETE | I pw make a DELETE request to "/api/users/1" |
| POST | I pw make a POST request to "/api/login" with body '{"u":"1"}' |
| Status Check | I pw expect the response status to be 200 |
| JSON Check | I pw expect the response property "data.id" to be "99" |
🛠️ Extending (Custom Steps)
Need a step that isn't included? You can easily register your own in your spec file.
// tests/bdd.spec.ts
import { runTests, Step } from "playwright-cucumber-ts-steps";
// 1. Define custom step
Step("I pw scroll to the bottom of the page", async (page) => {
await page.evaluate(() => window.scrollTo(0, document.body.scrollHeight));
});
// 2. Run tests
runTests("features/*.feature");Then use it in your feature:
Scenario: Scroll Test
Given I pw visit "[https://infinite-scroll.com](https://infinite-scroll.com)"
When I pw scroll to the bottom of the page
📘 Step Definition Documentation
When I pw click
When I pw clickWhen I pw click on element {string}
When I pw click on element {string}When I pw click on button {string}
When I pw click on button {string}When I pw click on link {string}
When I pw click on link {string}When I pw click on label {string}
When I pw click on label {string}When I pw click on text {string}
When I pw click on text {string}When I pw click on exact text {string}
When I pw click on exact text {string}When I pw click on selector ([^]+)
When I pw click on selector ([^]+)When I pw click all
When I pw click allWhen I pw double click
When I pw double clickWhen I pw double click on text {string}
When I pw double click on text {string}When I pw double click position {int} {int}
When I pw double click position {int} {int}When I pw right click
When I pw right clickWhen I pw right click on text {string}
When I pw right click on text {string}When I pw right click position {int} {int}
When I pw right click position {int} {int}When I pw click on ({int})(?:st|nd|rd|th) element ([^]+)
When I pw click on ({int})(?:st|nd|rd|th) element ([^]+)When I pw click on ({int})(?:st|nd|rd|th) selector ([^]+)
When I pw click on ({int})(?:st|nd|rd|th) selector ([^]+)When I pw find element by selector {string}
When I pw find element by selector {string}When I pw find element by text {string}
When I pw find element by text {string}When I pw find element by title {string}
When I pw find element by title {string}When I pw find element by testid {string}
When I pw find element by testid {string}When I pw find element by role {string}
When I pw find element by role {string}When I pw find element by placeholder text {string}
When I pw find element by placeholder text {string}When I pw find element by label text {string}
When I pw find element by label text {string}When I pw find element by alt text {string}
When I pw find element by alt text {string}When I pw find link by text {string}
When I pw find link by text {string}When I pw find heading by text {string}
When I pw find heading by text {string}When I pw find element by name {string}
When I pw find element by name {string}When I pw find elements by selector {string}
When I pw find elements by selector {string}When I pw find headings by text {string}
When I pw find headings by text {string}When I pw find buttons by text {string}
When I pw find buttons by text {string}When I pw get first element
When I pw get first elementWhen I pw get last element
When I pw get last elementWhen I pw get ({int})(?:st|nd|rd|th) element
When I pw get ({int})(?:st|nd|rd|th) elementWhen I pw get focused element
When I pw get focused elementWhen I pw find input by ID {string}
When I pw find input by ID {string}When I pw find input by name {string}
When I pw find input by name {string}When I pw find input by placeholder text {string}
When I pw find input by placeholder text {string}When I pw find input by display value {string}
When I pw find input by display value {string}When I pw find textarea by label text {string}
When I pw find textarea by label text {string}When I store element text as {string}
When I pw store element text as {string}When I pw fill the following {string} form data
When I pw fill the following {string} form dataWhen I pw fill the following {string} test form data
When I pw fill the following {string} test form dataWhen I switch to frame {string}
When I pw switch to frame {string}When I pw find element {string} in frame {string}
When I pw find element {string} in frame {string}When I switch to new tab
When I pw switch to new tabWhen I type {string}
When I pw type {string}When I type stored {string}
When I pw type stored {string}When I slowly type {string}
When I pw slowly type {string}When I set value {string}
When I pw set value {string}When I clear
When I pw clearWhen I press {string}
When I pw press {string}When I check
When I pw checkWhen I uncheck
When I pw uncheckWhen I check input
When I pw check inputWhen I uncheck input
When I pw uncheck inputWhen I (check|uncheck) ({int})(?:st|nd|rd|th) selector ([^]+)
When I pw (check|uncheck) ({int})(?:st|nd|rd|th) selector ([^]+)When I pw select option {string}
When I pw select option {string}When I pw submit
When I pw submitWhen I pw select file {string}
When I pw select file {string}When I pw upload file {string}
When I pw upload file {string}When I pw click {string}
When I pw click {string}When I pw force click {string}
When I pw force click {string}When I pw fill {string} with {string}
When I pw fill {string} with {string}When I press {string}
When I pw press {string}When I wait for {int} milliseconds
When I pw wait for {int} millisecondsWhen I press key {string}
When I pw press key {string}When I press key {string} on element
When I pw press key {string} on elementWhen I press keys {string}
When I pw press keys {string}When I press shortcut {string}
When I pw press shortcut {string}When I hold down key {string}
When I pw hold down key {string}When I release key {string}
When I pw release key {string}When I wait for {int} milliseconds
When I pw wait for {int} millisecondsWhen I wait for {int} seconds
When I pw wait for {int} secondsWhen I pause
When I pw pauseWhen I debug
When I pw debugWhen I log {string}
When I pw log {string}When I focus
When I pw focusWhen I blur
When I pw blurWhen I set cookie {string} to {string}
When I pw set cookie {string} to {string}When I clear all cookies
When I pw clear all cookiesWhen I set local storage item {string} to {string}
When I pw set local storage item {string} to {string}When I pw get local storage item {string}
When I pw get local storage item {string}When I clear local storage
When I pw clear local storageWhen I set session storage item {string} to {string}
When I pw set session storage item {string} to {string}When I clear session storage
When I pw clear session storageWhen I tap
When I pw tapWhen I tap element {string}
When I pw tap element {string}When I tap coordinates x:{int} y:{int}
When I pw tap coordinates x:{int} y:{int}When I resize window to width {int} and height {int}
When I pw resize window to width {int} and height {int}When I simulate device {string}
When I pw simulate device {string}When I set geolocation to lat: {float} long: {float}
When I pw set geolocation to lat: {float} long: {float}When I grant permission {string}
When I pw grant permission {string}When I scroll {string} into view
When I pw scroll {string} into viewWhen I scroll {string} to position x:{int} y:{int}
When I pw scroll {string} to position x:{int} y:{int}When I scroll to coordinates x:{int} y:{int}
When I pw scroll to coordinates x:{int} y:{int}When I scroll mouse window to position top:{int} left:{int}
When I pw scroll mouse window to position top:{int} left:{int}When I scroll to {string}
When I pw scroll to {string}When I hover over the element {string}
When I pw hover over the element {string}When I move mouse to coordinates {int}, {int}
When I pw move mouse to coordinates {int}, {int}When I hover on ({int})(?:st|nd|rd|th) element ([^]+)
When I pw hover on ({int})(?:st|nd|rd|th) element ([^]+)When I hover on ({int})(?:st|nd|rd|th) selector ([^]+)
When I pw hover on ({int})(?:st|nd|rd|th) selector ([^]+)When I visit {string}
When I pw visit {string}When I reload the page
When I pw reload the pageWhen I go back
When I pw go backWhen I go forward
When I pw go forwardWhen I navigate to {string}
When I pw navigate to {string}When I wait for network idle
When I pw wait for network idleWhen I wait for load state {string}
When I pw wait for load state {string}When I wait for element to be visible
When I pw wait for element to be visibleWhen I wait for element to be hidden
When I pw wait for element to be hiddenWhen I wait for URL to contain {string}
When I pw wait for URL to contain {string}When I pw expect the response status to be {int}
When I pw expect the response status to be {int}When I pw expect the response body to contain {string}
When I pw expect the response body to contain {string}When I pw expect the response property {string} to be {string}
When I pw expect the response property {string} to be {string}When I mock the API endpoint {string} with body {string}
When I pw mock the API endpoint {string} with body {string}When I mock the API endpoint {string} with response from {string}
When I pw mock the API endpoint {string} with response from {string}When I mock the API endpoint {string} with status {int}
When I pw mock the API endpoint {string} with status {int}When I intercept URL ([^]+) and stub body:?
When I pw intercept URL ([^]+) and stub body:?When I intercept URL {string} and stub body {string}
When I pw intercept URL {string} and stub body {string}When I intercept URL {string}
When I pw intercept URL {string}When I make request to {string}
When I pw make request to {string}When I make a POST request to ([^]+) with JSON body:?
When I pw make a POST request to ([^]+) with JSON body:?When I make a {word} request to {string}
When I pw make a {word} request to {string}When I make a GET request to {string}
When I pw make a GET request to {string}When I make a DELETE request to {string}
When I pw make a DELETE request to {string}When I make a POST request to {string} with data
When I pw make a POST request to {string} with dataWhen I make a POST request to {string} with payload from {string}
When I pw make a POST request to {string} with payload from {string}When I pw expect the url to contain {string}
When I pw expect the url to contain {string}When I pw expect the url to be {string}
When I pw expect the url to be {string}When I pw expect the title to contain {string}
When I pw expect the title to contain {string}When I pw expect the title to be {string}
When I pw expect the title to be {string}When I pw expect {string} to have text {string}
When I pw expect {string} to have text {string}When I pw expect {string} to contain text {string}
When I pw expect {string} to contain text {string}When I pw expect {string} to have value {string}
When I pw expect {string} to have value {string}When I pw expect {string} to have attribute {string} with value {string}
When I pw expect {string} to have attribute {string} with value {string}When I pw expect element to be visible
When I pw expect element to be visibleWhen I pw expect {string} to be visible
When I pw expect {string} to be visibleWhen I pw expect element to be hidden
When I pw expect element to be hiddenWhen I pw expect element to be enabled
When I pw expect element to be enabledWhen I pw expect element to be disabled
When I pw expect element to be disabledWhen I pw expect element to have text {string}
When I pw expect element to have text {string}When I pw expect element to contain text {string}
When I pw expect element to contain text {string}When I pw expect element to have value {string}
When I pw expect element to have value {string}When I pw expect element to have attribute {string}
When I pw expect element to have attribute {string}When I pw expect element to have attribute {string} with value {string}
When I pw expect element to have attribute {string} with value {string}When I pw expect the page screenshot to match {string}
When I pw expect the page screenshot to match {string}When I pw expect the element screenshot to match {string}
When I pw expect the element screenshot to match {string}When I save the browser state to {string}
When I pw save the browser state to {string}When I load the browser state from {string}
When I pw load the browser state from {string}When I run the database query {string}
When I pw run the database query {string}When I pw expect the database to return {int} record(s)
When I pw expect the database to return {int} record(s)When I pw expect the database to return no records
When I pw expect the database to return no recordsWhen I pw expect the first database record to contain
When I pw expect the first database record to containWhen I pw expect database row {int} to contain
When I pw expect database row {int} to containWhen I pw expect all database records to contain
When I pw expect all database records to containWhen I pw expect database column {string} to exist
When I pw expect database column {string} to existWhen I pw expect database column {string} to contain {string}
When I pw expect database column {string} to contain {string}When I pw expect database column {string} to be of type {string}
When I pw expect database column {string} to be of type {string}When I accept the next dialog
When I pw accept the next dialogWhen I dismiss the next dialog
When I pw dismiss the next dialogWhen I type {string} into the next prompt and accept
When I pw type {string} into the next prompt and acceptWhen I pw select option {string} from {string}
When I pw select option {string} from {string}When I check {string}
When I pw check {string}When I uncheck {string}
When I pw uncheck {string}When I upload file {string} to {string}
When I pw upload file {string} to {string}When I pw click {string} inside frame {string}
When I pw click {string} inside frame {string}When I pw fill {string} inside frame {string} with {string}
When I pw fill {string} inside frame {string} with {string}When I pw expect {string} inside frame {string} to have text {string}
When I pw expect {string} inside frame {string} to have text {string}📄 License
MIT © 2024

