How can I implement Before() and After() hooks within a hooks.js file for a Selenium and JavaScript project?

Within my Selenium JS / Cucumber framework, I have incorporated Before() & After() functions to handle the setup and tear down of my webdriver.

To manage these functions, I decided to organize them in my customSteps.js file alongside other cucumber steps. Here's a snippet of how it looks:

const { When, Then, Before, After } = require('@cucumber/cucumber')
const webdriver = require('selenium-webdriver')

let driver;

Before(() => {
    driver = new webdriver.Builder()
    .forBrowser('chrome')
    .build();
})

After(() => {
    driver.quit();
})

When('I go to {string}', {timeout: 2 * 5000}, async url => {
    await driver.get(url)
});

Then('the page header {string} is shown', async expectedPageHeader => {});

When('I click on the {string} button', async text => {});

Then('I am directed to the {string} page', async text => {});

When('the intro heading says {string}', async expectedPageHeader => {});

When('the intro subheading reads {string}', async expectedSubHeader => {});

In my package.json, here are the respective scripts:

"scripts": {
    "test": "node_modules/.bin/cucumber-js -f @cucumber/pretty-formatter features/test.feature"
}

Recently, my client advised me to migrate only the Given, When, & Then steps to my customSteps.js file, while relocating the Before() & After() functions to a separate hooks.js file within a designated support folder.

I've scoured online resources for guidance on implementing this structure in Selenium JavaScript, but without success thus far.

If anyone could offer advice on whether this reorganization is more efficient, as well as some tips on how to execute it successfully, I would greatly appreciate it. It's worth noting that these functions interact with my driver variable crucially utilized in the Given step for URL navigation.

Lastly, included below is an image illustrating my current directory arrangement for reference:

https://i.sstatic.net/jW95c.png

Answer №1

If you're utilizing the cucumber runner, it's advisable to place them in a separate file and then include it in the command.

Check out the following cucumber configuration file: cucumber.conf.js

const { Before, After } = require('@cucumber/cucumber');

Before(() => {
    global.driver = new webdriver.Builder()
    .forBrowser('chrome')
    .build();
})

After(() => {
    driver.quit();
})

To incorporate this setup, use the script below:

"scripts": {
    "test": "node_modules/.bin/cucumber-js --require cucumber.conf.js -f @cucumber/pretty-formatter features/test.feature"
  }

You can find a similar example using Playwright in this repository.

Answer №2

It ultimately comes down to how you choose to structure it.

The suggestion to separate Given/When/Then/And and hooks is a common best practice for improving the readability of StepDefs and simplifying troubleshooting in case of failures. Picture a scenario with 40-50 StepDef classes all containing Before/After hooks - it would quickly become disorganized and difficult to track what's happening before/after each scenario.

As for reusing the same instance of a driver across multiple StepDef classes, this article provides some insight: Sharing same selenium WebDriver between step definition files.

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

What is the best way to include default text in my HTML input text field?

Is it possible to include uneditable default text within an HTML input field? https://i.stack.imgur.com/eklro.png Below is the current snippet of my HTML code: <input type="text" class="form-control input-sm" name="guardian_officeno" placeholder="Off ...

Angular 13 does not currently have support for the experimental syntax 'importMeta' activated

Since upgrading to angular 13, I've encountered an issue while attempting to create a worker in the following manner: new Worker(new URL('../path/to/worker', import.meta.url), {type: 'module'}) This code works as expected with "ng ...

What is the best way to utilize jQuery in order to present additional options within a form?

Let's consider a scenario where you have an HTML form: <form> <select name="vehicles"> <option value="all">All Vehicles</option> <option value="car1">Car 1</option> <option value="car2">Car 2< ...

JavaScript: Dynamically load a script when a particular <a> element is in an active state

