Run Gherkin scenarios with Cypress without a single line of code.


Keywords
cypress, cypress.io, gherkin, scenario, bdd, test, cucumber
License
MIT
Install
npm install cypress-scenario-runner@2.1.2

Documentation

Cypress Scenario Runner npm version Build Status

Run Gherkin scenarios in Cypress without a single line of code.

Cypress Scenario Runner enables you to run Gherkin scenarios like this one:

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"

…without needing to write any Cypress glue code like cy.visit(), cy.click(), etc. All you need to do is tag HTML elements:

<input  data-test="email input" />
<input  data-test="password input" />
<button  data-test="login button">Login</button>

and map route names to URIs:

{
  "login": "/login"
}

Table of contents

Installation

Requires:

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.

Usage

Writing test scenarios

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):

Actions

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

Assertions

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.

Tagging elements

HTML attributes are used to map {element} step parameters to their corresponding HTML elements. data-test attributes is used by default, but this is configurable.

<!-- login.html -->
<input name="email" data-test="email input" />
<input name="password" data-test="password input" />
<button type="submit" data-test="login button">Login</button>

Element options

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 data-options attribute. Example:

  <input
    name="search"
    type="text"
    data-test="search input"
+   data-options="{ force: true, log: true }"
  >

Mapping routes

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\/.*'
+ }
})

Working with inputs

Like other HTML elements, input elements are selectable by their data-test attribute (or whichever attribute you've configured).

Supported types

The step I set {element} to {string} can be used to set the value of nearly any type of input:

  • <input type="checkbox">
  • <input type="color">
  • <input type="date">
  • <input type="datetime-local">
  • <input type="email">
  • <input type="file">
  • <input type="hidden">
  • <input type="image">
  • <input type="month">
  • <input type="number">
  • <input type="password">
  • <input type="radio">
  • <input type="range">
  • <input type="search">
  • <input type="tel">
  • <input type="text">
  • <input type="time">
  • <input type="url">
  • <input type="week">
  • <select></select>
  • <textarea></textarea>

Input value and options

TBD

Wrapped inputs

When using UI frameworks, it may not be practical to add data-test 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 data-test="some input"></my-custom-input>

This is convenient when checkboxes are wrapped with their labels:

<label data-test="color options">
  <input type="checkbox" name="colors" value="red" />
  <input type="checkbox" name="colors" value="green" />
  <input type="checkbox" name="colors" value="blue" />
</label>

Selects

<select> options can be selected by their value or by their label. For example, given:

<select name="select" data-test="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 <option> can be selected by its value Value B or by its label Label B:

# By value:
I set "select input" to "Value B"

# By label:
I set "select input" to "Label B"

For more example usage, see input/select.feature.

Multi-selects

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" data-test="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.

Checkboxes

Checkboxes can be checked by their value or by their data-value attributes (or whichever attribute you've configured for input values). For example, given:

<input type="checkbox" name="color" value="f00" data-test="colors" data-value="red" />
<input type="checkbox" name="color" value="0f0" data-test="colors" data-value="green" />
<input type="checkbox" name="color" value="00f" data-test="colors" data-value="blue" />

The second checkbox can be set by its data-value attribute green or by its value 0f0:

# By data-value:
I set "colors" to "green"

# By value:
I set "colors" to "0f0"

Multiple checkboxes can be checked individually by data-value or by value:

# By data-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 data-value or value attributes with commas:

# By data-value:
I set "colors" to "green, blue"

# By value:
I set "colors" to "0f0, 00f"

NOTE: Setting one or more checkboxes does not clear the other checkboxes.

For more example usage, see input/checkbox.feature.

Using data tables

TBD

For more example usage, see input/tables.feature.

Running scenarios

Scenario files can be run directly with Cypress:

$(npm bin)/cypress run [files]

or by using the Cypress UI:

$(npm bin)/cypress open

Customization

TBD

  • Options
  • Custom steps
  • API