Skip to main content

external@serenity-js/playwright-test

NPM Version Build Status Maintainability Code Coverage Contributors Known Vulnerabilities GitHub stars

Follow Serenity/JS on LinkedIn Watch Serenity/JS on YouTube Join Serenity/JS Community Chat Support Serenity/JS on GitHub

@serenity-js/playwright-test brings full Serenity reporting capabilities to Playwright Test and provides fixtures that enable writing tests using the Screenplay Pattern.

Learn more about using Serenity/JS with Playwright Test

Features

  • Integrates Serenity/JS with Playwright Test using dedicated test fixtures
  • Supports testing websites, web apps, and HTTP APIs
  • Enables Screenplay Pattern APIs in Playwright Test scenarios
  • Supports all Serenity/JS reporting features and expands native Playwright Test reports
  • TypeScript-first design with strong typing for safer and more predictable test code.

Installation

Use an existing Playwright Test project or generate a new one by running:

npm init playwright@latest

Install the below Serenity/JS modules in your Playwright Test project directory:

npm install --save-dev @serenity-js/assertions @serenity-js/console-reporter @serenity-js/core @serenity-js/html-reporter @serenity-js/rest @serenity-js/web @serenity-js/playwright @serenity-js/playwright-test

See the Serenity/JS Installation Guide.

Quick Start

import { describe, it } from '@serenity-js/playwright-test'
import { Navigate, Page } from '@serenity-js/web'
import { Ensure, startsWith } from '@serenity-js/assertions'

describe('Website', () => {

it('should have a title', async ({ actor }) => {

await actor.attemptsTo(
Navigate.to('https://serenity-js.org/'),
Ensure.that(Page.current().title(), startsWith('Serenity/JS')),
)
})
})

Explore the in-depth Serenity/JS and Playwright Test integration guide in the Serenity/JS Handbook.

Serenity/JS Playwright Fixtures

To use Serenity/JS Screenplay Pattern APIs and benefit from the in-depth reporting capabilities, import Serenity/JS test fixtures instead of the default ones:

// todo_app.spec.ts
+ import { test } from '@serenity-js/playwright-test'
- import { test } from '@playwright/test'

test.describe('To-do app', () => {

test.describe('New Todo', () => {

test('should allow me to add todo items', async ({ page }) => {
//...
})
})
})

If you prefer, Serenity/JS also offers the more concise BDD-style describe/it syntax:

// todo_app.spec.ts
import { describe, it, test } from '@serenity-js/playwright-test'

test.use({
headless: true,
})

describe('To-do app', () => {

describe('New Todo', () => {

it('should allow me to add todo items', async ({ page }) => {
//...
})
})
})

Serenity/JS Screenplay Pattern Actors

Serenity/JS test fixtures simplify how you manage the actors.

Single-actor scenarios

If your tests need only a single actor, you can inject it using the actor fixture. To configure the name of your default actor, use the defaultActorName configuration property:

// todo_app.spec.ts

// import fixtures
import { describe, it, test } from '@serenity-js/playwright-test'
// import Screenplay Pattern web APIs
import { Navigate, Page } from '@serenity-js/web'
// import Screenplay Pattern assertion APIs
import { Ensure, equals } from '@serenity-js/assertions'

test.use({
headless: true,
// change default actor name
defaultActorName: 'Serena'
})

describe('To-do app', () => {

describe('New Todo', () => {

// inject default actor:
it('should allow me to add todo items', async ({ actor }) => {

// define test workflow
await actor.attemptsTo(
Navigate.to('https://todo-app.serenity-js.org/'),
Ensure.that(Page.current().title(), equals('Serenity/JS TodoApp')),
)
})
})
})

Multi-actor scenarios

For multi-actor scenarios, for example where you need each actor to use a separate browser, use the actorCalled fixture.

// todo_app.spec.ts

import { describe, it, test } from '@serenity-js/playwright-test' // import fixtures

test.use({
// change default actor name
defaultActorName: 'Alice'
})

