How do I re-use expressions in Cucumber?

30 Views Asked by At

I have this scenario where I want to check if a banner element exists on each page.

I have created a separate banners.js file that contains the (Selenium Webdriver) Javascript that does the check:

./components/banner.js

const { By } = require('selenium-webdriver');

async function checkBannerExists(webdriver, bannerClass) {
    var banner = await webdriver.driver.findElement(By.className(bannerClass)).getRect();
    return banner.height;
  };

module.exports = { checkBannerExists };

And I can simply call it in a step's file expression when I need it:

const banners = require("../../components/banners");

Given('I am on the home page',  async function () {
    this.driver = new Builder()
        .forBrowser('firefox')
        .build();
    
    this.driver.wait(until.elementLocated(By.tagName('h1')));
    await this.driver.get('https://www.awebsite.com');
});

Then('there should be a banner', async function() {
    var homeBanner = await banners.checkBannerExists(this, 'banner');
    assert.ok(homeBanner!==null);
});

All good there.

But if I add this same expression to another page, eg:

const banners = require("../../components/banners");

Given('I am on the about us page',  async function () {
    this.driver = new Builder()
        .forBrowser('firefox')
        .build();
    
    this.driver.wait(until.elementLocated(By.tagName('h1')));
    await this.driver.get('https://www.awebsite.com/about');
});

Then('there should be a banner', async function() {
    var homeBanner = await banners.checkBannerExists(this, 'banner');
    assert.ok(homeBanner!==null);
});

I get the error Multiple step definitions match:

Is there a way I can re-use the same expression across multiple steps and features files?

1

There are 1 best solutions below

0
MeltingDog On

I ended up doing a different approach to this using Scenario Outline where you use the same .feature file and give it multiple pages:

genericBannerTest.feature

Feature: Generic Banner Tests
 
    Scenario Outline: Run a check for generic banner
        Given I am on the '<page>' page
        Then there should be a banner on the '<page>' page

    Examples: 
        | page     |
        | /        |
        | /contact |
        | /about   |
        | /products|

genericBannerTestSteps.js

const banners = require("../components/banners");
// other required stuff

Given('I am on the {string} page', async function (string) {
    this.driver = new Builder()
        .forBrowser('firefox')
        .build();
    
    this.driver.wait(until.elementLocated(By.tagName('h1')));
    await this.driver.get('https://www.awebsite.com' + string);
});

Then('there should be a banner on the {string} page', async function(string) {
  let bannerClass = 'banner-module'
  if (string == '/') {
    bannerClass = 'home-banner';
  }
  else if (string == '/product-banner') {
    bannerClass = 'prod-short';
  }

  var banner = await banners.checkBannerExists(this, bannerClass);
  assert.ok(banner!==null);
});

banner.js

const { By } = require('selenium-webdriver');

async function checkBannerExists(webdriver, bannerClass) {
  var banner = await webdriver.driver.findElement(By.className(bannerClass)).getRect();
  return banner.height;
};

module.exports = { checkBannerExists };