DEPRECATED: No longer maintained. For details, see: #22
⚠️ CAUTION: These docs are for latest unstable development version. For for the latest stable release, see the 2.x branch docs.
Run Gherkin scenarios in Cypress without a single line of code.
To run a Gherkin scenario like this:
Feature: Login
===
Scenario: Successful login
---
Given I navigate to "/login"
And I set "email input" to "name@example.com"
And I set "password input" to "p4ssw0rd"
When I click "login button"
Then I should be on "/dashboard"
Just tag the appropriate HTML elements:
<input … test-element="email input" />
<input … test-element="password input" />
<button … test-element="login button">Login</button>
That's it. No other coding required.
Requires:
- Node.js 8.0+
cypress
cypress-cucumber-preprocessor
npm install --save-dev cypress cypress-cucumber-preprocessor cypress-scenario-runner
$(npm bin)/install-cypress-scenario-runner
The installer will create or modify a handful of files. You should review and commit those changes.
Test scenarios are written in Gherkin syntax:
Feature: Login
===
Scenario: Successful login
---
Given I navigate to "login"
And I set "email input" to "name@example.com"
And I set "password input" to "abc123"
When I click "login button"
Then I should be on "home"
Each line in the scenario is called a step. cypress-scenario-runner
works by using a predefined set of reusable step templates, but you can also add your own (see Customization):
Step | Description | Examples |
---|---|---|
I navigate to {route} |
Navigates the browser to a preconfigured route (see Mapping routes) or an absolute URL | navigation.feature |
I click {element} |
Clicks the first element with a matching tag (see Tagging elements) | pointer-events.feature |
I set {element} to {string} |
Sets the first matching input to the given value (see Working with inputs) | input/ |
I set: |
Same as the step above, but for setting multiple inputs using an inline data table (see Using data tables) | input/ |
I wait for {element} to disappear |
Waits for all matching elements to be invisible (ie. is(':visible') returns false), checking every 500ms |
visibility.feature |
I wait {float} seconds |
Pauses test execution for the specified number of seconds; fractional seconds allowed | miscellaneous.feature |
I pause |
Pauses test execution until manually resumed (see cy.pause() ) |
And I pause |
I debug |
Sets a debugger breakpoint (see cy.debug() ) |
And I debug |
Step | Description | Examples |
---|---|---|
I should be on {route} |
Asserts that the current page URL matches the specified route (see Mapping routes), an absolute URL, or a regular expression | navigation.feature |
I should not be on {route} |
Asserts the inverse of the step above | navigation.feature |
{element} should be visible |
Asserts that the first matching element is visible, using .should('be.visible') |
visibility.feature |
{element} should not be visible |
Asserts that the first matching element is not visible, using .should('not.be.visible') |
visibility.feature |
{element} should have {int} occurrences |
Asserts that the number of matching elements (visible and invisible) is exactly some value | counting.feature |
{element} should have at least {int} occurrences |
Asserts that the number of matching elements (visible and invisible) is greater than or equal to some value | counting.feature |
{element} should have at most {int} occurrences |
Asserts that the number of matching elements (visible and invisible) is less than or equal to some value | counting.feature |
{element} should be set to {string} |
Asserts that the value of an input element (<input> , <select> , <textarea> ) matches the given string; for inputs that accept multiple values (eg. checkboxes, multi-selects), the value used for comparison is the string value of each input, concatenated with , (eg. one, two, three ) |
input/ |
{element} text should be {string} |
Asserts that a non-input element's text content matches the given string, ignoring case and surrounding whitespace | text-content.feature |
elements text should be: |
Same as the step above, but for asserting multiple elements using an inline data table (see Using data tables) | text-content.feature |
{element} text should not be {string} |
Asserts the inverse of the step above | text-content.feature |
elements text should not be: |
Same as the step above, but for asserting multiple elements using an inline data table (see Using data tables) | text-content.feature |
{element} text should contain {string} |
Asserts that a non-input element's text content contains the given string, ignoring case and surrounding whitespace | text-content.feature |
elements text should contain: |
Same as the step above, but for asserting multiple elements using an inline data table (see Using data tables) | text-content.feature |
{element} text should not contain {string} |
Asserts the inverse of the step above | text-content.feature |
elements text should not contain: |
Same as the step above, but for asserting multiple elements using an inline data table (see Using data tables) | text-content.feature |
Text in {brackets}
above are parameters whose values must be (double) quoted in the scenario. For example, this step template:
I set {element} to {string}
should be written like this in a test scenario:
And I set "email input" to "name@example.com"
The full Gherkin specification is supported along with additional enhancements by cypress-cucumber-preprocessor
. For instance, you can use scenario templates/outlines, data tables, and tags in your scenarios.
See the cypress/integration/
directory for more examples.
HTML attributes are used to map {element}
step parameters to their corresponding HTML elements. test-element
attributes is used by default, but this is configurable.
<!-- login.html -->
<input name="email" test-element="email input" />
<input name="password" test-element="password input" />
<button type="submit" test-element="login button">Login</button>
Many Cypress commands accept an optional options
object that can be used to customize how the command is executed (eg. cy.type(text, options)
). These options can be set on a per-element basis via a test-options
attribute. Example:
<input
name="search"
type="text"
test-element="search input"
+ test-options="{ force: true, log: true }"
>
Routes need to be provided for navigation steps like these to work:
Given I navigate to "login"
A map of all route names to URIs should be provided to addSteps()
in the cypress/support/step_definitions/index.js
file created during installation. Route URIs can be absolute URLs, relative to the web root, or regular expressions.
const { addSteps } = require('cypress-scenario-runner')
addSteps({
+ routes: {
+ login: '/login',
+ 'a specific product': '/products/acme-widget',
+ 'any product': '\/products\/.*'
+ }
})
Like other HTML elements, input elements are selectable by their test-element
attribute (or whichever attribute you've configured).
Nearly any type of input can be set with this step:
I set {element} to {string}
A <select>
option can be selected by its value or label. For example, given:
<select name="fav_color" test-element="favorite color">
<option value="#f00">Red</option>
<option value="#0f0">Green</option>
<option value="#00f">Blue</option>
</select>
These steps are equivalent:
I set "favorite color" to "#0f0"
I set "favorite color" to "Green"
For more example usage, see input/select.feature.
For multi-selects (ie. <select multiple>
), multiple options can be selected by stringing together their labels or values with commas. For example, given:
<select multiple name="select" test-element="select input">
<option value="Value A">Label A</option>
<option value="Value B">Label B</option>
<option value="Value C">Label C</option>
</select>
The second and third <option>
s can be selected by their values or by their labels:
# By values:
I set "select input" to "Value B, Value C"
# By labels:
I set "select input" to "Label B, Label C"
For more example usage, see input/select.feature.
A radio option can set by its value or test-value
label. For example:
<label>
<input type="radio" name="fav_color" value="#f00" test-element="favorite color" test-value="Red" />
Red
</label>
<label>
<input type="radio" name="fav_color" value="#0f0" test-element="favorite color" test-value="Green" />
Green
</label>
<label>
<input type="radio" name="fav_color" value="#00f" test-element="favorite color" test-value="Blue" />
Blue
</label>
These steps are equivalent:
I set "favorite color" to "#0f0"
I set "favorite color" to "Green"
When using UI frameworks, it may not be practical to add test-element
and other attributes directly to the input elements themselves. In such cases, those attributes can be added to an ancestor element that wraps the input. For example:
<my-custom-input test-element="some input"></my-custom-input>
This is convenient when checkbox or radio inputs are wrapped with labels:
<label test-element="color options">
<input type="checkbox" name="colors" value="red" />
</label>
<label test-element="color options">
<input type="checkbox" name="colors" value="green" />
</label>
<label test-element="color options">
<input type="checkbox" name="colors" value="blue" />
</label>
Checkboxes can be checked by their value or by their test-value
attributes (or whichever attribute you've configured for input values). For example, given:
<input type="checkbox" name="color" value="f00" test-element="colors" test-value="red" />
<input type="checkbox" name="color" value="0f0" test-element="colors" test-value="green" />
<input type="checkbox" name="color" value="00f" test-element="colors" test-value="blue" />
The second checkbox can be set by its test-value
attribute green
or by its value 0f0
:
# By test-value:
I set "colors" to "green"
# By value:
I set "colors" to "0f0"
Multiple checkboxes can be checked individually by test-value
or by value:
# By test-value:
I set "colors" to "green"
I set "colors" to "blue"
# By value:
I set "colors" to "0f0"
I set "colors" to "00f"
Multiple checkboxes can also be checked together by stringing together their test-value
or value
attributes with commas:
# By test-value:
I set "colors" to "green, blue"
# By value:
I set "colors" to "0f0, 00f"
A single-option checkbox can be checked or unchecked by setting its value to the string checked
or unchecked
. For example, given:
<input type="checkbox" name="remember_me" value="1" test-element="remember me" />
I set "remember me" to "checked"
NOTE: Setting one or more checkboxes does not clear the other checkboxes.
For more example usage, see input/checkbox.feature.
Repetitive steps can be written in tabular form with inline data tables.
For example, this scenario:
I set "first name" to "Jane"
I set "last name" to "Doe"
I set "email" to "jdoe@example.com"
I set "address" to "123 Somewhere St."
I set "city" to "Anywhere"
I set "zip" to "38274"
Can be written as a data table with I set:
:
I set:
| element | value |
| first name | Jane |
| last name | Doe |
| email | jdoe@example.com |
| address | 123 Somewhere St. |
| city | Anywhere |
| zip | 38274 |
The first column of the table are column headers. It doesn't matter how you name them—they're meant to be purely informational and are ignored.
The list steps that use data tables are:
I set:
elements text should be:
elements text should not be:
elements text should contain:
elements text should not contain:
For more example usage, see input/tables.feature and the official Gherkin spec.
Repetitive scenarios can be parameterized with a scenario outline (aka scenario template):
Scenario Template: Multiple valid forms can be submitted
---
Given I navigate to "form"
And I set "first name" to "<first name>"
And I set "last name" to "<last name>"
And I set "email" to "<email>"
When I click "submit button"
Then I "form submitted message" should be visible
Examples:
| first name | last name | email |
| Peter | Gibbons | pgibbons@initech.com |
| Samir | Nagheenanajar | samir@initrode.com |
| Mike | Bolton | pcl04dl3tt3r@aol.com |
The scenario is run once for each row in the table. Parameters denoted by < >
are replaced with the associated column value.
For more details, see the official Gherkin spec.
Scenario files can be run directly with Cypress:
$(npm bin)/cypress run [files]
or by using the Cypress UI:
$(npm bin)/cypress open
TBD
- Options
- Custom steps
- API