describe('To-do app', () => {

describe('Chat app', () => {

it('should allow actors to send and receive messages', async ({ actor, actorCalled, browser }) => {

// Define part of the workflow performed by the default actor:
await actor.attemptsTo(
// Navigate to a chat app...
// Post a message to Bob...
)

// Fefine parts of the workflow performed by the any other actors.
// Note that invoking actorCalled(name) multiple times
// while using the same name and within the scope of a single test
// returns the same actor, so you don't need to cache them:
await actorCalled('Bob')
// The second actor can use a separate browser instance
.whoCan(BrowseTheWebWithPlaywright.using(browser))
.attemptsTo(
// Navigate to a chat app...
// Post a reply to Alice...
)


await actor.attemptsTo(
// Check if the reply from Bob is received
)
})
})
})

To learn more about customising actors and managing their abilities, see the Serenity/JS Handbook section on Playwright Test customisation.

Customising test fixtures

The useFixtures function lets you configure your actors in a single place, and define custom test fixtures if needed.

// my-custom-api.ts
export const {
describe, it, test, beforeAll, beforeEach, afterEach, afterAll, expect
} = useFixtures<{ email: string }>({

// Override Serenity/JS fixtures:
actors: async ({ browser, baseURL }, use) => {
await use(
Cast.where(actor => actor.whoCan(
BrowseTheWebWithPlaywright.using(browser),
TakeNotes.usingAnEmptyNotepad(),
CallAnApi.at(baseURL),
))
)
},

// Add your own fixtures:
email: async ({ actor }, use) => {
await use(`${ actor.name }@example.org`);
},
})

Next, use your custom test API definition in your test files:

// todo_app.spec.ts
import { Log } from '@serenity-js/core'

// Import describe/it/test from your custom API
import { describe, it, test } from './my-custom-api'

describe('To-do app', () => {

describe('New Todo', () => {

// inject default actor:
it('should allow me to add todo items', async ({ actor, email }) => {

// define test workflow
await actor.attemptsTo(
Log.the(email),
)
})
})
})

UI Component Testing

You can use Serenity/JS and Playwright Test to write UI component tests and reuse your test code between component and end-to-end test suites.

To get started with component testing:

// src/App.spec.tsx
- import { test, expect } from '@playwright/experimental-ct-react'
+ import { test as componentTest } from '@playwright/experimental-ct-react'
+ import { useBase } from '@serenity-js/playwright-test'

+ const { test, expect } = useBase(componentTest)

import App from './App'

test.use({ viewport: { width: 500, height: 500 } })

test('should work', async ({ mount }) => {
const component = await mount(<App />)
await expect(component).toContainText('Learn React')
})

Using Serenity/JS actors for Component Testing

Serenity/JS useBase(test) creates a test API that gives you access to all the SerenityFixtures you could access in any other regular end-to-end test.

This capability allows you to use Serenity/JS actors and design and experiment with your tasks before incorporating them in your high-level acceptance and end-to-end tests.

import { test as componentTest } from '@playwright/experimental-ct-react'
import { Ensure, contain } from '@serenity-js/assertions'
import { useBase } from '@serenity-js/playwright-test'
import { Enter, PageElement, CssClasses } from '@serenity-js/web'

import EmailInput from './EmailInput'

const { it, describe } = useBase(componentTest).useFixtures<{ emailAddress: string }>({
emailAddress: ({ actor }, use) => {
use(`${ actor.name }@example.org`)
}
})

describe('EmailInput', () => {

it('allows valid email addresses', async ({ actor, mount, emailAddress }) => {
const nativeComponent = await mount(<EmailInput/>)

const component = PageElement.from(nativeComponent)

await actor.attemptsTo(
Enter.theValue(emailAddress).into(component),
Ensure.that(CssClasses.of(component), contain('valid')),
)
})
})

Explore the in-depth Serenity/JS and Playwright Test integration guide in the Serenity/JS Handbook.

Reporting

To use Serenity/JS reporting capabilities, register the @serenity-js/playwright-test reporter in your playwright.config.ts and define the appropriate reporting services (a.k.a. your "stage crew").

