DEV Community

Swikriti Tripathi
Swikriti Tripathi

Posted on

How to automate tests for your website using Nightwatch.js? - Part 2- Writing tests

Before starting this blog please make sure you've followed through the previous blog. This blog is the continuation of the previous one.

We will be using BDD for writing tests meaning we will be writing a feature file first. We will be using Gherkin to write feature files.

Through Gherkin, we can write test cases in the native language which will be easier to understand by everyone involved in the project whether they're from the technical field or not. I'm going to explain some of the keywords and their usage, that are used in this blog for further information please visit their official website

Keywords

  • Feature: a short description about a software feature
  • Scenario: list of steps to describe a business rule

Syntax

Scenario: name of the scenario
Given [Preconditions or initial context of the system ]
When [Event or action]
Then [Expected output]
Enter fullscreen mode Exit fullscreen mode

Write a feature file

Inside tests/acceptance/ folder make a folder name feature. Inside this folder make a feature file named todo.feature, we will be writing a scenario in this file.

The UI of the application that I'm writing test on looks like this

UI of a todo app with input fileds and add button

UI of a todo app with an item added in the list

We can simply add todo items and remove them. For this blog, I'm going to write a test scenario for adding the item and checking if the item is displayed in the UI.

The feature file todo.feature looks like this

Feature: todo
  As a user
  I want to add an item to the todo list
  So that I can organize task

  Scenario: Add item to the todo list
    Given a user has navigated to the homepage
    When the user adds "test" to the todo list using the webUI
    Then card "test" should be displayed on the webUI
Enter fullscreen mode Exit fullscreen mode

You can add multiple scenarios in the same feature file as per your need.

Step Definitions

After writing scenarios we need to implement them, for this, we will create stepDefinitions. Create a folder stepDefinitions inside tests/acceptance/ and inside setDefinitions create a file todo.js.

Add the following script in your package.json in the scripts section

"test:e2e": "cucumber-js --require tests/acceptance/cucumber.conf.js --require tests/acceptance/stepDefinitions"
Enter fullscreen mode Exit fullscreen mode

We will use the test:e2e script for running the test.

Run selenium server

Using docker:
docker run -d --network="host" -v /dev/shm:/dev/shm selenium/standalone-chrome-debug
Enter fullscreen mode Exit fullscreen mode
using jar file: (inside the folder where your selenium server and chromedriver files are)
java -jar <name-of-seleniun-server-standalone>.jar -port 4444
Enter fullscreen mode Exit fullscreen mode

Now go to your terminal and from inside the root directory of your project run the feature file using the following script

npm run test:e2e <path-to-yourfeature-file>
Enter fullscreen mode Exit fullscreen mode

In my case

npm run test:e2e tests/acceptance/feature/todo.feature
Enter fullscreen mode Exit fullscreen mode

The above script will run the whole feature, if you want to run a particular scenario you can and the line number of the scenario at last like so

npm run test:e2e tests/acceptance/feature/todo.feature:6

Enter fullscreen mode Exit fullscreen mode

After running the feature file you will see an output similar to this in your terminal

Failures:

1) Scenario: Add item to todo list # tests/acceptance/feature/todo.feature:6
   ? Given a user has navigated to the homepage
       Undefined. Implement with the following snippet:

         Given('a user has navigated to the homepage', function () {
           // Write code here that turns the phrase above into concrete actions
           return 'pending';
         });

   ? When the user adds "clean room" to the todo list using the webUI
       Undefined. Implement with the following snippet:

         When('the user adds {string} to the todo list using the webUI', function (string) {
           // Write code here that turns the phrase above into concrete actions
           return 'pending';
         });

   ? Then card "clean room" should be displayed on the webUI
       Undefined. Implement with the following snippet:

         Then('card {string} should be displayed on the webUI', function (string) {
           // Write code here that turns the phrase above into concrete actions
           return 'pending';
         });


1 scenario (1 undefined)
3 steps (3 undefined)
0m00.001s (executing steps: 0m00.000s)

Enter fullscreen mode Exit fullscreen mode

You can copy these code templates and paste in your todo.js file. This is where we will write the implementation.

 Given('a user has navigated to the homepage', function () {
           // Write code here that turns the phrase above into concrete actions
           return 'pending';
         });
Enter fullscreen mode Exit fullscreen mode

First of all, import following in the file todo.js

const {Given, When, Then} = require('@cucumber/cucumber')
const {client} = require('nightwatch-api')
Enter fullscreen mode Exit fullscreen mode

Now find the CSS or XPath selector of various elements that will be involved in the test.

//css selectors
const todoInputField = '.todo-input'
const todoCreateButton = '.todo-button'
const todoListItem = '.todo .todo-item'
Enter fullscreen mode Exit fullscreen mode

You can do this by using the developer’s tool in the browser and inspecting each element you need.

inspecting an element using developer's tool

You can also check if the element is correct by using console.

making sure the element element is correct by printing it in console
Now we implement the steps.

Given('a user has navigated to the homepage', function () {
    return client.url("http://localhost:3000");
});


When('the user adds {string} to the todo list using the webUI', async function (item) {
    await client.waitForElementVisible(todoInputField)
        .click(todoInputField)
        .setValue(todoInputField, item)
        .click(todoCreateButton)
    return client
});

Then('card {string} should be displayed on the webUI', function (item) {
    return client.getText(todoListItem, function (result) {
        this.assert.equal(result.value, item)
    })
});

Enter fullscreen mode Exit fullscreen mode

At the Given step we navigated to the index page of our UI, this is the precondition. Each action that we perform to achieve certain output needs to be specified at the when step and at the Then step we check if the expected output has been achieved or not. The API commands used can be found on the official website of nightwatch.

The whole code together looks like this

const {Given, When, Then} = require('@cucumber/cucumber')
const {client} = require('nightwatch-api')

//css selectors
const todoInputField = '.todo-input'
const todoCreateButton = '.todo-button'
const todoListItem = '.todo .todo-item'

Given('a user has navigated to the homepage', function () {
    return client.url("http://localhost:3000");
});


When('the user adds {string} to the todo list using the webUI', async function (item) {
    await client.waitForElementVisible(todoInputField)
        .click(todoInputField)
        .setValue(todoInputField, item)
        .click(todoCreateButton)
    return client
});

Then('card {string} should be displayed on the webUI', function (item) {
    return client.getText(todoListItem, function (result) {
        this.assert.equal(result.value, item)
    })
});

Enter fullscreen mode Exit fullscreen mode

Now you can run the test again and they should pass.

npm run test:e2e tests/acceptance/feature/todo.feature                                

> todo@0.1.0 test:e2e
> cucumber-js --require tests/acceptance/cucumber.conf.js --require tests/acceptance/stepDefinitions "tests/acceptance/feature/todo.feature"

ℹ Connected to localhost on port 4444 (328ms).
  Using: chrome (87.0.4280.66) on linux platform.

..√ Element <.todo-input> was visible after 69 milliseconds.
.√ Passed [equal]: clean room == clean room
..

1 scenario (1 passed)
3 steps (3 passed)
0m06.385s (executing steps: 0m06.353s)


Enter fullscreen mode Exit fullscreen mode

Voila, you have successfully written and implemented an acceptance test! You can add more tests and features as per your project and need. Hope this blog helped you!

You can find the source code here

Top comments (0)