2

I am getting 'AfterAll hook errored' when attempting to close my browser at the end of my tests (using cucumber-js and selenium). 'this' is not referring to world as it does in my step.js files

This is my hooks.js file:

const { AfterAll, Before } = require("cucumber");

AfterAll(async function() {
  await this.browser.close();
});

and this is my world.js file:

const driver = require("selenium-webdriver");
require("chromedriver");
const browser = new driver.Builder().forBrowser("chrome").build();
const { setWorldConstructor, setDefaultTimeout } = require("cucumber");

class CustomWorld {
  constructor() {
    this.driver = driver;
    this.browser = browser;
    this.setDefaultTimeout = setDefaultTimeout(60 * 1000);
  }
}

setWorldConstructor(CustomWorld);
R. Cooper
  • 21
  • 1
  • 5
  • I don't use Cucumber but in other frameworks `*all` blocks have different `this` context rather than test blocks because test context is created for each test while `*all` are evaluated once. The reference confirms that. *World is an isolated context for each scenario, exposed to the hooks and steps as this*. You likely should set up and close `browser` for each test. – Estus Flask Oct 16 '18 at 17:32

2 Answers2

1

In a JS closure this is implicitly set to whatever the outer context is (usually global). You either need to .bind() your function to this or use the fat array notation:

AfterAll(async () => {
  await this.browser.close();
});
Rarblack
  • 4,559
  • 4
  • 22
  • 33
Jon Acker
  • 31
  • 6
1

Per the CucumberJS docs:

Unlike Before / After these methods will not have a world instance as this. This is because each scenario gets its own world instance and these hooks run before / after all scenarios.

It's unfortunate, as I've ran into this as well. My workaround thus far has been to declare the variable in a scope available to the beforeAll and afterAll hooks, and then import and assign that to the world object in it's file.

rawkfist0215
  • 1,445
  • 6
  • 21
  • 34