</>

Technology

Playwright

Difficulty

Advanced

Interview Question

How do you integrate Playwright with Cucumber BDD?

Answer

Playwright + Cucumber BDD Integration

Installation

Bash
npm install --save-dev @cucumber/cucumber @playwright/test
npm install --save-dev playwright-cucumber-js
# OR use the community package:
npm install --save-dev @badeball/cypress-cucumber-preprocessor  # (for Cypress)
npm install --save-dev @cucumber/cucumber

Popular setup with @cucumber/cucumber + @playwright/test directly:

Bash
npm install --save-dev @cucumber/cucumber @playwright/test playwright

Feature File

Gherkin
# features/login.feature
Feature: User Authentication
  As a registered user
  I want to log in to the application
  So that I can access my account

  Scenario: Successful login with valid credentials
    Given I am on the login page
    When I enter email "user@test.com" and password "password123"
    And I click the Sign In button
    Then I should be redirected to the dashboard
    And I should see the welcome message "Welcome back"

  Scenario Outline: Failed login with invalid credentials
    Given I am on the login page
    When I enter email "<email>" and password "<password>"
    And I click the Sign In button
    Then I should see error "<error>"

    Examples:
      | email              | password    | error                    |
      | wrong@test.com     | password123 | Invalid email or password |
      | user@test.com      | wrongpass   | Invalid email or password |
      | notanemail         | password123 | Please enter a valid email |

Step Definitions

TypeScript
// features/steps/login.steps.ts
import { Given, When, Then } from '@cucumber/cucumber';
import { chromium, Browser, BrowserContext, Page } from '@playwright/test';
import { expect } from '@playwright/test';

let browser: Browser;
let context: BrowserContext;
let page: Page;

Given('I am on the login page', async () => {
  browser = await chromium.launch({ headless: true });
  context = await browser.newContext();
  page    = await context.newPage();
  await page.goto(process.env.BASE_URL + '/login');
});

When('I enter email {string} and password {string}', async (email: string, password: string) => {
  await page.getByLabel('Email').fill(email);
  await page.getByLabel('Password').fill(password);
});

When('I click the Sign In button', async () => {
  await page.getByRole('button', { name: 'Sign in' }).click();
});

Then('I should be redirected to the dashboard', async () => {
  await expect(page).toHaveURL(/dashboard/);
});

Then('I should see the welcome message {string}', async (message: string) => {
  await expect(page.getByRole('heading')).toContainText(message);
});

Then('I should see error {string}', async (errorText: string) => {
  await expect(page.locator('.error-message')).toContainText(errorText);
});

// Teardown
After(async () => {
  await context?.close();
  await browser?.close();
});

Cucumber Config

TypeScript
// cucumber.config.ts
export default {
  default: {
    paths: ['features/**/*.feature'],
    require: ['features/steps/**/*.ts'],
    requireModule: ['ts-node/register'],
    format: ['progress', 'html:reports/cucumber-report.html'],
    parallel: 2,
    retry: 1,
  },
};

Run Cucumber Tests

Bash
npx cucumber-js --config cucumber.config.ts

World Context (Share Page Between Steps)

TypeScript
// support/world.ts
import { setWorldConstructor, World } from '@cucumber/cucumber';
import { Browser, BrowserContext, Page, chromium } from '@playwright/test';

class PlaywrightWorld extends World {
  browser!: Browser;
  context!: BrowserContext;
  page!: Page;

  async init() {
    this.browser = await chromium.launch();
    this.context = await this.browser.newContext();
    this.page    = await this.context.newPage();
  }
}

setWorldConstructor(PlaywrightWorld);

Follow AutomateQA

Related Topics