For example, to enable Serenity/JS Console Reporter and HTML Reporter, install the relevant modules:

npm install --save-dev @serenity-js/console-reporter @serenity-js/html-reporter

Next, configure your Playwright project as follows:

// playwright.config.ts

import { defineConfig } from '@playwright/test';
import { SerenityFixtures, SerenityWorkerFixtures } from '@serenity-js/playwright-test';

export default defineConfig<SerenityFixtures, SerenityWorkerFixtures>({
testDir: './spec',

reporter: [
[ '@serenity-js/playwright-test', {
crew: [
'@serenity-js/console-reporter',
[ '@serenity-js/html-reporter', {
outputDirectory: './reports/serenity-js',
specDirectory: './spec',
} ],
// '@serenity-js/core:StreamReporter',
]
}],

// optional
[ 'html', { open: 'never' } ], // built-in Playwright HTML reporter
],

// Other configuration omitted for brevity
// For details, see https://playwright.dev/docs/test-configuration
})

Serenity/JS reporters work well with native Playwright reporters.

Using Serenity BDD? If you prefer Serenity BDD reports, see the Serenity BDD Reporter documentation.

Documentation

Contributing

Contributions of all kinds are welcome! Get started with the Contributing Guide.

Community

If you enjoy using Serenity/JS, make sure to star ⭐️ Serenity/JS on GitHub to help others discover the framework!

License

The Serenity/JS code base is licensed under the Apache-2.0 license, while its documentation and the Serenity/JS Handbook are licensed under the Creative Commons BY-NC-SA 4.0 International.

See the Serenity/JS License.

Support

Support ongoing development through GitHub Sponsors. Sponsors gain access to Serenity/JS Playbooks and priority help in the Discussions Forum.

For corporate sponsorship or commercial support, please contact Jan Molak.

GitHub Sponsors

Index

Type Aliases

externalPlaywrightTestConfig

PlaywrightTestConfig<TestArgs, WorkerArgs>: BasePlaywrightTestConfig<SerenityFixtures & TestArgs, SerenityWorkerFixtures & WorkerArgs>

Convenience alias for PlaywrightTestConfig object that includes SerenityFixtures and SerenityWorkerFixtures and allows for any other custom options when needed.

Example

Configuring Playwright Test using the standard PlaywrightTestConfig from @playwright/test:

// playwright.config.ts
import type { PlaywrightTestConfig } from '@playwright/test'
import type { SerenityFixtures, SerenityWorkerFixtures } from '@serenity-js/playwright-test'

const config: PlaywrightTestConfig<SerenityFixtures & MyCustomOptions, SerenityWorkerFixtures> = {
// ...
}

export default config

Simplified configuration using Serenity/JS PlaywrightTestConfig from @serenity-js/playwright-test:

// playwright.config.ts
import type { PlaywrightTestConfig } from '@serenity-js/playwright-test'

const config: PlaywrightTestConfig<MyCustomOptions> = {
// ...
}
export default config

Learn more


Type parameters

  • TestArgs = object
  • WorkerArgs = object

externalTestApi

TestApi<TestArgs, WorkerArgs>: Pick<TestType<TestArgs, WorkerArgs>, describe | beforeAll | beforeEach | afterEach | afterAll | expect> & { useFixtures: <T, W>(customFixtures: Fixtures<T, W, TestArgs, WorkerArgs>) => TestApi<TestArgs & T, WorkerArgs & W>; it: TestType<TestArgs, WorkerArgs>; test: TestType<TestArgs, WorkerArgs> }

Serenity/JS BDD-style test API created by useBase.


Type parameters

  • TestArgs: object
  • WorkerArgs: object

Variables

externalconstfixtures

fixtures: Fixtures<SerenityFixtures & SerenityInternalFixtures, SerenityWorkerFixtures & SerenityInternalWorkerFixtures, PlaywrightTestArgs & PlaywrightTestOptions, PlaywrightWorkerArgs & PlaywrightWorkerOptions> = ...
Page Options