@silverstripe-bespoke/cypress-bespoke-shared
v0.0.4
Published
Generic Cypress Cucumber steps
Downloads
251
Readme
Cypress Shared Module
This module contains common patterns for using Cypress with Cucumber (via @badeball/cypress-cucumber-preprocessor
).
Getting started
yarn add @silverstripe-bespoke/cypress-bespoke-shared --dev
How to use this module
This module will add generic Cucumber steps to your cypress project.
The steps contained in this module is designed to be used with a Page Object Model so you will nee to supply at least one Page object and call the follwing in your global.cy.js
file:
import createGenericSteps from '@silverstripe-bespoke/cypress-bespoke-shared';
import pageObjects from './your-project-somewhere';
createGenericSteps(pageObjects);
you can then start using the Steps included in this module.
Page Objects
Page objects mediate between the test code and your application. Think of if as where the natural language of a Cucumbers step is translated into code.
To do this Page objects have two required properties url
and elements
as below:
type PageObject = {
readonly url: string,
elements: {
[index: string]: string
}
}
The url
will be used by Cypress to navigate to this page (via cy.visit()
).
The elements
object is a map of element names as they appear in steps to a valid JavaScript selector. Eg {'Main navigation': 'nav[role="main"]'}
. Test steps then only need to refer to the element name eg Then the "Main navigation" is visible
.
Steps included in this module
Given
| Step | Parameters | Description | Example |
|---|---|---|---|
|I am on the {string}
| Page object name | This will set the current page object context | Given I am on the "HomePage"
|
|I navigate to the {string}
| Page Object Name | This will set the current page object context and navigate to that page. This is normally the first step in a test. | Given I navigate to the "HomePage"
|
|I am testing the {string}
| Page Object Name | This will set the current page object context, useful when testing distinct features on another page| Given I am testing the "Header"
|
|I visit {string}
| url string | This will navigate to a given url | Given I visit "/"
|
|I request {string}
| url string | This will make a get request to the given url| Given I request "/api"
|
|I am on desktop
| none | This will change the viewport to a desktop size ||
|I am on tablet
| none | This will change the viewport to a tablet size ||
|I am on mobile
| none | This will change the viewport to a mobile size ||
Then
Browser state
| Step | Parameters | Description | Example |
|---|---|---|---|
|I should see the title is {string} in the browser
| title text | Checks the page title | Then I should see the title is "Home" in the browser
|
|I should see the url includes {string}
| url fragment | Checks the url contains a substring | Then I should see the url includes "/home"
|
Visibility
| Step | Parameters | Description | Example |
|---|---|---|---|
|I should see the {string} is visible
| page element name | checks the given page element is visible| Then I should see the "Main navigation" is visible
|
|I should see the {string} of the {string} is visible
| ordinal position, page element name | checks the first, second, third etc. of a given page element is visible| Then I should see the "first" of the "Main navigation items" is visible
|
|I should see the last of the {string} is visible
| page element name | checks the last of a given page element is visible| Then I should see the last of the "Main navigation items" is visible
|
|||||
|I should see the {string} is not visible
| page element name | checks the given page element is not visible| Then I should see the "Main navigation" is not visible
|
|I should see the {string} of the {string} is not visible
| ordinal position, page element name | checks the first, second, third etc. of a given page element is not visible| Then I should see the "second" of the "Main navigation items" is not visible
|
|I should see the last of the {string} is not visible
| page element name | checks the last of a given page element is not visible| Then I should see the last of the "Main navigation items" is not visible
|
|||||
|I should see the {string} is in the viewport
| page element name | checks the given page element is in the viewport. Requires the isInViewport assertion | Then I should see the "tool tip" is in the viewport
|
|I should see the {string} is not in the viewport
| page element name | checks the given page element is not in the viewport. Requires the isInViewport assertion | Then I should see the "tool tip" is not in the viewport
|
|||||
|I should see {int} {string}
| number and page element name | counts how many of a page element are present| `Then I should see 5 "list items"|
Exists
| Step | Parameters | Description | Example |
|---|---|---|---|
|I should see the {string} exists
| page element name | checks the given page element exists| Then I should see the "Main navigation" exists
|
|I should see the {string} of the {string} exists
| ordinal position, page element name | checks the first, second, third etc. of a given page element exists| Then I should see the "first" of the "Main navigation items" exists
|
|I should see the last of the {string} exists
| page element name | checks the last of a given page element exists| Then I should see the last of the "Main navigation items" exists
|
|||||
|I should see the {string} does not exist
| page element name | checks the given page element does not exist| Then I should see the "Main navigation" does not exist
|
|I should see the {string} of the {string} does not exist
| ordinal position, page element name | checks the first, second, third etc. of a given page element does not exist| Then I should see the "fourth" of the "Main navigation items" does not exist
|
|I should see the last of the {string} does not exist
| page element name | checks the last of a given page element does not exist| Then I should see the last of the "Main navigation items" does not exist
|
Content assertions
| Step | Parameters | Description | Example |
|---|---|---|---|
|I should see the {string} contains {string}
| page element name, text | Check if an page element contains a given string | Then I should see the "button" contains "Read More"
|
|I should see the {string} has attribute {string}
| page element name, attribute name| Checks a page element has a given attribute| Then I should see the "menu" has attribute "hidden"
|
|I should see the {string} does not have attribute {string}
| page element name, attribute name| Checks a page element does not have a given attribute| Then I should see the "menu" does not have attribute "hidden"
|
|I should see the {string} has attribute {string} with value {string}
| page element name, attribute name, attribute value | Checks a page element has a given attribute with a given value| Then I should see the "menu" has attribute "aria-expanded" with value "false"
|
Forms
| Step | Parameters | Description | Example |
|---|---|---|---|
|I should see the {string} form field has value {string}
| page element name, field value | Checks a page element has a given attribute with a given string value| Then I should see the "email" form field has value "[email protected]"
|
Wait
| Step | Parameters | Description | Example |
|---|---|---|---|
|I wait {int} seconds
| seconds | This will make the test wait for a given length of time | Given I wait 5 seconds
|I wait a bit
| none | Adds a 500ms wait step to the test, useful for quick animations or interactions | Then I wait a bit
|
Meta states
coming soon
Content assertions
| Step | Parameters | Description | Example |
|---|---|---|---|
|I should see the {string} element receive focus
| page element name | Checks an element is in the focus state| Then I should see the "button" element receive focus
|
When
Press
| Step | Parameters | Description | Example |
|---|---|---|---|
|I press the {string} element
| page element name | Clicks or touches a page element | When I press on the "button" element
|
|I press the first {string} element
| page element name | Clicks or touches the first of a list of page elements | When I press the first "button" element
|
|I press the second {string} element
| page element name | Clicks or touches the second of a list of page elements | When I press the second "button" element
|
Keyboard interactions
| Step | Parameters | Description | Example |
|---|---|---|---|
|I press the Enter key on {string} element
| page element name | Presses the <enter>
key on the keyboard | When I press the Enter key on "button" element
|
|I press the tab key
| none | Presses the <tab>
key on the keyboard | When I press the tab key
|
|I press the tab key on {string}
| page element name | Presses the <tab>
key on a particular element | When I press the tab key on "link"
|
|I type {string} into the {string} field
| field value, page text field | Types the content into the field element | When I type "This is a text field" into the "input" field
|
Example setup
The following shows a basic cypress setup using this module:
Setup re-usable components inside cypress/page_objects/components
directory:
e.g. Header.js
export default {
'Header': '.header',
'Header logo': '.header__logo',
}
Setup an page object as follows in your cypress/page_objects
directory:
import Header from '../components/Header';
export class TestPage {
static url = '/test-page/';
static elements = {
...Header,
'Cta Block Container': '.cta-block',
'Cta Block Header': '.cta-block .cta-block__title',
'Cta Block Links': '.cta-block .cta-block__links'
}
}
Add this page to the index file cypress/page_objects/index.js
:
import TestPage from './testPage';
const pages = {
TestPage: TestPage,
};
export default pages;
Import the page objects to your cypress/common/global.cy.js
file:
import Pages from '../page_objects';
import createSharedSteps from '@silverstripe-bespoke/cypress-bespoke-shared'
createSharedSteps(Pages);
You can now use these steps in a feature file e.g. cypress/e2e/TestPage.feature
Feature: Test Page feature
@desktop
Scenario: A Test page has a CTA block
Given I am on desktop
And I navigate to the "TestPage"
Then I should see the "Cta Block Container" is visible
And I should see the "Cta Block Header" is visible
And I should see the "Cta Block Header" contains "Example title"
And I should see the "third" of the "Cta Block Links" is visible
Is in viewport assertion
Add this to the cypress/support/assertions.js
file:
const isInViewport = (_chai, utils) => {
function assertIsInViewport(options) {
const subject = this._obj;
const bottom = Cypress.$(cy.state('window')).height();
const rect = subject[0].getBoundingClientRect();
// Keeping our "is in viewport" check simple. If the top of the element is anywhere in our viewport, and if the
// bottom of the element is lower than the top of our viewport, then we will consider this to be "in view"
this.assert(
rect.top > 0 && rect.bottom > 0 && rect.top <= bottom,
"expected #{this} to be in viewport",
"expected #{this} to not be in viewport",
this._obj
)
}
_chai.Assertion.addMethod('inViewport', assertIsInViewport)
};
chai.use(isInViewport);