Skip to main content

Serenity/JS for Cucumber Users

Already using Cucumber.js? Serenity/JS plugs right into your existing setup — with Playwright or WebdriverIO driving the browser.

You keep Cucumber's Gherkin syntax, step definitions, and hooks. Serenity/JS adds the Screenplay Pattern, structured reporting, and multi-actor support that matter once your feature files outgrow a handful of scenarios.


Why add Serenity/JS?

Serenity/JS works on top of Cucumber.js — your existing feature files, step definitions, and CI/CD pipeline all stay exactly as they are. You don't need to rewrite anything.

Here's how Serenity/JS helps you address common Cucumber challenges:

ChallengeHow Serenity/JS helps
Step definitions coupled to selectorsThe Screenplay Pattern gives you composable Tasks that separate what from how
Reports show only pass/failSerenity BDD reports generate living documentation organised by feature and capability
Multi-user workflows are awkwardMulti-actor support is built in — actorCalled('Alice') and actorCalled('Bob') in the same scenario
Step definitions are hard to reuseScreenplay Tasks are composable and portable — reuse them across step definitions, scenarios, and projects
Locked into one browser driverScreenplay Tasks work with both Playwright and WebdriverIO — switch without rewriting logic
Slow UI-only test suitesBlended testing — use APIs for setup, UI only where it matters

Get started in 5 minutes

The progression most teams go through looks like this:

  1. Add reporting (Steps 1–3) — configure the Serenity/JS adapter and reporters. Existing scenarios get better reports immediately.
  2. Use Screenplay for new step definitions (Step 4) — use the actor model for new scenarios. Old step definitions stay untouched.
  3. Extract shared Tasks — refactor common workflows into reusable building blocks.
  4. Blended testing — mix UI and API interactions in the same scenario for speed and reliability.

Step 0: Create a Cucumber project

Already have a Cucumber project?

Skip this step and proceed with the remaining steps from your project directory.

Create a new directory and initialise a Cucumber project:

mkdir my-serenity-project
cd my-serenity-project
npm init -y
npm install --save-dev @cucumber/cucumber typescript ts-node @types/node

Create a tsconfig.json:

tsconfig.json
{
"compilerOptions": {
"target": "ES2021",
"module": "commonjs",
"lib": ["ES2021"],
"strict": true,
"esModuleInterop": true,
"outDir": "./lib"
}
}

Step 1: Install

Prerequisites

You'll need a recent Node.js LTS version (Serenity/JS supports Node 20, 22, and 24), as well as Java 11+ for the Serenity BDD reports.

npm install --save-dev @serenity-js/core @serenity-js/cucumber @serenity-js/web @serenity-js/assertions @serenity-js/playwright @serenity-js/console-reporter @serenity-js/serenity-bdd rimraf npm-failsafe playwright

→ Learn more: Full Cucumber installation guide | Why Serenity/JS?

Step 2: Configure

Create a Cucumber profile that attaches the Serenity/JS adapter:

cucumber.yaml
default:
requireModule:
- ts-node/register
format:
- '@serenity-js/cucumber'
require:
- ./features/**/*.steps.ts
- ./features/**/*.config.ts

Create a Serenity/JS configuration file:

features/support/serenity.config.ts
import { BeforeAll, AfterAll } from '@cucumber/cucumber'
import { configure, Cast } from '@serenity-js/core'
import { BrowseTheWebWithPlaywright } from '@serenity-js/playwright'

import * as playwright from 'playwright'

let browser: playwright.Browser;

BeforeAll(async () => {
browser = await playwright.chromium.launch({ headless: true });

configure({
actors: Cast.where(actor =>
actor.whoCan(BrowseTheWebWithPlaywright.using(browser)),
),
crew: [
'@serenity-js/console-reporter',
[ '@serenity-js/serenity-bdd', { specDirectory: './features' } ],
[ '@serenity-js/core:ArtifactArchiver', {
outputDirectory: './reports/serenity'
} ],
],
});
});

AfterAll(async () => {
await browser?.close();
});

Add the following scripts to your package.json:

Reading the diffs

Lines marked with + should be added to your file; lines marked with - should be removed. Don't copy the +/- prefixes themselves.

package.json
 {
"scripts": {
+ "clean": "rimraf target",
+ "test": "failsafe clean test:execute [...] test:report",
+ "test:execute": "cucumber-js",
+ "test:report": "serenity-bdd run --features='./features' --source='./reports/serenity' --destination='./reports/serenity'"
}
}

→ Learn more: Cucumber configuration | Serenity BDD reporter setup | Using npm-failsafe

Step 3: Run

npm test

That's it. Your existing scenarios run as before, but now produce a rich HTML report in reports/serenity/. Open reports/serenity/index.html in your browser to view it.

Running a single scenario

The [...] wildcard in the test script is provided by npm-failsafe and passes any arguments you provide directly to Cucumber. For example, to run scenarios by name:

npm test -- --name="descriptive title"

Or to run scenarios by tag:

npm test -- --tags="@smoke"

→ Learn more: Reporting overview | Serenity BDD reports

