Huckleberry Carignan
Huckleberry Carignan

Reputation: 2318

Using CucumberJS / Puppeteer, how do you extend the Page object with multiple scenarios?

I am writing a test automation suite using Puppeteer and CucumberJS.

I'm having an issue where the Page object is not being passed between scenarios in a feature file.

Test_1.features

Feature: Login and hit some buttons
    In order to show my issue
    As a stackOverflow users
    I want be able to login and select some buttons

  Scenario: Log in
      Given I have navigated to to the App "foobar"
      When I have selected the Imports button 
      I should see the Console on the page title

      When I have selected the Imports button 
      Then I should see the Imports on the page title

Test_2.features

Feature: Login and hit some buttons
    In order to show my issue
    As a stackOverflow users
    I want be able to login and select some buttons

  Scenario: Log in
      Given I have navigated to to the App "foobar"
      When I have selected the Imports button 
      I should see the Console on the page title

  Scenario: Navigate from the Imports page/list to the Console
      When I have selected the Imports button 
      Then I should see the Imports on the page title

I have a world.js

'use strict';

const { setWorldConstructor } = require("cucumber");
const puppeteer = require("puppeteer");

class thisApp {
  constructor() {
      this.app = "";
  }

// Open browser
async openBrowser() {
  this.browser = await puppeteer.launch({
  headless: false,
  slowMo: 25 
  });
  this.page = await this.browser.newPage();
}

async appLogIn(username_password) {
   await this.page.waitFor(settings._3000);
   await this.navigateToAppLoginPage();
   await this.appEnterUsernamePassword(username_password);
   await this.page.click('[data-test-button-SignIn="true"]');
   await this.page.waitFor(settings._3000);
}

// Select the Imports button
async selectButtonNavigationPaneImports() {
  await this.page.click('[data-test-button-navigation-pane-imports="true"]');
}

// Select the Console button
async selectButtonNavigationPaneConsole() {
  await this.page.click('[data-test-button-navigation-pane-console="true"]');
}

}
setWorldConstructor(ePayApp);

I have not put all the steps on there - I'm just trying to give an example.

app_steps.js

// Login
 Given(/^I have navigated to to the App "([^"]*)"$/, async 
  function(username_password){
  return this.appLogIn(username_password);
});

// import button
 When(/^I have selected the Imports button$/, async 
  function(){
  return this.selectButtonNavigationPaneImports();
});

// console button
 When(/^I have selected the Console button$/, async 
  function(){
  return this.selectButtonNavigationPaneConsole();
});

I have the index.js

const { BeforeAll, Before, AfterAll, After } = require('cucumber');
const puppeteer = require('puppeteer');

Before(async function() {
   const browser = await puppeteer.launch({ headless: false, slowMo: 50 });
  this.browser = browser;
  this.page = page;
})

Now, when I have all the steps under one scenario (Test_1.features), it works. When I break the tests into multiple scenarios (Test_2.features), I get:

 TypeError: Cannot read property 'click' of undefined

Which makes me believe that the page object isn't being accessed in the second scenario.

What am I doing wrong?

Upvotes: 0

Views: 1467

Answers (1)

Lean Prop
Lean Prop

Reputation: 111

With 2 scenarios, you have completely different World objects. The member you initiated in the first scenario will be recreated in the hook function of the second scenario, which may probably be the cause of your problem.

"Before" hook will be executed for each scenario, so you have two different browser in each scenario.

Upvotes: 0

Related Questions