Serenity/JS: a Screenplay Pattern layer over Playwright, WebdriverIO and Cucumber
A TypeScript-native acceptance testing framework that gives your Playwright Test, WebdriverIO, or Cucumber test suite the architecture it needs to scale.
At a glance
- What is it?
- Serenity/JS does not replace a test runner, it adds an architecture on top of one, with reusable tasks that separate what a test does from how it does it, plus the reporting that makes the result readable by people who do not write the tests.
- Who is it for?
- Serenity/JS is the right tool for a team whose end to end suite has grown past the point where duplicated selectors, unclear reports and slow UI only flows are affordable, and it fits a TypeScript codebase that already runs Playwright Test, WebdriverIO or Cucumber.
- Can I use it commercially?
- Yes. Apache-2.0 is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
- Is it still maintained?
- Yes. The repository received new commits within the last day.
- What is it written in?
- Mainly TypeScript, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on October 22, 2026, and from our analysis. They are not legal advice.
Editorial analysis
An architecture layer, not another test runner
Serenity/JS is described as a TypeScript-native acceptance testing framework that gives your Playwright Test, WebdriverIO or Cucumber test suite the architecture it needs to scale. The project calls it a TypeScript-native test automation framework, and the repository is a monorepo of packages published under the @serenity-js scope.
The important word in that description is on top of. The documentation states it directly: Serenity/JS works on top of your existing tools, you do not replace anything, you add structure and reporting. Supported runners and integration tools include Playwright Test, WebdriverIO, Cucumber, Mocha and Jasmine.
That positioning explains the rest of the design. A runner knows how to start a browser, find a test file and report a pass or fail. Serenity/JS adds a vocabulary for describing what the test does, a way to record what actually happened, and a report format that a person can read.
Who it is for is a team that has outgrown a flat list of spec files. The reasons table in the documentation lists the symptoms: duplicated selectors and test logic, tests whose output does not tell you what they did, multi user workflows that are painful to implement, and stakeholders who cannot read the test report. Each of those is answered by a different piece of the framework, which is a good way to decide whether you need it.
The other audience is a team that plans to change tools. Because the tasks are written against the framework rather than against a runner, the documentation claims you can switch integration tools and test runners without rewriting the tests.
The Screenplay Pattern in one test
The example in the documentation is the fastest way to understand the model, because it looks like a specification rather than a script.
import { describe, it } from '@serenity-js/playwright-test'
import { Ensure, equals } from '@serenity-js/assertions'
import { Navigate } from '@serenity-js/web'
describe('Swag Labs', () => {
it('should let a standard user complete checkout', async ({ actor }) => {
await actor.attemptsTo(
Navigate.to('https://www.saucedemo.com/'),
Authenticate.withCredentials('standard_user', 'secret_sauce'),
Inventory.productCalled('Sauce Labs Backpack').addToCart(),
Checkout.completeWith({
firstName: 'Alice',
lastName: 'Smith',
postalCode: '90210',An actor performs activities, and each activity is a Task. Navigate, Authenticate, Inventory and Checkout are not functions you wrote, they are tasks that live in your code and describe intent: go somewhere, log in, put an item in the basket, complete the checkout with these details. The documentation is direct that each Task is reusable across scenarios, test runners and integration tools, and that the Screenplay Pattern is what separates what from how.
Assertions use the same shape. Ensure.that(Checkout.confirmationHeading(), equals('Thank you for your order!')) states the expectation in a form the framework can record, which is what lets a report show what was checked rather than only that a line of code passed.
The example also carries a security note worth repeating: the username and password there are public demo values from saucedemo.com, and in a real project you would use environment variables or a secrets manager.
Reporting is the part stakeholders read
The documentation lists hard to tell what a test did as one of the problems Serenity/JS addresses, and the answer is structured reports that show every action with timing and screenshots. Alongside that there is an HTML reporter with trends, consistency analysis and what the documentation calls living documentation.
The mechanism is a crew, which is a list of reporters that run alongside the tests. The Playwright Test configuration registers a Serenity/JS reporter whose crew contains a console reporter and an HTML reporter pointed at a spec directory and an output directory. The console reporter gives you something readable in the terminal during a run, and the HTML reporter produces the artefact that gets shared afterwards.
Two details make this practical. The HTML report is generated automatically when the tests finish, with no additional build step, so nothing has to be remembered after a run. And the report is not a static dump, since trends and consistency analysis are what turn a pile of results into something a team can read over time.
Multi actor support is the other structural feature, and it is described as built in rather than as an extension. A test that needs two users acting against the same system is a common requirement in anything with a shopping cart, a booking flow or a two party approval, and it is the kind of thing that is fiddly to add to a plain runner.
For a team where non engineers read the results, this is the part that changes the conversation, and it is the part that costs the most to build without a framework.
Blended testing is how the framework answers slow suites
Two entries in the reasons table describe the same idea from different sides, and it is the most distinctive capability in the project.
Logic duplicated across API and UI tests is answered by Screenplay Tasks working across interfaces. Slow UI only test suites are answered by blended testing, which means using APIs for setup and the user interface only where it matters.
The mechanism is that a task is written against a capability rather than against a page object, so the same intent, for example completing a checkout, can be carried out through the web module or through the rest module. The packages make this visible: @serenity-js/web and @serenity-js/rest are both first class parts of the install, and the documentation has a page on blended testing under web testing.
This is where the architecture pays for itself. In a plain Playwright suite, a test that needs a customer record to exist has to create it through the UI, which is slow, or through a request call written by hand outside the framework. With tasks, the setup step is a task like any other, and it can be executed as an API call when that is faster and as a UI action when the interface is what is under test.
The cost is that you have to write the tasks in a way that both paths can serve, which is a discipline that a team has to agree on. A framework that lets you mix paths without a rule produces a suite where some tests are fast for reasons nobody can reconstruct later.
Adding it to an existing Playwright Test project
The quick start is four steps, and none of them replaces your runner.
The first step is installing the modules.
npm install --save-dev @serenity-js/core @serenity-js/console-reporter @serenity-js/html-reporter @serenity-js/playwright @serenity-js/playwright-test @serenity-js/rest @serenity-js/web @serenity-js/assertionsThe second step is registering the reporter in playwright.config.ts, which is a diff against the file you already have.
import { defineConfig, devices } from '@playwright/test';
+ import { SerenityFixtures, SerenityWorkerFixtures } from '@serenity-js/playwright-test';
- export default defineConfig({
+ export default defineConfig<SerenityFixtures, SerenityWorkerFixtures>({
testDir: './tests',
// ... keep your existing settings ...
- reporter: 'html',
+ reporter: [
+ [ 'line' ],
+ [ '@serenity-js/playwright-test', {
+ crew: [
+ '@serenity-js/console-reporter',
+ [ '@serenity-js/html-reporter', {
+ specDirectory: './tests',
+ outputDirectory: './reports/serenity',The third step adds a test script to package.json, and the fourth is described as changing one import in your test files to use the Serenity/JS fixtures.
{
"scripts": {
+ "test": "npx playwright test"
}
}The point of that sequence is that adoption is incremental. The config change is additive, the script change is additive, and the import change is one line per file, so a team can convert a single spec and see the report before deciding whether to convert the suite.
Where Serenity/JS is the wrong tool
Four mismatches are worth being honest about.
The first is scale. If you have ten end to end tests, this framework is a lot of machinery. You would be learning a pattern, a task model, a reporting configuration and a set of module names, in exchange for structure you do not yet need. The overhead is real, and the documentation's own framing, that it gives a suite the architecture it needs to scale, implies the scale.
The second is the type. Serenity/JS is TypeScript native. A JavaScript suite can be migrated, but the value of the framework, which is type safety around actors, tasks and abilities, is diluted in a project that is not typed.
The third is a team that wants results, not structure. If the goal is a fast suite with clear failures and nothing more, a runner with its built in reporter, trace and screenshot support does that today without a pattern in between.
The fourth is an existing investment in a different abstraction. A suite already built on page objects with a well maintained helper layer will not benefit much from Screenplay Tasks, and migrating it means rewriting the layer. The documentation also carries Protractor era examples and a protractor.conf.js in the repository, which tells you the project has history with a runner that has since been retired, and that some of the examples are not the path a new project would take.
The monorepo behind the framework and how it releases
The build system is worth a look if you plan to contribute or to vendor parts of it.
The root package.json is a private monorepo manifest named serenity-js-monorepo, with a workspace version of 3.0.0-monorepo, and the packages live in a packages directory. The toolchain is pnpm with a workspace file, Lerna for the package graph and Nx for task running, with a pnpm-lock.yaml and a pnpm-workspace.yaml at the root. There are separate scopes for compiling and for testing, so a change can be compiled across the libraries, across the integration packages or across the examples, and the Makefile exposes those scopes as variables with a verify target that runs lint, compile, test and integration-test in sequence.
"scripts": {
"setup": "pnpm setup:protractor && pnpm setup:playwright && pnpm setup:webdriverio",
"setup:playwright": "npx playwright install --with-deps",
"setup:protractor": "npx tsx bin/install-browsers.ts [email protected] [email protected]",
"setup:webdriverio": "npx tsx bin/install-browsers.ts chrome@stable chromedriver@stable",
"clean": "rimraf target && lerna run clean",
"cc": "nx reset",
"lint": "eslint .",The examples directory is a good map of the supported combinations, with Playwright Test, WebdriverIO, Cucumber, Mocha and Jasmine variants, and separate examples for domain level testing, reporting and REST API level testing.
The licence is Apache-2.0, with a LICENSE.md and a NOTICE.md at the root, which is a permissive grant with an express patent clause. The release rhythm is fast: version 3.48.1 on 2026-10-08, 3.48.2 on 2026-10-09 and 3.49.0 on 2026-10-10, with the last push on 2026-10-19. Patch releases a day apart mean you should pin versions deliberately rather than track a floating range.
Editorial conclusion
Serenity/JS is the right tool for a team whose end to end suite has grown past the point where duplicated selectors, unclear reports and slow UI only flows are affordable, and it fits a TypeScript codebase that already runs Playwright Test, WebdriverIO or Cucumber. It is the wrong tool for a small suite with a handful of specs, for a team that has no appetite for a pattern and a reporting layer over its runner, and for a JavaScript project that has not standardised on TypeScript. Before adopting, run one existing scenario through the actor and attemptsTo style and check the HTML report output, and confirm that the reporter configuration in playwright.config.ts produces the crew you expect before you migrate the rest of the suite.
Frequently asked questions
What is Serenity/JS and what does it add to Playwright Test?
Serenity/JS is a TypeScript-native acceptance testing framework that works on top of existing tools rather than replacing them, and it supports Playwright Test, WebdriverIO, Cucumber, Mocha and Jasmine. It adds the Screenplay Pattern with reusable Tasks, multi actor support, structured reports with timing and screenshots, and an HTML reporter with trends and living documentation.
How do I add Serenity/JS to an existing Playwright Test project?
Install the @serenity-js modules with npm, register the Serenity/JS reporter in playwright.config.ts with a crew containing the console and HTML reporters, add a test script to package.json, and change the import in your test files to use the Serenity/JS fixtures. The HTML report is generated automatically when the tests finish, with no extra build step.
What is blended testing in Serenity/JS?
It is the practice of using APIs for setup and the user interface only where it matters, made possible by Screenplay Tasks working across interfaces. The @serenity-js/web and @serenity-js/rest packages are both first class, so the same intent can be carried out through a browser or through an API call.
Does Serenity/JS support multi user test scenarios?
Yes, multi actor support is described as built in rather than as an extension, and there is a dedicated handbook page for multi actor scenarios with Playwright Test. The documentation lists multi user workflows being hard to implement as one of the problems the framework addresses.
What licence is Serenity/JS released under?
It is released under the Apache-2.0 licence, with the licence file named LICENSE.md and a NOTICE.md at the root of the repository. The project is published to npm as a set of packages under the @serenity-js scope, with @serenity-js/core as the core package.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/serenity-js-serenity-js)Was this useful?