Transcripted Summary

After we finished our feature file, now it's time to write our step definition - to start implementing the steps from the feature file in real code using our page object, and our custom hooks, to be able to run with TestCafe test cases.

After that, we need to add the step definition, and cucumber.js as a file configuration to able to run Cucumber with TestCafe.

Here we have one tutorial under Cucumber documentation.

This is a guide for JavaScript, and here we can find also for Java, or Ruby, or Kotlin.

Here, we have the steps.

We already installed Cucumber, and we wrote our first scenario or feature.

Now, it's time to write our first step definition in JavaScript, and then run Cucumber.

Here, we have all the steps, for example, by creating the empty project at the start from scratch.

But, all of these features we have already.

We have a feature step definition, we just need to create one cucumber.js file, so we can just copy this one, and put it in the root of the project.

So, here in the root, we can create this file, and this file will help us with this configuration, to be able to run or export the module to run, with Cucumber JavaScript.

module.exports = {
    default: `--format-options '{"snippetInterface": "synchronous"}'`

Then, create a file with a step definition.

So, we already have a folder under features, with step_definitions.

After that, we can create a step definition file stepdefs.js. A

After that, we can add anything - for example - add Given, When, Then as constants to be able to import.

And for verifying a Cucumber installation, we can run npm test or run a standalone.

Let's try to run this code and see if it works or not.

Let's open the terminal, and here we can just run:

npm test

Now, TestCafe is running, but this will run our old configuration, so let's stop this one, and just copy this and run it:


Here we have 1 scenario is undefined, and we have to 12 steps undefined, also.

So, let's go to the first thing. So, here we have a warning - this scenario - New User Registration Scenario is undefined.

So, we need to Implement the following snippet.

So, this is like Java.

We can use Given, so I can copy this Given, and the When, and we can add all the things that are related to adding, and after that, we can create our step definition file.

So, in our step definition JavaScript file, we can just copy these two imports, or these two constants and add it in stepdefs.js:

const assert = require('assert');
const { Given, When, Then } = require('cucumber');

After that, we need to copy all the functions from the test result, to be able to implement this step definition.

So, we will copy this one with Given, and then we will copy When until we reach the end.

const assert = require('assert');
const { Given, When, Then } = require('cucumber');

Given('I open the registration page', async function () {

  When('I select the gender', async function () {

  When('I enter First Name {string}', async function (firtname) {

  When('I enter Last Name {string}', async function (lastname) {

  When('I select Date of Birth {string}', async function (day) {

  When('I select Month of Birth {string}', async function (month) {

  When('I select Year of Birth {string}', async function (year) {

  When('I enter Email {string}', async function (email) {

  When('I enter Password {string}', async function (password) {

  When('I enter Confirm Password {string}', async function (password) {

  When('I click register button', async function () {

  Then('successfull message is displayed', async function () {

I finished now, and I kept all functions from the command line from the result of when we ran the feature file with the set definition.

After that, we just need to remove the return 'pending'; and add async before function to be able to start using our step definition with the page object.

Now, let's try to run our command line again with cucumber.js after we added the implementation of the functions here, then we can just check the result.

So, here we have 1 scenario pending - it's not undefined anymore.

One step, or one scenario, or one step is pending, and 11 are skipped.

So, we can go up, and here we can find that, "Given I open the registration" is pending.

Here we can find when I select the gender when I enter the first name, the value from the feature file, last name, birthday, and the month - and all the data are displaying here.

So, then, what we need to do is remove the return 'pending', add our page object, and complete our step definition.

We will start by adding our URL because our step definition will be our test case.

We don't need to create a new test here; we will not use the RegistrationTest from our test package.

So, here we will add the URL. I will add const URL, and then I will pass the URL, this is hitting the register link, directly - we are not opening the homepage.

After that, we click on the Register link.

Now we have also another option that we can redirect directly to the Register link.

After that, with Given, we can just remove the inner sample code and start writing our case.

We just need to clean these two lines from each function.

After that, we need to add async, with the functions to be ready to run with TestCafe.

So, I removed all the unused code and after that, I added async, or, asynchronous for each function.

I still have one change in this step definition - I need to remove the string parameter string to rename it with the actual value - for example, last name, and first name, and so on.

So, I will just give it a name with a firstname lowercase.

Then here, this is the lastname.

This is the date or the day.

Here is the month, and this is year, and this is the userEmail.

And this is a password. This also, for confirmation, it would be password.

And, we don't have any parameters after that, so we can save.

So, now, our step file is waiting to call the functions, or the elements, from the page object class.

Under the page folder, I just leave the RegisterPage.js from our previous demo.

Here, we will find that this structure - or this file - will not work with the BDD, and step definition, and Cucumber.

We usually assume that we will use this class with the test case, using fixture and TestController, with TestCafe.

But in our case, we are running it from a step definition, and we are using a custom hook, and custom controller.

So, we need to refactor this file, to be able to work with BDD and step definition file.

Because we will use a different way with the page object.

So, I will just copy the RegisterPage.js and rename it to RegisterPage_old.js, and we will use this original.

So, we will just remove the constructor from this class, and asynchronous, and we will not use this export anymore, because we will use a normal class.

And then, we need to import Selector and we will remove the t, and we can just use something called require.

const {Selector} = require('testcafe');

class RegisterPage{


After that, we can create one function for the selector.

We have a function with select, just to implement the selector inside it, and take a selector as a parameter.

Inside this function, return Selector from TestCafe, and then passing the selector, then .with(), passing boundTestRun and, in this case, as a testController.

If you open boundTestRun, in the documentation or the TestCafe file, the definition is: "If we need to call a selector from a Node.js callback, and assign the current test controller to the boundTestRun option".

So, we are just using it to try to use a test controller with boundTestRun.

After that, we can, with our custom controller and our hook, we can use this file (RegisterPage.js).

So, this is to be able to run or to create the selector with the page object. After that, this test controller will be passed with our custom file.

Inside the class, we can just add here, exports.RegisterPage = and after that, we can start writing our page objects.

We will create a function for each element.

We will start with the gender element.

So GenderButton is a function and it will return select('#gender-male');.

Then, we will do the same implementation for the rest,

For example, for FirstName, this is a function, and with the function, we can return a select, and pass the selector. So, return select('input#Firstname')

We need to add a comma between elements.

const {Selector} =  require('testcafe');

function select(selector){
    return Selector(selector).with({boundTestRun:testController})

exports.RegisterPage ={
    GenderButton: function() {
        return select('#gender-male');

      Firstname : function()
        return select('input#FirstName');

      Lastname : function()
        return select('#LastName');

      DateOfBirth : function(){
        return select("select[name='DateOfBirthDay']");
      MonthOfBirth : function(){
        return select("select[name='DateOfBirthMonth']");

      YearOfBirth : function(){
        return select("select[name='DateOfBirthYear']");

      Email : function()
        return select('#Email');

      Password : function()
        return select('#Password');

      ConfirmPassword : function()
        return select('#ConfirmPassword');

      RegistrationButton: function(){
        return select('#register-button.button-1.register-next-step-button');

      SuccessfullMessage: function(){
        return select('div.result').withText('Your registration completed');
      ListOption : function(){
        return select('option');

I've add all the elements - so, this is the FirstName, LastName, DateOfBirth, MonthOfBirth, YearOfBirth, Email, Password,ConfirmPassword, RegistrationButton, and SuccessfullMessage.

And ListOption to be able to get the option inside the drop-down list. So, now, we finish refactoring our page class for registration.

After that, we can start using it in our step definition file.



The quiz for this chapter can be found in 9.7

© 2024 Applitools. All rights reserved. Terms and Conditions Privacy Policy GDPR