In this section we’ll be focusing on Scenario Outlines and running individual Feature Files.
So, this time we have three scenarios.
Let's go through the first one and see how it should work.
Feature: Menu Navigation — As a user, I want to be able to navigate throughout the website using the menu links to get to various pages.
Scenario: Navigating through the main menu options from the home page
Okay, great, so we know how that should work.
If you look at the other scenarios, we notice they're pretty much identical. The only difference being the menu option being selected.
Scenario Outlines are an easy way for us to repeat scenarios when we want different data for each scenario.
Let's start by creating the Feature File.
I'll create a sub folder called “Navigation” and a Feature File called “MenuNavigation”.
I'll start off by copying in the first scenario.
Now, the data that is different for each step is a menu option and the expected title for the page.
So, I've created an Examples
table with headers that match those requirements.
Great. Now I'll put the data for each of our 3 scenarios in the table.
The first scenario clicks on the “Women” menu option and expects the title to be “Women - My Store”
The second scenario clicks on “Dresses” and expects the title to be “Dresses - My Store”
And the last scenario clicks on “T-Shirts” and expects the title to be “T-Shirts - My Store”
Now, for the Examples
table to work, we need to change our Scenario
here to Scenario Outline
And the last step is to update our When
and Then
steps to pull the data from the example table.
We do this by referencing the header between angle brackets.
Feature: Menu Navigation
As a user, I want to be able to navigate through out the website using the menu links to get to various pages
Scenario Outline: Navigating through the main menu options from the home page
Given the browser is at the "Home" page
When the user clicks on the "<menuOption>" menu option in the menu
Then the title of the page should be "<pageTitle>"
Examples:
| menuOption | pageTitle |
| Women | Women - My Store |
| Dresses | Dresses - My Store |
| T-Shirts | T-shirts - My Store |
Now we need to define our When
and Then` steps.
We've already defined our Given
step in the previous section.
Based on our scenarios our tests will go to the home page, the “Women” catalog page, the “Dresses” page, and the “T-Shirts” page. These are all types of catalog pages, so I won't be creating any new page objects.
What I'll do is, update the Home
Page Object to include the selectors for the menu options.
First up is the womenMenuOption
, then the dressesMenuOption
, and the tshirtMenuOption
.
The next thing I'll do is right here in the Home
Page Object — I'll be creating a function to click on a menu option called selectMenuOption
.
I'll take a similar approach to our goToPage
function. I’ll rely on a switch
case that will test the parameter option to know which menu options to click.
class Home {
get url() {
return "/";
}
get searchField() {
return $("#search_query_top");
}
get searchButton() {
return $(".btn.btn-default.button-search");
}
get womenMenuOption() {
return $('ul.menu-content >li >a[title="Women"]');
}
get dressesMenuOption() {
return $('ul.menu-content >li >a[title="Dresses"]');
}
get tshirtMenuOption() {
return $('ul.menu-content >li >a[title="T-shirts"]');
}
/**
* Searches for a keyword
* @param {String} keyword Search term
*/
search(keyword) {
this.searchField.waitForDisplayed(2000);
this.searchField.setValue(keyword);
this.searchButton.click();
}
/**
* Clicks a menu option
* @param {String} option - Name of the menu option to click
*/
selectMenuOption(option) {
switch (option) {
case "Women":
this.womenMenuOption.click();
break;
case "Dresses":
this.dressesMenuOption.click();
break;
case "T-Shirts":
this.tshirtMenuOption.click();
break;
default:
console.log(`Invalid Option ${option}`);
}
}
}
module.exports = new Home();
So, if the option is “Women”, it will click on the womenMenuOption
. If the option is “Dresses”, you'll click on the dressesMenuOption
. And so on.
The next thing I'll do is create an action that we'll call this function — I'll call that action, "selectedMenuOption".
It will be pretty simple, all I will do is call the homepage function, select the menu option.
import home from "../../pages/Home";
export default option => {
home.selectMenuOption(option);
};
The last step to get to our When
step to work is, create a step definition for it.
I'll create this in the when.js
file that's in the Home
folder.
First, I'll import our action, then I'll define the step that calls it.
import { When } from "cucumber";
import search from "../../support/actions/search";
import selectMenuOption from "../../support/actions/selectMenuOption";
When(/^the user searches for "(.*)"$/, keyword => {
search(keyword);
});
When(/^the user clicks on the "(.*)" menu option in the menu$/, option => {
selectMenuOption(option);
});
Great.
Let's do a quick test run to see for test works.
Now, we have two Feature files — “DressSearch” and “MenuNavigation” — I only want to run the “MenuNavigation.feature” file.
To do that I have to specify which files to run at the command line. We can do that pretty easily by just adding a parameter to our command. The parameter is --spec
, followed by the path to the file you want to run.
./node_modules/.bin/wdio wdio.conf.js --spec ./features/Navigation/MenuNavigation.feature
Great, it looks like all of the menu options are being clicked.
We have an error because our Then
step is still undefined. Let's fix that right now.
For our Then
step, we need to verify the title of the page.
This is pretty easy with WebDriverIO API.
The first thing I'll do is, create an assertion file to verify a title, I'll call it “checkTitle”. Import the assert
library and define the function.
import assert from "assert";
/**
* @param {boolean} title expected title
*/
export default title => {
assert(
browser.getTitle() === title,
`Title, ${browser.getTitle()} not equal to ${title}`
);
};
So, this function takes 1 parameter, a title. Then it uses a WebDriver API, getTitle
to verify that the title on the browser is equal to the title that we passed.
Now we have to create the Step Definition for Then
to call it this assertion.
I'll do this in the Catalog “then.js” file.
I'll import our checkTitle
assertion and create our definition. This one should be familiar to you. It just checks for a wildcard to be passed within quotations.
import { Then } from "cucumber";
import checkNoResultsError from "../../support/assertions/checkNoResultsError";
import checkProducts from "../../support/assertions/checkProducts";
import checkProductsContain from "../../support/assertions/checkProductsContain";
import checkTitle from "../../support/assertions/checkTitle";
Then("a no results error message is shown", () => {
checkNoResultsError();
});
Then(/^(no )?products are listed$/, notListed => {
if (notListed) {
checkProducts(false);
} else {
checkProducts(true);
}
});
Then(/^search results show products related to "(.*)"$/, keyword => {
checkProductsContain(keyword);
});
Then(/^the title of the page should be "(.*)"$/, title => {
checkTitle(title);
});
So that should be all we need to get our tests are running and passing,
Let’s run our test again. And remember to run an individual file, you can pass --spec
along with the file path.
So, it clicks on each menu option — “Women”, “Dresses”, “T-Shirts” — and should verify the title.
Great. Let's move on to the next section.
Quiz
The quiz for this chapter can be found in section 5.3