Table of Contents
Creating the Base Scenarios
Validate the Title of a Website
Creating the Cucumber Scenario
- Open up the ‘base-scenarios.feature’ file and add the following test scenario…
Feature: BaseScenarios These scenarios can be used in any project Scenario: 01. Validate the title of a website Given I am on the base page Then I see the page title contains "DuckDuckGo"
These steps are still undefined. If we try to run our test, it will fail, however it will output the undefined step definitions that we need, so let’s do that now.
Creating the Undefined Step Definitions
- Open up the Terminal (or Command prompt) window and change directory (cd) in to the root of your WebDriverIO project again…
cd your/Project/Root
- Run your test suite with the following command…
npm test
The test will obviously fail, but you will get output in the console like below…
************************************************************************* ** For Feature: BaseScenarios ** Step Definitions are not specified ** Copy and Paste the following snippet(s) into your step definitions Given(/^I am on the base page$/, () => { // Write code here that turns the phrase above into concrete actions return 'pending'; }); Given(/^I see the page title contains "([^"]*)"$/, (arg1) => { // Write code here that turns the phrase above into concrete actions return 'pending'; }); npm ERR! Test failed. See above for more details. ➜ webdriverio-framework git:(master) ✗
This is useful, as we can copy and paste these undefined step definitions into the relevant steps.js files.
- Firstly, let’s open up the ‘base-scenarios-steps.js’ file and add the following import to the top so we can use the Given, When and Then step definitions…
import { Given, When, Then } from 'cucumber';
In fact, feel free to add this same import to the top of all the step definition files 🙂
- Copy and paste the undefined ‘Given I navigate to the base URL’ step definition in to the ‘base-scenarios-steps.js’ file, it should look similar to below…
import { Given, When, Then } from 'cucumber'; Given(/^I am on the base page$/, () => { // Write code here that turns the phrase above into concrete actions return 'pending'; });
- Because our base page is also the search page, let’s slightly tweak our undefined ‘Given’ step definition so that we can use RegEx to either use the word ‘base’ or ‘search’ when referring to the step and being on the page, without capturing the match (see https://agileforall.com/just-enough-regular-expressions-for-cucumber/ for more info…
import { Given, When, Then } from 'cucumber'; Given(/^I am on the (?:base|search) page$/, () => { // Write code here that turns the phrase above into concrete actions return 'pending'; });
- Next, copy and paste the undefined ‘Given I see the page title contains…’ step definition in to the ‘base-scenarios-steps.js’ file, changing the Given to a Then. Also change the name of the argument from ‘arg1’ to something more suitable, like ‘expectedPageTitle’ The whole should look similar to below…
import { Given, When, Then } from 'cucumber'; Given(/^I am on the (?:base|search) page$/, () => { // Write code here that turns the phrase above into concrete actions return 'pending'; }); Then(/^I see the page title contains "([^"]*)"$/, (expectedPageTitle) => { // Write code here that turns the phrase above into concrete actions return 'pending'; });
Defining the Step Definitions
‘Given I am on the base page’ step definition
We already added the page.open() command in our ‘base.page.js’ file, which navigates and open the base URL for us. All we need to do is import the page object and call that in our step definition.
- Open up the ‘base-scenarios-steps.js’ file again and add the following import to the top of the file so we can use the base page object…
import Page from '../page-objects/base.page';
- Also add an instance of our Page class that we can use, like so…
const page = new Page();
- Edit the ‘Given’ step definition to now call the page.open() function, like below…
Given(/^I am on the (?:base|search) page$/, () => { page.open('/'); });
‘Then I see the page title contains…’ step definition
We can add a function to our base page object which returns the page title of the current page we are on.
- Open up the ‘base.page.js’ file in the ‘/page-objects’ folder and add the following function in the Page class to return the current page title…
get title() { return browser.getTitle(); }
The whole thing should look like below…
export default class Page { open(path) { browser.url(path); } get title() { return browser.getTitle(); } }
- Go back to the ‘base-scenarios-steps.js’ step definition file and define the ‘Then’ step to assert that the value returned from ‘page.title’ contains the ‘expectedPageTitle’ that we pass in from our scenario…
Then(/^I see the page title contains "([^"]*)"$/, (expectedPageTitle) => { expect(page.title).to.contain(expectedPageTitle); });
The whole thing should look like below…
import { Given, When, Then } from 'cucumber'; import Page from '../page-objects/base.page'; const page = new Page(); Given(/^I am on the (?:base|search) page$/, () => { page.open('/'); }); Then(/^I see the page title contains "([^"]*)"$/, (expectedPageTitle) => { expect(page.title).to.contain(expectedPageTitle); });
If you then run
npm test
in the terminal (or command prompt) window, your test should pass successfully 🙂
Validate the URL of a Website
Creating the Cucumber Scenario
- Open up the ‘base-scenarios.feature’ file and add the following test scenario…
Scenario: 02. Validate the Url of the website Given I am on the base page Then I see the page Url contains "https://start.duckduckgo.com/"
We have reused the ‘Given’ step, which is already defined. It is only this new ‘Then’ step which is still undefined.
Creating the Undefined Step Definition
- Open up the Terminal (or Command prompt) window and change directory (cd) in to the root of your WebDriverIO project again…
cd your/Project/Root
- Run your test suite with the following command…
npm test
The test will obviously fail, but you will get output in the console like below for the undefined step definition…
************************************************************************* ** For Feature: BaseScenarios ** Step Definitions are not specified ** Copy and Paste the following snippet(s) into your step definitions Given(/^I see the page Url contains "([^"]*)"$/, (arg1) => { // Write code here that turns the phrase above into concrete actions return 'pending'; });
- Copy the pending ‘Given’ step, and paste it in to the ‘base-scenarios-steps.js’ file, changing the ‘Given’ to a ‘Then’ and changing the name of the ‘arg1’ argument to something more meaningful, like below…
Then(/^I see the page Url contains "([^"]*)"$/, (expectedPageUrl) => { // Write code here that turns the phrase above into concrete actions return 'pending'; });
The whole thing should look similar to below…
import { Given, When, Then } from 'cucumber'; import Page from '../page-objects/base.page'; const page = new Page(); Given(/^I am on the (?:base|search) page$/, () => { page.open('/'); }); Then(/^I see the page title contains "([^"]*)"$/, (expectedPageTitle) => { expect(page.title).to.contain(expectedPageTitle); }); Then(/^I see the page Url contains "([^"]*)"$/, (expectedPageUrl) => { // Write code here that turns the phrase above into concrete actions return 'pending'; });
Defining the Step Definition
‘Then I see the page URL contains…’ step definition
We can add a function to our base page object which returns the URL of the current page we are on.
- Open up the ‘base.page.js’ file in the ‘/page-objects’ folder and add the following function in the Page class to return the current page URL…
get url() { return browser.getUrl(); }
The whole thing should look similar to below…
export default class Page { open(path) { browser.url(path); } get title() { return browser.getTitle(); } get url() { return browser.getUrl(); } }
- Open up the ‘base-scenarios-steps.js’ file again and define the undefined ‘Then’ step by asserting that the value returned from ‘page.url’ contains the ‘expectedPageUrl’ that we pass in from our test scenario…
Then(/^I see the page Url contains "([^"]*)"$/, (expectedPageUrl) => { expect(page.url).to.contain(expectedPageUrl); });
The whole file should look like below…
import { Given, When, Then } from 'cucumber'; import Page from '../page-objects/base.page'; const page = new Page(); Given(/^I am on the (?:base|search) page$/, () => { page.open('/'); }); Then(/^I see the page title contains "([^"]*)"$/, (expectedPageTitle) => { expect(page.title).to.contain(expectedPageTitle); }); Then(/^I see the page Url contains "([^"]*)"$/, (expectedPageUrl) => { expect(page.url).to.contain(expectedPageUrl); });
Validate a PageSource String on the Website
Creating the Cucumber Scenario
- Open up the ‘BaseScenarios.feature’ file and add the following test scenario…
Scenario: 03. Validate the PageSource string on the website Given I am on the base page Then I see "DuckDuckGo" in the PageSource
We have again reused the ‘Given’ step, which is already defined. It is only this new ‘Then’ step which is still undefined.
Creating the Undefined Step Definition
- Open up the Terminal (or Command prompt) window and change directory (cd) in to the root of your WebDriverIO project again (if necessary)…
cd your/Project/Root
- Run your test suite with the following command…
npm test
The test will obviously fail, but you will get output in the console like below for the undefined step definition…
************************************************************************* ** For Feature: BaseScenarios ** Step Definitions are not specified ** Copy and Paste the following snippet(s) into your step definitions Given(/^I see "([^"]*)" in the PageSource$/, (arg1) => { // Write code here that turns the phrase above into concrete actions return 'pending'; });
- Copy the pending ‘Given’ step, and paste it in to the ‘base-scenarios-steps.js’ file, changing the ‘Given’ to a ‘Then’ and changing the name of the ‘arg1’ argument to something more meaningful, like below…
Then(/^I see "([^"]*)" in the PageSource$/, (expectedPageSource) => { // Write code here that turns the phrase above into concrete actions return 'pending'; });
The whole thing should look similar to below…
import { Given, When, Then } from 'cucumber'; import Page from '../page-objects/base.page'; const page = new Page(); Given(/^I am on the (?:base|search) page$/, () => { page.open('/'); }); Then(/^I see the page title contains "([^"]*)"$/, (expectedPageTitle) => { expect(page.title).to.contain(expectedPageTitle); }); Then(/^I see the page Url contains "([^"]*)"$/, (expectedPageUrl) => { expect(page.url).to.contain(expectedPageUrl); }); Then(/^I see "([^"]*)" in the PageSource$/, (expectedPageSource) => { // Write code here that turns the phrase above into concrete actions return 'pending'; });
Defining the Step Definition
‘Then I see the page source contains…’ step definition
We can add a function to our base page object which returns the page source of the current page we are on.
- Open up the ‘base.page.js’ file in the ‘/page-objects’ folder and add the following function in the Page class to return the current page source…
get source() { return browser.getSource(); }
The whole thing should like below…
export default class BasePage extends Page { open(path) { browser.url(path); } get title() { return browser.getTitle(); } get url() { return browser.getUrl(); } get source() { return browser.getSource(); } }
- Open up the ‘base-scenarios-steps.js’ file again and define the undefined ‘Then’ step to assert that the value returned from ‘page.source’ contains the ‘expectedPageSource’ value passed in from our test scenario…
Then(/^I see "([^"]*)" in the PageSource$/, (expectedPageSource) => { expect(page.source).contains(expectedPageSource); });
The whole thing should look like below…
import { Given, When, Then } from 'cucumber'; import basPage from '../page-objects/base.page'; const page = new Page(); Given(/^I am on the (?:base|search) page$/, () => { page.open('/'); }); Then(/^I see the page title contains "([^"]*)"$/, (expectedPageTitle) => { expect(page.title).to.contain(expectedPageTitle); }); Then(/^I see the page Url contains "([^"]*)"$/, (expectedPageUrl) => { expect(page.url).to.contain(expectedPageUrl); }); Then(/^I see "([^"]*)" in the PageSource$/, (expectedPageSource) => { expect(page.source).to.contain(expectedPageSource); });
Validate Existence of Multiple Text in PageSource
Creating the Cucumber Scenario
- Open up the ‘BaseScenarios.feature’ file and add the following test scenario…
Scenario: 04. Validate existence of multiple texts in PageSource Given I am on the base page Then I see | DuckDuckGo | | search engine | | track you |
We have again reused the ‘Given’ step, which is already defined. It is only this new ‘Then’ step, which has a data table, that is still undefined.
Creating the Undefined Step Definition
- Open up the Terminal (or Command prompt) window and change directory (cd) in to the root of your WebDriverIO project again (if necessary)…
cd your/Project/Root
- Run your test suite with the following command…
npm test
The test will obviously fail, but you will get output in the console like below for the undefined step definition…
************************************************************************* ** For Feature: BaseScenarios ** Step Definitions are not specified ** Copy and Paste the following snippet(s) into your step definitions Given(/^I see$/, () => { // Write code here that turns the phrase above into concrete actions return 'pending'; });
This pending step in the console is slightly wrong and does not contain anything for our data table, so we will need to add that.
- Copy and paste the pending ‘Given’ step in to the ‘base-scenarios-steps.js’ file, changing the ‘Given’ to a Then and editing it to be able to use the data table, like below…
Then(/^I see$/, (dataTable) => { // Write code here that turns the phrase above into concrete actions return 'pending'; });
We will add more details for use of the data table when we define the step 🙂
The whole thing should look like below…import { Given, When, Then } from 'cucumber'; import Page from '../page-objects/base.page'; const page = new Page(); Given(/^I am on the (?:base|search) page$/, () => { page.open('/'); }); Then(/^I see the page title contains "([^"]*)"$/, (expectedPageTitle) => { expect(page.title).to.contain(expectedPageTitle); }); Then(/^I see the page Url contains "([^"]*)"$/, (expectedPageUrl) => { expect(page.url).to.contain(expectedPageUrl); }); Then(/^I see "([^"]*)" in the PageSource$/, (expectedPageSource) => { expect(page.source).to.contain(expectedPageSource); }); Then(/^I see$/, (dataTable) => { // Write code here that turns the phrase above into concrete actions return 'pending'; });
Defining the Step Definition
‘Then I see…’ step definition
We already have a getter function in our base page object to get the page source, so we can simply re-use this when asserting that the page source contains each row of data in our data table.
- Open up the ‘base-scenarios-steps.js’ file and edit the step definition to assert that the page source contains the passed in data from the data table, for each row of the table…
Then(/^I see$/, (dataTable) => { dataTable.rows().forEach(row => { expect(page.source).to.contain(row); }); });
The whole completed ‘base-scenarios-steps.js’ file should now look like below…
import { Given, When, Then } from 'cucumber'; import Page from '../page-objects/base.page'; const page = new Page(); Given(/^I am on the (?:base|search) page$/, () => { page.open('/'); }); Then(/^I see the page title contains "([^"]*)"$/, (expectedPageTitle) => { expect(page.title).to.contain(expectedPageTitle); }); Then(/^I see the page Url contains "([^"]*)"$/, (expectedPageUrl) => { expect(page.url).to.contain(expectedPageUrl); }); Then(/^I see "([^"]*)" in the PageSource$/, (expectedPageSource) => { expect(page.source).to.contain(expectedPageSource); }); Then(/^I see$/, (dataTable) => { dataTable.rows().forEach(row => { expect(page.source).to.contain(row); }); });
Cucumber Background Step
- If you look at the four base scenarios in your ‘BaseScenarios.feature’ file, you will see that every scenario shares the step of ‘Given I navigate to the base URL’. Because of this, we can clean up the Feature file a bit by declaring the ‘Given’ step once as a Background step, which will be applied at the beginning of every scenario in the Feature file (see https://github.com/cucumber/cucumber/wiki/Background for more information)…
@Chrome Feature: BaseScenarios These scenarios can be used in any project Background: Base Background Steps Given I am on the base page Scenario: 01. Validate the title of a website Then I see the page title contains "DuckDuckGo" Scenario: 02. Validate the Url of the website Then I see the page Url contains "https://start.duckduckgo.com" Scenario: 03. Validate the PageSource string on the website Then I see "DuckDuckGo" in the PageSource Scenario: 04. Validate existence of multiple texts in PageSource Then I see | DuckDuckGo | | search engine | | track you |
We have now successfully added our BaseScenarios. In the next part, we will actually add our first proper test of searching for something on Google and then clicking through on a search result.
If we now run our tests via
npm test
, all the tests should pass fully 😀
In the next section, we will begin to write our first proper test scenario!