testcafe-cucumber-steps
Cucumber steps (step definitions) written with TestCafe for end-to-end (e2e)
tests - see the presentation of why and how you can easily use
TestCafe with Cucumber in 5 stepsSupported versions
Table of contents
- Installation fast
- Installation detailed
- Writing tests
- Importing and running in CLI
- Importing and running with config file
- List of predefined steps
Installation fast
If you want to start writing tests as fast as possible, here are the commands you'll need to execute:npm init --yes # To create a basic package.json
npm install testcafe-cucumber-steps @cucumber/cucumber testcafe gherkin-testcafe --save-dev # To install dependencies and save them to package.json
node node_modules/testcafe-cucumber-steps/utils/prepare.js # To create basic test and Page Object files
Then just see the list of predefined steps and start writing tests (in
tests/*.feature
) and adding Page Objects
(in tests/page-model/*.js
).Run the tests with:
node_modules/.bin/gherkin-testcafe chrome,firefox
Note: all TestCafe CLI options are supported.
Installation detailed
Note: this package is lightweight and has only 3 peerDependencies - it uses:
- cucumber to parse step definitions
- testcafe to execute steps
- gherkin-testcafe to connect TestCafe with Cucumber
First of all you will need to create
package.json
if you do not have one in
the root folder of your project:
npm init --yes
To install the testcafe-cucumber-steps package and its peerDependencies and to save it to your
package.json
just run:npm install testcafe-cucumber-steps @cucumber/cucumber testcafe gherkin-testcafe --save-dev # In case if you want to use Cucumber 7 (the recent one)
OR
npm install testcafe-cucumber-steps cucumber@6.0.5 testcafe gherkin-testcafe@2.5.1 --save-dev # In case if you want to use Cucumber 6
OR
npm install testcafe-cucumber-steps cucumber@5.1.0 testcafe gherkin-testcafe@2.5.1 --save-dev # In case if you want to use Cucumber 5
If you also want to have pre-created config (
.testcaferc.json
) and example
test files (tests/test-example.feature
, tests/page-model/test-page-example.js
) -
run additionally:
node node_modules/testcafe-cucumber-steps/utils/prepare.js
Writing tests
To give a short example of how you can write the tests - here istest-main-page.feature
feature file:
# tests/test-main-page.feature
Feature: My portal main page tests
As a user of My portal
I should be able to use main page
to log in
Scenario: Open the main page, page title should be present
Given user goes to URL "http://myportal.test/login.html"
Then the title should be "Test1 main page"
Scenario: Products link should lead to Products page
Given user goes to pageMain from main-page
When user clicks linkProducts from main-page
Then URL should contain "/products"
And the title should contain "Test1 Products"
Scenario: Log in, link with username and status should be present
Given user goes to pageMain from main-page
When user types "mytestuser" in inputLogin from main-page
And user types "mytestpassword" in inputPassword from main-page
And user clicks buttonLogin from main-page
Then linkUsernameLoggedIn from main-page should be present
And the Page Object file for this tests will look like this:
// tests/page-model/main-page.js
let mainPage = {
pageMain: 'http://myportal.test/login.html',
linkProducts: '.link-products',
inputLogin: '#login',
inputPassword: '#pass',
buttonLogin: '.btn-login',
linkUsernameLoggedIn: 'a.username-authorized'
};
module.exports = mainPage;
If you want the Page Objects to look even shorter - you can write the same tests like this:
# tests/test-main-page.feature
Feature: My portal main page tests
As a user of My portal
I should be able to use main page
to log in
Scenario: Open the main page, page title should be present
Given user goes to URL "http://myportal.test/login.html"
Then the title should be "Test1 main page"
Scenario: Products link should lead to Products page
Given user goes to "main-page"."pageMain"
When user clicks "main-page"."linkProducts"
Then URL should contain "/products"
And the title should contain "Test1 Products"
Scenario: Log in, link with username and status should be present
Given user goes to "main-page"."pageMain"
When user types "mytestuser" in "main-page"."inputLogin"
And user types "mytestpassword" in "main-page"."inputPassword"
And user clicks "main-page"."buttonLogin"
Then "main-page"."linkUsernameLoggedIn" should be present
See more examples of how to use predefined steps in
test1-user.feature
and
test2-user.feature
.If you want to get access to Page Objects in your custom Cucumber steps - you can just require them inside any step definitions file like this:
const pageObjects = require('testcafe-cucumber-steps/utils/get-page-objects.js');
Importing and running in CLI
To get access to all Cucumber steps defined in this package just specify the path to this package when launching tests:node_modules/.bin/gherkin-testcafe chrome,firefox node_modules/testcafe-cucumber-steps/index.js tests/**/*.js tests/**/*.feature
If you store your Page Objects not in
tests/page-model
folder, then
PO_FOLDER_PATH
environment variable has to be specified to show the path to
your Page Objects folder:
PO_FOLDER_PATH='tests/my-custom-page-objects' node_modules/.bin/gherkin-testcafe chrome,firefox node_modules/testcafe-cucumber-steps/index.js tests/**/*.js tests/**/*.feature
Note: you can specify multiple Page Object folders by separating them with commas:
PO_FOLDER_PATH='main/my-custom1,login/my-custom2,auth,create/my-custom3'
Also you can just add
test-e2e
command to scripts
in package.json
:
"test-e2e": "PO_FOLDER_PATH='tests/my-custom-page-objects' node_modules/.bin/gherkin-testcafe 'chrome:headless' node_modules/testcafe-cucumber-steps/index.js tests/**/*.js tests/**/*.feature"
and then launch tests with:
npm run test-e2e
Note: all TestCafe CLI options are supported.
Additionally, you can specify:
- tags to run:
```bash
node_modules/.bin/gherkin-testcafe chrome,firefox node_modules/testcafe-cucumber-steps/index.js tests/**/*.js tests/**/*.feature --tags @fast
```
When using more than one tag, the list needs to be comma separated:
```bash
node_modules/.bin/gherkin-testcafe chrome node_modules/testcafe-cucumber-steps/index.js tests/**/*.js tests/**/*.feature --tags @fast,@long
```
Negation of a tag (via `~`) is also possible (to run all scenarios that have
tag `fast`, but not `long`):
```bash
node_modules/.bin/gherkin-testcafe chrome node_modules/testcafe-cucumber-steps/index.js tests/**/*.js tests/**/*.feature --tags @fast,~@long
```
- custom parameter types:
```bash
node_modules/.bin/gherkin-testcafe chrome node_modules/testcafe-cucumber-steps/index.js tests/**/*.js tests/**/*.feature --param-type-registry-file ./a-file-that-exports-a-parameter-type-registry.js
```
> Note: see Cucumber Expressions in
> [gherkin-testcafe](https://github.com/kiwigrid/gherkin-testcafe#cucumber-expressions)
> and Custom Parameter types in
> [cucumber.io](https://cucumber.io/docs/cucumber/cucumber-expressions/#custom-parameter-types).
Importing and running with config file
To make life easier and not to specify all options in CLI command, a.testcaferc.json
configuration file can be created in the root directory of
your project to store all settings (pathes to all step definitions and tests
should be specified inside the array in src
):
{
"browsers": "chrome",
"src": ["node_modules/testcafe-cucumber-steps/index.js", "tests/**/*.js", "tests/**/*.feature"],
"screenshots": {
"path": "tests/screenshots/",
"takeOnFails": true,
"pathPattern": "${DATE}_${TIME}/test-${TEST_INDEX}/${USERAGENT}/${FILE_INDEX}.png"
},
"quarantineMode": false,
"stopOnFirstFail": true,
"skipJsErrors": true,
"skipUncaughtErrors": true,
"concurrency": 1,
"selectorTimeout": 3000,
"assertionTimeout": 1000,
"pageLoadTimeout": 1000,
"disablePageCaching": true
}
and then launch tests with:
node_modules/.bin/gherkin-testcafe
or if you use custom Page Objects folder:
PO_FOLDER_PATH='tests/my-custom-page-objects' node_modules/.bin/gherkin-testcafe
All options that are specified in CLI command will override settings from
.testcaferc.json
.Note: for all possible settings see: example of .testcaferc.json
List of predefined steps
Given steps
I/user go(es) to URL "..."
- open a site (by its URL provided in "" as a
"https://github.com/Marketionist"
) in the current
browser window/tab.I/user go(es) to "..."."..."
- open a site (by its URL provided in
I/user go(es) to ... from ...
- open a site (by its URL provided in
I/user set(s) cookie "..."
- set cookie on the current site (cookie
"my_test_cookie1=11"
).I/user set(s) cookie "..."."..."
- set cookie on the current site (cookie
I/user set(s) cookie ... from ...
- set cookie on the current site (cookie
I/user send(s) "..." request to "..." with body "..."
- send request
POST
) to URL
(provided in "" as a string - for example: "http://httpbin.org/post"
) with
body (provided in "" as JSON - for example: "{ \"test1\": 1, \"test2\": 2 }"
).- Note: GET request will be sent with default header
'Content-Type': 'text/html'
, - all other requests will be sent with default header
'Content-Type': 'application/json'
.I/user send(s) "..." request to "..." with body "..."."..."
- send request
POST
) to URL
(provided in "" as a string - for example: "http://httpbin.org/post"
) with
body (provided in "page"."object").I/user send(s) "..." request to "..."."..." with body "..."."..."
- send
POST
) to URL
(provided in "page"."object") with body (provided in "page"."object").I/user send(s) "..." request to ... from ... with body ... from ...
- send
POST
) to URL
(provided in object from page) with body (provided in object from
page).I/user send(s) "..." request to "..." with headers "..." and body "..."
-
POST
)
to URL (provided in "" as a string - for example: "http://httpbin.org/post"
)
with headers (provided in "" as JSON - for example:
"{ \"Content-Type\": \"application/json\", \"Authorization\": \"Bearer aBcD1234\" }"
) and body (provided in "" as JSON - for example:
"{ \"test1\": 1, \"test2\": 2 }"
).I/user send(s) "..." request to "..." with headers "..."."..." and body "..."."..."
-
POST
) to URL
(provided in "" as a string - for example: "http://httpbin.org/post"
) with
headers (provided in "page"."object") and body (provided in
"page"."object").I/user send(s) "..." request to "..."."..." with headers "..."."..." and body "..."."..."
-
POST
)
to URL (provided in "page"."object") with headers (provided in
"page"."object") and body (provided in "page"."object").I/user send(s) "..." request to ... from ... with headers ... from ... and body ... from ...
-
POST
) to URL
(provided in object from page) with headers (provided in object from
page) and body (provided in object from page).When steps
- `I/user log(s) in with l: "..." in "..."."..." and p: "..." in
- `I/user log(s) in with l: "..." in ... from ... and p: "..." in ...
- `I/user log(s) in with l: "..."."..." in "..."."..." and p: "..."."..." in
- `I/user log(s) in with l: ... from ... in ... from ... and p: ... from ... in
I/user reload(s) the page
- reload current page.I/user click(s) "..."."..."
- click on any element (provided in
I/user click(s) ... from ...
- click on any element (provided in object
I/user right click(s) "..."."..."
- right click on any element (provided in
I/user right click(s) ... from ...
- right click on any element (provided in
I/user wait(s) for ... ms
- wait for provided amount of time (in
I/user wait(s) and click(s) "..."."..."
- wait for 300 ms and then click
I/user wait(s) and click(s) ... from ...
- wait for 300 ms and then click on
I/user wait(s) up to ... ms for "..."."..." to appear
- wait up to
I/user wait(s) up to ... ms for ... from ... to appear
- wait up to provided
I/user click(s) "..."."..." if present
- click on any element (provided in
I/user click(s) ... from ... if present
- click on any element (provided in
I/user double click(s) "..."."..."
- double click on any element (provided
I/user double click(s) ... from ...
- double click on any element (provided
I/user type(s) "..." in "..."."..."
- type any text (provided in "" as a
I/user type(s) "..." in ... from ...
- type any text (provided in "" as a
I/user type(s) "..."."..." in "..."."..."
- type any text (provided in
I/user type(s) ... from ... in ... from ...
- type any text (provided in
I/user clear(s) "..."."..." and type(s) "..."
- clear the input field
I/user clear(s) ... from ... and type(s) "..."
- clear the input field
I/user clear(s) "..."."..." and type(s) "..."."..."
- clear the input field (provided in "page1"."object1" as CSS or XPath selector) and type any text
I/user clear(s) ... from ... and type(s) ... from ...
- clear the input
I/user select(s) "..." in "..."."..."
- select any option (provided in ""
I/user select(s) "..." in ... from ...
- select any option (provided in ""
I/user select(s) "..."."..." in "..."."..."
- select any option (provided in
I/user select(s) ... from ... in ... from ...
- select any option
I/user move(s) to "..."."..."
- move the mouse pointer over any element
I/user move(s) to ... from ...
- move the mouse pointer over any element
I/user move(s) to "..."."..." with an offset of x: ...px, y: ...px
- move
I/user move(s) to ... from ... with an offset of x: ...px, y: ...px
- move
I/user switch(es) to "..."."..." frame
- switch the context to iframe
I/user switch(es) to ... frame from ...
- switch the context to iframe
I/user wait(s) up to ... ms and switch(es) to "..."."..." frame
- wait up
I/user wait(s) up to ... ms and switch(es) to ... frame from ...
- wait up
I/user switch(es) to main frame
- switch the context back to default
I/user set(s) "..." file path in "..."."..."
- set a file path (provided
I/user set(s) "..." file path in ... from ...
- set a file path (provided in
I/user set(s) "..."."..." file path in "..."."..."
- set a file path
I/user set(s) ... from ... file path in ... from ...
- set a file path
I/user execute(s) "..."."..." function
- execute script (JavaScript
I/user execute(s) ... function from ...
- execute script (JavaScript
I/user drag(s)-and-drop(s) "..."."..." to "..."."..."
- drag-and-drop
I/user drag(s)-and-drop(s) ... from ... to ... from ...
- drag-and-drop
I/user accept(s) further browser alerts
- accept (OK) all further browser
I/user dismiss(es) further browser alerts
- dismiss (Cancel) all further
I/user open(s) "..." in new browser window
- open a site (by its URL
"https://github.com/Marketionist"
)
in the new browser window/tab.I/user open(s) "..."."..." in new browser window
- open a site (by its URL
I/user open(s) ... from ... in new browser window
- open a site (by its URL
I/user close(s) current browser window
- close current browser window/tab.I/user press(es) "..."
- press the specified keyboard keys (provided in ""
I/user set(s) PAGE_URL environment variable
- take current page URL and
I/user go(es) to PAGE_URL
- open a site from PAGEURL environment
I/user debug(s)
- set a breakpoint to stop the tests execution and start
Then steps
the title should be "..."
- verify that title of the current browser
the title should contain "..."
- verify that title of the current browser
"..."."..." should be present
- verify that element (provided in
... from ... should be present
- verify that element (provided in
... "..."."..." should be present
- verify that the number of elements
... ... from ... should be present
- verify that the number of elements
"..."."..." should not be present
- verify that element (provided in
... from ... should not be present
- verify that element (provided in
"..."."..." text should be "..."
- verify that text of the element
... from ... text should be "..."
- verify that text of the element
"..."."..." text should be "..."."..."
- verify that text of the element
... from ... text should be ... from ...
- verify that text of the
"..."."..." text should contain "..."
- verify that text of the element
... from ... text should contain "..."
- verify that text of the element
"..."."..." text should contain "..."."..."
- verify that text of the
... from ... text should contain ... from ...
- verify that text
URL should be "..."
- verify that URL of the current page equals to the
URL should be "..."."..."
- verify that URL of the current page equals to
URL should be ... from ...
- verify that URL of the current page equals to
URL should contain "..."
- verify that URL of the current page contains
URL should contain "..."."..."
- verify that URL of the current page
URL should contain ... from ...
- verify that URL of the current page
"..."."..." attribute "..." should contain "..."
- verify that the
... from ... attribute "..." should contain "..."
- verify that the
Bonus feature: use XPath selectors in TestCafe
As you know TestCafe does not support XPath selectors out of the box. But now you can use them in TestCafe Cucumber steps - just write XPath selector in a Page Object file the same way as you do with CSS selectors - see the example intest1-page.js
.
It can also be used in your custom Cucumber steps - for example:
const SelectorXPath = require('testcafe-cucumber-steps/utils/selector-xpath.js');
const buttonStartTest = SelectorXPath('//*[ancestor::*[@class="test-panel"] and contains(text(), "Start test")]');