@silverstripe-bespoke/cypress-bespoke-shared

0.0.4 • Public • Published

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 "test@test.com"

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

Readme

Keywords

Package Sidebar

Install

npm i @silverstripe-bespoke/cypress-bespoke-shared

Weekly Downloads

45

Version

0.0.4

License

ISC

Unpacked Size

24.1 kB

Total Files

16

Last publish

Collaborators

  • jameszhuu
  • jareddreyerss
  • mo7
  • edwilde-silverstripe
  • chrispenny
  • bernie-silverstripe