<script> function DisplayTag(){ var q1=document.getElementById( 'ctl00_ContentPlaceHolder1_ctl00_ctl00_Showcase' ).childNodes[1].innerHTML; var counter1=0; function executeScript(q1,counter1){ q1= document.getElementById( 'ctl00_Co ...

Tips for maintaining login status following a test using PHPUnit, Selenium, and php-webdriver

My goal is to execute multiple tests with a shared session, all starting with a login process. <?php class ExampleTest extends PHPUnit_Framework_TestCase { /** * @var \RemoteWebDriver */ protected $webDriver; ...

Unable to extract or store JSON response in a variable using Selenium with Python

Below is an example code snippet showing how to retrieve the desired result in the 'res' variable: from selenium import webdriver from selenium.webdriver.common.action_chains import ActionChains from selenium.webdriver.common.keys import Keys fro ...

A guide on retrieving the selected option from a dropdown menu with React Material UI

Utilizing Material UI React, I am constructing a dropdown menu containing various options. My concern is: if I choose two options from different dropdowns within the menu, how can I intercept or store which option was selected? Below is a snippet of my co ...

There seems to be a problem with how the navbar is being displayed in ResponsiveSlides.js

I am currently using WordPress, but I have come here seeking help with a jQuery/CSS issue. I am utilizing responsiveSlides.js to create a simple slideshow, however, when viewing it here at gallery link, it appears that something is not quite right. STEPS: ...

Enhance link with dynamic content using an AJAX call

I need help appending a picture after a link with the same URL as the link. The current AJAX code is producing the following result: <a href="images/Draadloos.png" data-lightbox="gallerij"></a> Here is an example of what I would like to achie ...

What is the best way to access the data stored within a Promise object in a React application?

Below is the snippet of my code that handles parsing application data: async function parseApplication(data: Application) { const fieldGroupValues = {}; for (const group of Object.keys(data.mappedFieldGroupValues)) { const groupValue = data.mappedF ...

execute web browser function using Node.js

Is it possible to use http to remotely send a request and retrieve data from a specific site, such as google.com? I'm curious about how to utilize node for browser actions, like navigating to google.com, interacting with the input bar, and triggering ...

Error caused by a nonexistent object in Selenium

try { catch (IOException e) { System.out.println("Test d"); } Whenever I execute the code above, I encounter the following exception: Exception in thread "main" java.lang.NullPointerException at test.testing.main(t ...

JavaScript and HTML are commonly used programming languages for developing

By utilizing JavaScript, I was able to generate a table dynamically based on user input. For example, if the user enters 3 and clicks "go", a table with 3 rows is created. Using the .keyup function allowed me to target a column successfully. However, an i ...

ObjectID is failing to store the hexadecimal values properly

Initially, the ObjectID in my Sails/Mongo database was stored like this: "_id" : ObjectId("557077fb836bdee256004232") However, something changed or happened, and now new records are stored differently: "_id" : { "_bsontype" : "ObjectID", "id" : ...

Attempting to single out various entities within a JSON array through the use of radio buttons

I am currently developing a website to showcase sports teams' schedules. Each team has its own JSON file containing relevant information that I aim to display upon selecting the team from a radio button. For instance, let's consider the example ...

Turning a lambda function into a function that is compatible with next.js API: A step-by-step guide

I am currently using an Instagram API to retrieve data from my personal profile, which is triggered by a lambda function on Netlify. Here is a snippet of the code: require('isomorphic-unfetch') const url = `https://www.instagram.com/graphql/quer ...

The getElementById function can only select one option at a time and cannot select multiple options

I'm having an issue with a JavaScript function that is supposed to allow me to select multiple options, but it's only selecting the first one. Here is the JavaScript code: function index(){ var a="${staffindex}".replace("[",""); ...

A custom JavaScript function designed to replicate Excel's functionality of dividing numbers by thousands

I've noticed a unique behavior in Excel where when a cell is in focus and you enter, for example, 1500.32, it displays as 1 500.32. However, once you click enter or move away from the cell, it changes to 1 500.32. I'm intrigued by how this works. ...

Deleting a string from a parameter

I have a string that reads: France (Republic of France) I am trying to extract only "France" and remove the rest of the string in parentheses. France (Republic of France) Any tips on how to achieve this? Thank you. ...

Exploring TypeScript Module Importation and WebPack Integration

Struggling with WebPack's injection of imported dependencies for a TypeScript project. The first challenge is getting TypeScript to recognize the imported module. In the header.ts file, there is a declaration of a module nested under vi.input, export ...