Example Serenity BDD report generated by Serenity/JS (source)

Step 4 (optional): Write your first Screenplay scenario

Steps 1–3 give you better reporting with zero changes to your step definitions. When you're ready to see what the Screenplay Pattern looks like with Cucumber, add a new feature file and step definitions:

features/website.feature
Feature: Website

Scenario: The serenity-js.org website should have a descriptive title
When Serena navigates to "https://serenity-js.org/"
Then she should see that the page title includes "Serenity/JS"
features/step-definitions/parameter.steps.ts
import { defineParameterType } from '@cucumber/cucumber'
import { actorCalled, actorInTheSpotlight } from '@serenity-js/core'

defineParameterType({
regexp: /[A-Z][a-z]+/,
transformer(name: string) {
return actorCalled(name);
},
name: 'actor',
});

defineParameterType({
regexp: /he|she|they|his|her|their/,
transformer() {
return actorInTheSpotlight();
},
name: 'pronoun',
});
features/step-definitions/website.steps.ts
import { When, Then } from '@cucumber/cucumber'
import { Actor } from '@serenity-js/core'
import { Ensure, includes } from '@serenity-js/assertions'
import { Navigate, Page } from '@serenity-js/web'

When('{actor} navigates to {string}', async (actor: Actor, url: string) => {
await actor.attemptsTo(
Navigate.to(url),
);
});

Then('{pronoun} should see that the page title includes {string}', async (actor: Actor, expectedTitle: string) => {
await actor.attemptsTo(
Ensure.that(
Page.current().title().describedAs('current page title'),
includes(expectedTitle),
),
);
});

Run npm test again. In the Serenity BDD report you'll now see each interaction (Navigate.to, Ensure.that) listed as a separate step with timing.

The key differences from plain Cucumber step definitions:

  • parameter.steps.ts registers the {actor} and {pronoun} Cucumber expression parameter types that Serenity/JS uses to resolve actors by name.
  • actorCalled('Serena') creates a named actor — the actor has a browser, but can also interact with REST APIs, multiple browser contexts, etc.
  • Navigate.to() and Ensure.that() are composable interactions that show up as named steps in your reports.
  • {actor} and {pronoun} automatically resolve to the correct actor instance based on the name or pronoun used in the Gherkin step.

For a more advanced example showing composable Tasks, the Lean Page Objects pattern, and masked credentials, see the Complete example below.

→ Learn more: Screenplay Pattern | Your first web scenario

Same Tasks, different runner

Screenplay Tasks are identical whether you use Cucumber, Playwright Test, or WebdriverIO as your test runner — only the configuration differs. See Serenity/JS with Playwright.


Reference projects

Complete example

A self-contained project you can copy in full. It includes:

  • features/website.feature — a simple Screenplay scenario using Navigate and Ensure (same pattern as Step 4)
  • features/swag-labs.feature — a more advanced scenario interacting with the Swag Labs demo website, using composable Task definitions and the Lean Page Objects pattern

Run npm install then npm test — the Serenity BDD HTML report lands in reports/serenity/index.html.

Credentials in examples

The password secret_sauce is hard-coded in these examples to keep them simple and self-contained. In real-world tests, load credentials from environment variables or a password vault to avoid committing secrets to your repository.

features/swag-labs.feature
Feature: Swag Labs

Scenario: Standard user completes checkout
Given Alice has logged in with credentials "standard_user" and "secret_sauce"
When she adds "Sauce Labs Backpack" to the cart
And she completes checkout with:
| firstName | Alice |
| lastName | Smith |
| postalCode | 90210 |
Then she should see the confirmation "Thank you for your order!"

Project templates

If you'd rather start from a fully configured project than add Serenity/JS to an existing one, use one of these GitHub template repositories. Each comes with CI configuration, example tests, and live reports you can preview.

StackLive Report
Cucumber + PlaywrightSerenity BDD
Cucumber + WebdriverIOSerenity BDD

All project templates


FAQ

Does it slow down my tests?

No. Serenity/JS adds negligible overhead.

Do I have to rewrite all my step definitions?

No. Mix Screenplay and non-Screenplay step definitions in the same project. Start with reporting and introduce Screenplay gradually for new scenarios.

Can I use it with WebdriverIO instead of Playwright?

Yes. Replace @serenity-js/playwright with @serenity-js/webdriverio and configure the cast of actors accordingly. Your Tasks stay identical — only the Ability configuration changes. See the Cucumber + WebdriverIO template.

Do I need Java?

Yes, for the Serenity BDD HTML reports (Java 11+). If you'd rather stay Java-free, use the console reporter alone.

What Cucumber versions are supported?

Serenity/JS supports all modern versions of @cucumber/cucumber. The adapter detects your version automatically.

Something not working?

Check the Troubleshooting guide for solutions to common issues with reports, screenshots, and configuration.


Next steps

Using Playwright Test instead of Cucumber?

If you don't need Gherkin syntax, Serenity/JS works directly with Playwright Test or WebdriverIO for a simpler setup. See Serenity/JS with Playwright or Serenity/JS with WebdriverIO.