Boilerplate project to run WebdriverIO (alpha v8) tests with Cucumber and brings true BDD to JavaScript. Instead of writing complicated test code that only developers can understand, Cucumber maps an ordinary language to code and allows to start with the test process in the early stages of your product development.
Note: If you are still using an older WebdriverIO version, check out the v7
branch.
Although this project works fine with NPM we recommend to use Yarn (>= 1.0.0) instead, due to its speed & solid dependency locking mechanism. To keep things simple we use yarn in this guide, but feel free to replace this with NPM if that is what you are using.
Also this project doesn't cover setting up a proper test environment. You need to download specific browser driver yourself and run the prior starting tests or use a cloud provider like SauceLabs.
Choose one of the following options:
Download the latest stable release here or clone the git repo — git clone https://github.com/webdriverio/cucumber-boilerplate.git
Then:
/integrationtests
(note the hidden files!)Clean the project (Optional):
yarn run clean
/.git
, /.github
, /demo-app
& /test
-- Remove the files .travis.yml
, jest.json
& wdio.BUILD.conf.js
-- Remove all the demo features from the /src/features
directoryyarn install
)Now you are ready to write your own features.
Tests are written in Gherkin syntax
that means that you write down what's supposed to happen in a real language. All test files are located in
./src/features/*
and have the file ending .feature
. You will already find some test files in that
directory. They should demonstrate, how tests could look like. Just create a new file and write your first
test.
myFirstTest.feature
Feature:
In order to keep my product stable
As a developer or product manager
I want to make sure that everything works as expected
Scenario: Check title of website after search
Given I open the url "http://google.com"
When I set "WebdriverIO" to the inputfield "#lst-ib"
And I press "Enter"
Then I expect that the title is "WebdriverIO - Google Search"
Scenario: Another test
Given ...
This test opens the browser and navigates them to google.com to check if the title contains the search query after doing a search. As you can see, it is pretty simple and understandable for everyone.
Start the local web server:
$ yarn run test
To run your tests just call the WDIO runner:
$ yarn run wdio
please note The WDIO runner uses the configuration file wdio.conf.js
by default.
To configure your tests, checkout the wdio.conf.js
file in your test directory. It comes with a bunch of documented options you can choose from.
You can setup multiple configs for specific environments. Let's say you want to have a different baseUrl
for
your local and pre-deploy tests. Use the wdio.conf.js
to set all general configs (like mochaOpts) that don't change.
They act as default values. For each different environment you can create a new config with the following name
scheme:
wdio.<ENVIRONMENT>.conf.js
Now you can create a specific config for your pre-deploy tests:
wdio.STAGING.conf.js
var config = require('./wdio.conf.js').config;
config.baseUrl = 'http://staging.example.com'
exports.config = config;
Your environment-specific config file will get merged into the default config file and overwrites the values you set. To run a test in a specific environment just add the desired configuration file as the first parameter:
$ yarn run wdio wdio.STAGING.conf.js
Sometimes it's useful to only execute a single feature file, to do so use the following command:
$ npx wdio wdio.conf.js --spec ./test/features/select.feature
If you want to run only specific tests you can mark your features with tags. These tags will be placed before each feature like so:
@Tag
Feature: ...
To run only the tests with specific tag(s) use the --cucumberOpts.tagExpression=
parameter like so:
$ npx wdio wdio.conf.js --cucumberOpts.tagExpression='@Tag or @AnotherTag'
For more tag options please see the Cucumber.js documentation
If you have failing or unimplemented tests you can mark them as "Pending" so they will get skipped.
// skip whole feature file
@Pending
Feature: ...
// only skip a single scenario
@Pending
Scenario: ...
The predefined snippets allow you to do a lot of common things but you might need extra snippets which
are better aligned with your aims. To do so you will find all step definitions in ./src/steps
. They
are separated in given
, when
and then
.
You define your snippet using regular expressions. This is pretty powerful as it allows you to create complex
sentences with multiple options. Everything that's within "([^"]*)?"
gets captured and appended to the
callback. The last argument is always a callback function that you need to call when your step is done.
You can access the browser and your WebdriverIO instance with browser
.
To assert values this boilerplate project uses WebdriverIOs embedded assertion library called expect-webdriverio.
You can add additional descriptive comments in your feature files.
###
This is a
block comment
###
Feature: As a bystander
I can watch bottles falling from a wall
So that I can be mildly amused
# This is a single line comment
Scenario: check if username is present
Given I login as "roboter" with password "test123"
Then the username "roboter" should be present in the header
Check out all predefined snippets. You can see how they get used in sampleSnippets.feature
.
I open the (url|site) "([^"]*)?"
the element "([^"]*)?" is( not)* displayed
the element "([^"]*)?" is( not)* enabled
the element "([^"]*)?" is( not)* selected
the checkbox "([^"]*)?" is( not)* checked
there is (an|no) element "([^"]*)?" on the page
the title is( not)* "([^"]*)?"
the element "([^"]*)?" contains( not)* the same text as element "([^"]*)?"
the (button|element) "([^"]*)?"( not)* contains the text "([^"]*)?"
the (button|element) "([^"]*)?"( not)* contains any text
the (button|element) "([^"]*)?" is( not)* empty
the page url is( not)* "([^"]*)?"
the( css)* attribute "([^"]*)?" from element "([^"]*)?" is( not)* "([^"]*)?"
the cookie "([^"]*)?" contains( not)* the value "([^"]*)?"
the cookie "([^"]*)?" does( not)* exist
the element "([^"]*)?" is( not)* ([\d]+)px (broad|tall)
the element "([^"]*)?" is( not)* positioned at ([\d]+)px on the (x|y) axis
I have a screen that is ([\d]+) by ([\d]+) pixels
I have closed all but the first (window|tab)
a (alertbox|confirmbox|prompt) is( not)* opened
I expect that the title is( not)* "([^"]*)?"
I expect that element "([^"]*)?" does( not)* appear exactly "([^"]*)?" times
I expect that element "([^"]*)?" is( not)* visible
I expect that element "([^"]*)?" becomes( not)* visible
I expect that element "([^"]*)?" is( not)* within the viewport
I expect that element "([^"]*)?" does( not)* exist
I expect that element "([^"]*)?"( not)* contains the same text as element "([^"]*)?"
I expect that (button|element) "([^"]*)?"( not)* contains the text "([^"]*)?"
I expect that (button|element) "([^"]*)?"( not)* contains any text
I expect that (button|elementelement) "([^"]*)?" is( not)* empty
I expect that the url is( not)* "([^"]*)?"
I expect that the path is( not)* "([^"]*)?"
I expect the url to( not)* contain "([^"]*)?"
I expect that the( css)* attribute "([^"]*)?" from element "([^"]*)?" is( not)* "([^"]*)?"
I expect that checkbox "([^"]*)?" is( not)* checked
I expect that element "([^"]*)?" is( not)* selected
I expect that element "([^"]*)?" is( not)* enabled
I expect that cookie "([^"]*)?"( not)* contains "([^"]*)?"
I expect that cookie "([^"]*)?"( not)* exists
I expect that element "([^"]*)?" is( not)* ([\d]+)px (broad|tall)
I expect that element "([^"]*)?" is( not)* positioned at ([\d]+)px on the (x|y) axis
I expect that element "([^"]*)?" (has|does not have) the class "([^"]*)?"
I expect a new (window|tab) has( not)* been opened
I expect the url "([^"]*)?" is opened in a new (tab|window)
I expect that element "([^"]*)?" is( not)* focused
I wait on element "([^"]*)?"( for (\d+)ms)*( to( not)* (be checked|be enabled|be selected|be visible|contain a text|contain a value|exist))*
I expect that a (alertbox|confirmbox|prompt) is( not)* opened
I expect that a (alertbox|confirmbox|prompt)( not)* contains the text "$text"
I (click|doubleclick) on the (link|button|element) "([^"]*)?"
I (add|set) "([^"]*)?" to the inputfield "([^"]*)?"
I clear the inputfield "([^"]*)?"
I drag element "([^"]*)?" to element "([^"]*)?"
I submit the form "([^"]*)?"
I pause for (\d+)ms
I set a cookie "([^"]*)?" with the content "([^"]*)?"
I delete the cookie "([^"]*)?"
I press "([^"]*)?"
I (accept|dismiss) the (alertbox|confirmbox|prompt)
I enter "([^"]*)?" into the prompt
I scroll to element "([^"]*)?"
I close the last opened (window|tab)
I focus the last opened (window|tab)
I select the (\d+)(st|nd|rd|th) option for element "([^"]*)?"
I select the option with the (name|value|text) "([^"]*)?" for element "([^"]*)?"
I move to element "([^"]*)?"( with an offset of (\d+),(\d+))
I switch to the iframe "([^"]*)?"