Adding E2E Setup With PlayWright And Cucumber In TypeScript Project

Cucumber

Playwright

TypeScript

01/05/2023


In this post, I'll demonstrate how to set up an end-to-end (E2E) testing framework using Cucumber and Playwright in your TypeScript project.

Installing dependencies

First, add the following libraries as dev dependencies to your project.

BASH
yarn add --dev @cucumber/cucumber @playwright/test # OR
npm install --save-dev @cucumber/cucumber @playwright/test

Setting up Cucumber

It should be noted that the testing framework is operated entirely by Cucumber, and Playwright is merely plugged 🔌 into it. Theoretically, you can switch it out for any browser automation tool such as Cypress or Selenium.

Features folder

All your E2E code will live in a folder named features at the root of your project.

Feature file

Inside of your features folder, you'll will have .feature files which represent your Cucumber 🥒 files. To test the entire setup, let's create an example file.

features/greeting.feature
GHERKIN
Feature: Greeting
Scenario: Say hello
When the greeter says hello
Then I should have heard "hello"

Support file

In the background, your feature files are executed by TypeScript files located in a steps folder. Their file names must correspond to the name of the feature file they are executing.

features/steps/greeting.ts
TYPESCRIPT
import { When, Then } from "@cucumber/cucumber"
interface MyWorld {
whatIHeard: string
}
When("the greeter says hello", function(this: MyWorld) {
this.whatIHeard = "hello"
})
Then("I should have heard {string}", function(
this: MyWorld,
expectedResponse: string
) {
// Make assertion here
})

Configuration file

What we have so far is enough to execute an E2E test. However, for that to happen we have to specify a host of parameters in the CLI, such as the Typescript execution engine, the location of the step definitions, etc. We can avoid repeating 🙏 these parameters on every test run by creating a cucumber.mjs file at the root of your project that stores theses parameters.

cucumber.mjs
JAVASCRIPT
const configuration = {
requireModule: ["@swc-node/register"],
require: ["features/steps/**/*.ts"],
// Optional below
format: ["summary", "progress-bar"],
formatOptions: { snippetInterface: "async-await" },
}
export default configuration

Specify a TypeScript execution engine of your choice in requireModule, such as @swc-node or ts-node. Oddly, ts-node did not work for me. 🤔

I recommend checking out the overview of all the configuration options for further reference.

Installing Playwright

With the current setup in place, you can already execute 😲 the test with yarn/npm run cucumber-js with a pass. However, it's passing because we aren't making any assertions, for which we will use Playwright.

Returning to the step file, make the following changes:

DIFF
+ import { expect } from "@playwright/test";
# [...]
Then(
"I should have heard {string}",
function (this: MyWorld, expectedResponse: string) {
+ expect(this.whatIHeard).toEqual(expectedResponse);
}
);

To check if the assertion actually works, simply change the casing of the string "hello" and you will receive a failed ❌ test after running Cucumber.

DIFF
- this.whatIHeard = "hello"
+ this.whatIHeard = "Hello"

Failed Cucumber Test

While you are now capable of running tests, you are nevertheless missing the proper setup to keep each test independent of each other. Check out my walk-through on how to do so.


WRITTEN BY

Code and stuff