0% found this document useful (0 votes)
29 views41 pages

Cypress

Uploaded by

bilelrtibi66
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
29 views41 pages

Cypress

Uploaded by

bilelrtibi66
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 41

Fast, easy and reliable testing for anything that runs in a browser

Last updated: 10 May 2022

© Pepgo Pty Ltd, Level 18, 333 Ann Street, Brisbane, QLD 4000, Australia
Contents
Cypress is not Selenium .......................................................................................................................... 5
Cypress Best Practices......................................................................................................................... 6
Installing Node and Cypress .................................................................................................................... 7
Install Node and the Node Package Manager (npm) .......................................................................... 7
Installing Cypress in Microsoft Windows ............................................................................................ 7
Upgrade Cypress to a newer version .................................................................................................. 7
Running Cypress interactively ................................................................................................................. 8
Cypress folder structure.......................................................................................................................... 9
Cypress configuration files .................................................................................................................... 10
Running Cypress from the command line or terminal.......................................................................... 10
Some example execution options ......................................................................................................... 11
Using browsers.................................................................................................................................. 11
Environment Variables...................................................................................................................... 11
Configuration Options....................................................................................................................... 12
Configure Cypress ................................................................................................................................. 13
Retries ............................................................................................................................................... 13
Writing Cypress tests ............................................................................................................................ 14
Debugging commands................................................................................................................... 14
Running specific tests or spec files only........................................................................................ 15
Skipping blocks (specs) or single tests .......................................................................................... 15
Interacting with Elements ..................................................................................................................... 16
.click() ................................................................................................................................................ 16
.dblclick() ........................................................................................................................................... 16
.rightclick() ........................................................................................................................................ 16
.type() ................................................................................................................................................ 16
.clear() ............................................................................................................................................... 16
.check() .............................................................................................................................................. 16
.uncheck().......................................................................................................................................... 16
.select().............................................................................................................................................. 16
.trigger() ............................................................................................................................................ 17
Overriding negative checks ............................................................................................................... 17
Browser navigation ............................................................................................................................... 17
Assertions.............................................................................................................................................. 18
Implicit and Explicit Assertions ......................................................................................................... 18

P a g e 2 | 41
Negative Assertions .......................................................................................................................... 18
Common Assertions .......................................................................................................................... 18
Length ........................................................................................................................................... 18
Class .............................................................................................................................................. 18
Value ............................................................................................................................................. 18
Text Content.................................................................................................................................. 18
Visibility ......................................................................................................................................... 18
Existence ....................................................................................................................................... 19
State .............................................................................................................................................. 19
CSS ................................................................................................................................................. 19
Multiple assertions ........................................................................................................................... 19
Hooks .................................................................................................................................................... 20
Closures and conditional statements ................................................................................................... 21
Aliases ................................................................................................................................................... 22
Stubbing, Spying, and controlling date and time (Clocks) .................................................................... 23
Use “cy.request()” instead of “cy.visit()” for API requests ............................................................... 23
Example GET method .................................................................................................................... 23
Example POST method.................................................................................................................. 23
Intercept............................................................................................................................................ 23
Stubbing with and without using Fixtures .................................................................................... 24
Spying ................................................................................................................................................ 24
Clocks ................................................................................................................................................ 25
Data-driven tests................................................................................................................................... 26
Reading data from a fixture file for data-driven tests ...................................................................... 27
Reading data from a JSON file....................................................................................................... 27
Reading data from a Comma-Separated Values (CSV) file ........................................................... 27
“Cy.visit()” configuration options.......................................................................................................... 29
Browser tab handling (Workaround) .................................................................................................... 30
Frames................................................................................................................................................... 31
File uploads ........................................................................................................................................... 32
XPath support ....................................................................................................................................... 33
Behaviour-Driven Development (BDD) ................................................................................................. 34
Jenkins integration ................................................................................................................................ 36
Docker ................................................................................................................................................... 36
Reporters .............................................................................................................................................. 37
Setup the “cypress-mochawesome-reporter” .................................................................................. 37

P a g e 3 | 41
Generate the HTML report using the “cypress-mochawesome-reporter”....................................... 37
Delete old test results data before creating a new report ............................................................... 38
Intelligent Code Completion in Microsoft Visual Studio Code ............................................................. 39
Option 1: Add “triple slash directives” to every program code page ............................................... 39
Option 2: Add a configuration file .................................................................................................... 39
“jsconfig.json” (if you use JavaScript) ........................................................................................... 39
“tsconfig.json” (if you use TypeScript) .......................................................................................... 39
Cypress Recorder .................................................................................................................................. 40
Cypress Scenario Recorder ................................................................................................................... 41

P a g e 4 | 41
Cypress is not Selenium
Cypress is not just another repackaging of Selenium like so many other JavaScript testing
frameworks, but it is a completely new and different approach. It uses very different technology.

Cypress tests run inside of the browser, which you can actually debug! Unlike Selenium, there are no
object serialisations or JSON wire protocol communications. You have real, native access to
everything in your application under test. This allows for direct access to the browser’s development
tools (<F12>), including all network recording and inspection options. It also allows for time travel
through a recorded session to restore the browser status to a specific time point during the test
execution. This makes debugging a lot easier than with Selenium.

Cypress is built around JavaScript and Node and supports them natively. This is unlike Selenium,
where JavaScript is just one of many possible language bindings and where using JavaScript does not
offer any advantage over any other language binding (like Java, C#, Python, Ruby etc.). Unlike
Selenium, Cypress is built around the concept of asynchronous communication that dominates
modern web architectures like Single Page Applications (SPA’s), which are often built with JavaScript
frameworks like React or Angular. Although there are plenty of JavaScript frameworks for Selenium
(like Nightwatch.js, Webdriver.io, Protractor etc.), these frameworks are still just repackaging and
trying to work around the synchronous nature of Selenium.

Selenium has been designed in a time where web applications were mostly static with fixed page
requests and page responses (stateless web applications). Cypress is about a decade newer than
Selenium and designed around asynchronous communication (stateful web applications).

The sweet spot of Cypress is to be used as a tool to test your own JavaScript application as you build
it. It is built for developers and Quality Assurance (QA) engineers. Cypress is particularly suitable for
fast visual low-level tests (Unit Tests and simple Integration Tests), while Selenium is often more
suitable for complex end-to-end business process based user interface tests, particularly when these
tests need to run on a variety of browsers and mobile devices.

Cypress has a much smaller community of developers, tools, and frameworks than Selenium. It will
certainly not replace Selenium any time soon, but it can and should be used where Selenium comes
to its limits with modern and interactive web applications.

 Tests execute faster in Cypress than in Selenium.


 Tests execute more reliably (less flaky) in Cypress than in Selenium.
 Cypress utilizes a single custom universal driver for all the browsers that it supports.
 Cypress comes with built-in explicit retries to search for elements in the Document Object
Model (DOM) and explicitly waits for events to happen before a test is considered to have
failed.
 Cypress allows for time travel. It takes snapshots as your tests run. In the Test Runner
application, you can them simply hover over commands in the Command Log to see exactly
what happened at, before, and after each step. You can often directly inspect the elements.
 Cypress allows for easy stubbing of API calls. This can make tests more reliable, and it also
allows for tests to be implemented when the API’s are not available yet, or cannot be used
because of financial constraints, or impacts on production systems.
 Screenshots are taken automatically on failure and videos of your entire test suite are
recorded when run headlessly (in Continuous Integration).

P a g e 5 | 41
 Cypress offers a simple Cucumber/Gherkin plugin for Behaviour-Driven Development (BDD).

 Cypress currently only supports Google Chrome-family browsers (including Electron,


Chromium-based Microsoft Edge, and Brave), and Mozilla Firefox. Other browsers, such as
Apple Safari might be supported in the future.
 Cypress does not support mobile testing. There is no equivalent to what Appium does for
Selenium.
 Selenium offers a much better integration with cloud testing providers like Sauce Labs and
BrowserStack.
 Cypress runs only in a single browser and only on a single browser tab, although this
document provides a workaround for the single browser tab problem.
 Cypress runs in a browser and therefore uses JavaScript only. Selenium supports a wide
range of programming languages, such as Java, Python, Ruby, C#, JavaScript, Perl, and PHP.
 In Cypress, each test is limited to only visiting a single superdomain (single origin).

Cypress is free and open source. Tests can be executed using the free Cypress Test Runner
application or headlessly, as described in this document. This document only covers free and open
source parts of Cypress.

In addition to that, Cypress also offers an optional cloud-based “Dashboard Service” for recording
test results. This service offers a free tier and multiple paid-for tiers with higher numbers of allowed
users and test results recordings. The paid “Dashboard Service” helps support the work that the
Cypress teams does on the free and open source Cypress Test Runner.

Cypress Best Practices


Cypress recommends using “data-*” attributes to provide context to your selectors and insulate
them from CSS or JavaScript changes.

1. Don’t target elements based on CSS attributes such as: “id“, “class“, or “tag“.
2. Don’t target elements that may change their text content.
3. Add “data-*” attributes to make it easy to target elements.

Cypress considers the use of “Page Objects” as recommended in Selenium as a no-go (anti-pattern).
It recommends testing specs in isolation (without the object sharing of “Page Objects”),
programmatically logging into your application (instead of using the user interface), and taking
control of your application’s state. This does not mean that the user interface login and account
creation / reset functionalities should not be tested using the user interface at all, but it means that
they should only be tested once, using the user interface in separate login tests. In all other test
cases, where the login state is just a precondition to the tests, the desired login state should ideally
be created programmatically, for example by using stubbed API calls. This is both faster and safer,
and it does not needlessly repeat the user interface login functionality multiple times.

P a g e 6 | 41
Installing Node and Cypress

Install Node and the Node Package Manager (npm)


Before you can install and use Cypress, you need to install Node.

Please follow an installation guide for your operating system and version.

You can check that Node has been successfully installed with this command:
node -v

When you installed Node, you also automatically installed the “npm” Command Line Interface (CLI),
which is the package manager for Node. You can check it with:
npm -v

Installing Cypress in Microsoft Windows


1. Change in the project folder where Cypress should get installed as part of the project:
cd /your_project_path

2. Initialise the project folder (if the folder is empty):


npm init -y
This will create a default “package.json” file that will be used to define the project.

3. Install Cypress with:


npm install --save-dev cypress

Upgrade Cypress to a newer version


The following example command upgrades Cypress to version 9.6.0:
npm install --save-dev [email protected]

P a g e 7 | 41
Running Cypress interactively
Cypress has 2 main execution commands:

 "cypress open" opens the GUI interactive mode (Test Runner application).
 "cypress run" executes in headless mode (suitable for Continuous Integration).

1. Add this to the “scripts” settings in the “package.json” file:

"scripts": {
"cypress:open": "cypress open"
},

2. You can then start the Cypress Test Runner application with:
npm run cypress:open

The following options are available for “cypress open”:

Option Description
--browser, -b Specify a different browser to run tests in
--config, -c Specify configuration
--detached, -d Open Cypress in detached mode
--config-file, -c Specify a configuration file that will be used to run the tests.
The values declared in this file override the ones in the
“cypress.json” file.
--env, -e Specify environment variables
--global Run in global mode
--help, -h Output usage information
--port, -p Override default port
--project, -P Path to a specific project

After running “cypress open” for the first time, the Test Runner window opens up after
some time with the message that a sample project folder structure has been provided by
Cypress.

P a g e 8 | 41
3. Cypress runs tests in a unique Test Runner application with many interactive features that
allow you to see commands as they execute while also viewing the application under test.

Cypress folder structure


cypress/fixtures Test data in form of key-value pairs for the tests
cypress/integration Test cases
cypress/plugins This folder is used for modifying and extending the internal
behaviour of Cypress. It can be used to extend the capabilities
like configuration management, dynamic browser selection,
running batch jobs etc.
The plugins file (“index.js”) is a special file that executes in
Node before the project is loaded, before the browser launches,
and during your test execution
cypress/support Reusable methods or customized commands, which can be
utilised by test cases directly without object creation.
“command.js” can contain re-usable code.
“index.js” runs before each test file. This can be leveraged
for handling pre-requisites for tests.
node_modules Project dependencies from the Nodes Package Manager (npm)

P a g e 9 | 41
Cypress configuration files
cypress.json The values of the current configurations can be modified here,
which overrules the default configurations
package.json Dependencies and scripts for the projects

Running Cypress from the command line or terminal


1. Add this to the “scripts” section in the “package.json” file:

"scripts": {
"cypress:run": "cypress run"
},

2. You can now run cypress with:


npm run cypress:run

If you just want to run a single spec file, then the command is for example:
npm run cypress:run -- --spec "cypress/integration/sample.spec.js"

If you want to run all spec file in a folder, then the command is for example:
npm run cypress:run -- --spec "cypress/integration/subfolder/**/"

Option Description
--browser, -b Specify a different browser to run tests in
--ci-build-id Specify a unique identifier for a run to enable grouping or
parallelisation
--config, -c Specify configuration
--config-file, -c Specify a configuration file that will be used to run the tests.
The values declared in this file override the ones in the
“cypress.json” file.
--env, -e Specify environment variables
--group Group recorded tests together under a single run
--headed Display the Electron browser instead of running headlessly
--headless Run tests without launching a browser
--help, -h Output usage information
--key, -k Specify your secret record key
--no-exit Keep Cypress Test Runner open after tests in a spec file run
--parallel Run recorded specs in parallel across multiple machines
--port,-p Override default port
--project, -P Path to a specific project
--record Whether to record the test run
--reporter, -r Specify a Mocha reporter
--reporter-options, -o Specify Mocha reporter options
--spec, -s Specify the spec files to run

P a g e 10 | 41
Some example execution options

Using browsers
Cypress currently supports Google Chrome in the varieties Chrome, Chrome Beta, Chrome Canary,
Chromium, Edge, Edge Beta, Edge Canary, Edge Dev, and Electron. Mozilla Firefox is currently
supported in the varieties Firefox, Firefox Developer Edition, and Firefox Nightly. Cypress does
recognise installed browser versions automatically.

The Electron browser is a version of Chromium that comes with Electron. It comes baked into
Cypress and does not need to be installed separately. By default, when running “cypress run”
from the command line or terminal, it will launch Electron headlessly. Because Electron is the default
browser, it is typically run in Continuous Integration. If you are seeing failures in Continuous
Integration, to easily debug them, you may want to run locally with the “--headed” option.

A specific browser can be launched with:


cypress run -- --browser chrome

A browser can also be launched by specifying a path to the binary:

cypress run -- --browser /usr/bin/chromium

Note: Cypress generates its own isolated profile apart from your normal browser profile.

Environment Variables
Cypress environment variables are dynamic name-value pairs that influence the way Cypress
executes tests. These environment variables are useful when there is a need to run the tests in
multiple environments, or when the defined values are prone to quickly changing.

In Cypress, you can define single or multiple environment variables either as strings or JSON objects.

Environment Variables are set in the file “package.json”.

This example defines an environmental variable called “TransferProtocol”:

"scripts": {
"cypress:run": "cypress run -–env TransferProtocol='http'",
"cypress:run:v2": "cypress run –-env TransferProtocol='https'"
},

It can then be used in tests like this:

cy.visit('${Cypress.env("TransferProtocol")}://www.example.com')

P a g e 11 | 41
The script can then be executed with either
npm run cypress:run

or
npm run cypress:run:v2

Configuration Options
Cypress can set and override configurations using commands running on the terminal.

This example sets or overrides the viewport settings:

"scripts": {
"cypress:tablet-view": "cypress run --config viewportHeight=763,viewportWidth=700"
},

It can be run with:


npm run cypress:tablet-view

P a g e 12 | 41
Configure Cypress
Configuration options are set in the file “cypress.json”.

This example “baseURL” automatically prefixes “cy.visit()” and “cy.request()”


commands:

{
"baseUrl": "https://example.cypress.io"
}

With this setting, it is then possible to call the home page just with “cy.visit('/')”, instead of
“cy.visit('https://example.cypress.io')”.

Cypress has many more configuration options that you can use to customise its behaviour. These
include where your tests live, default timeout periods, environment variables, which reporter(s) to
use, and many more.

The default timeout periods are:


Option Default Description
defaultCommandTimeout 4000 Time, in milliseconds, to wait until most DOM based commands are
considered timed out
execTimeout 60000 Time, in milliseconds, to wait for a system command to finish executing
during a “cy.exec()” command
taskTimeout 60000 Time, in milliseconds, to wait for a task to finish executing during a
“cy.task()” command
pageLoadTimeout 60000 Time, in milliseconds, to wait for page transition events or
“cy.visit()”, “cy.go()”, “cy.reload()” commands to fire their
page load events. Network requests are limited by the underlying
operating system, and may still time out if this value is increased.
requestTimeout 5000 Time, in milliseconds, to wait for an XHR request to go out in a
“cy.wait()” command
responseTimeout 30000 Time, in milliseconds, to wait until a response in a “cy.request()”,
“cy.wait()”, “cy.fixture()”, “cy.getCookie()”,
“cy.getCookies()”, “cy.setCookie()”,
“cy.clearCookie()”, “cy.clearCookies()”, and
“cy.screenshot()” commands

Retries
A powerful configuration useful for unstable tests is retries. The retries option retries the test, if it
fails. At times tests fail because of network or environmental issues. In these circumstances, retrying
tests is very important, as there might not be any problem with the actual tests themselves. The
retries option is specified in the “cypress.json” file. The following example retires a failed tests
3 more times when executed in run mode, and 2 more times when executed in open mode:

"retries": {
"runMode": 3,
"openMode": 2
}

P a g e 13 | 41
Writing Cypress tests
Cypress test spec files should use the “*.spec.js” file extension and be stored in the
“cypress/integration” folder of the project. This ensures that the test spec files will
automatically be picked up by the Test Runner application.

This example test uses the example application named “Kitchen Sink” from the “cypress.io” web site.
It does the following:

1. Calls the “Kitchen Sink” start page https://example.cypress.io .


2. Clicks on an element that contains the text “type”.
3. Verifies (=asserts) that the resulting URL includes “/commands/actions”.
4. Types “[email protected]” into the element “.action-email” and verifies (=asserts) that the
text is correctly entered into the element.

describe('My First Test', () => {


it('Gets, types and asserts', () => {
cy.visit('https://example.cypress.io')
cy.contains('type').click()
// Should be on a new URL which includes '/commands/actions'
cy.url().should('include', '/commands/actions')
// Get an input, type into it and verify that the value has been updated
cy.get('.action-email')
.type('[email protected]')
.should('have.value', '[email protected]')
})
})

Note: In Cypress, elements are queried using the JQuery syntax. This also allows JQuery DOM
traversals. For example:

// Each method is equivalent to its jQuery counterpart.


cy.get('#main-content')
.find('.article')
.children('img[src^="/static"]')
.first()

Most commands allow individual timeout settings (the Cypress default timeout is 4 seconds):

// Give this element 10 seconds to appear


cy.get('.my-slow-selector', { timeout: 10000 })

Debugging commands
cy.pause() Stop “cy” commands from running and allow interaction with the application
under test. You can then “resume” running all commands or choose to step
through the “next” commands from the Command Log.
Unlike the “.debug” command, “cy.pause()” does not have to chained to
other commands and can be used independently.

P a g e 14 | 41
.debug() Set a debugger and log what the previous command yields. You need to have
your Developer Tools (<F12>) open for “.debug()” to hit the breakpoint.
Example use for logging out the current subject for debugging:
cy.get('.ls-btn').click({ force: true }).debug()

Running specific tests or spec files only


By default, Cypress executes all tests and specs files. If only a single test (or spec) should be
executed, then this can be achieved by adding “.only” to the test (or spec), for example for the
test example used before:

it.only('Gets, types and asserts', () => {



}

This is particularly useful during test development when a new test case gets added to the existing
test cases.

Skipping blocks (specs) or single tests


Tests that are in a whole block (spec) can be excluded from execution by skipping the whole test
block (spec) with “describe.skip(…)”.

Single tests can be excluded from execution by skipping the test with “it.skip(…)”.

P a g e 15 | 41
Interacting with Elements
These action commands can interact with elements:

.click()
cy.get('button').click() // Click on button (in the centre of the button)
cy.get('button').click('topLeft') // Click on button (in the top left corner of the button)
cy.focused().click() // Click on el with focus
cy.contains('Welcome').click() // Click on first el containing 'Welcome'
An element will be clicked in the centre by default, .but an element can also be clicked “topLeft”,
“top”, “topRight”, “left”, “right”, “bottomLeft”, “bottom”, and “bottomRight”.

.dblclick()
cy.get('button').dblclick() // Double click on button
cy.focused().dblclick() // Double click on el with focus
cy.contains('Welcome').dblclick() // Double click on first el containing 'Welcome'

.rightclick()
cy.get('button'). rightclick() // Right-click on button
cy.focused().rightclick() // Right-click on el with focus
cy.contains('Welcome').rightclick() // Right-click on first el containing 'Welcome'

.type()
cy.get('input').type('Hello, World') // Type 'Hello, World' into the 'input'
cy.get('input').type('Hello, World',{force: true}) // Type 'Hello, World' into disabled 'input'

.clear()
cy.get('[type="text"]').clear() // Clear text input
cy.get('textarea').type('Hi!').clear() // Clear textarea
cy.focused().clear() // Clear focused input/textarea

.check()
cy.get('[type="checkbox"]').check() // Check checkbox element
cy.get('[type="radio"]').first().check() // Check first radio element
cy.get('[type="radio"]').should('be.checked') // Verification

.uncheck()
cy.get('[type="checkbox"]').uncheck() // Unchecks checkbox element
cy.get('[type="radio"]').should('not.be.checked') // Verification

.select()
cy.get('select').select('user-1') // Select the 'user-1' option
cy.get('select').select(['user-1','user-2']) // Select both 'user-1' and 'user-2'

P a g e 16 | 41
.trigger()
cy.get('a').trigger('mousedown') // Trigger mousedown event on link
The trigger command in Cypress helps trigger an event on the DOM element. X, Y positions can also
be supplied to the trigger command.

This command is useful for all mouse events, including drag and drop operations. Mouse events
include “mousedown”, “mouseup”, “mouseover”, and “mousemove”.

Overriding negative checks


Cypress does a lot of internal checks and adjustments before action commands get executed.
Sometimes, a negative result from these checks will prevent the execution. In these cases, it is
possible to override the negative results by using “{force: true}”, for example:

cy.get('button').click({force: true})

Browser navigation
Going back to the previous page is possible by passing “-1” or “'back'” to the “go” method, for
example:

cy.go(-1)
cy.go('back')

Similarly, going forward to the next page is accomplished by passing “1” or “'forward'” to the
“go” method:

cy.go(1)
cy.go('forward')

Cypress also provides a method called “reload” for refreshing or reloading the page:

cy.reload()

P a g e 17 | 41
Assertions

Implicit and Explicit Assertions


An Implicit assertion is an assertion that applies to the object provided by the parent chained
command. This category of assertions generally includes commands such as “.should()” and
“.and()”. As these commands don’t stand independently and always depend on the previously
chained parent command, they automatically inherit and act on the object yielded by the previous
command.

When there is a need to pass an explicit object for the assertion, it falls under the category of Explicit
assertion. This category of assertions contains commands such as “expect()” and “assert()”.

Negative Assertions
By adding “.should('not.exist')” to any DOM command, Cypress will reverse its default
assertion and automatically wait until the element does not exist.

Common Assertions
Length
// retry until finding 3 matching <li.selected>
cy.get('li.selected').should('have.length', 3)

Class
// retry until this input does not have class disabled
cy.get('form').find('input').should('not.have.class', 'disabled')

Value
// retry until this textarea has the correct value
cy.get('textarea').should('have.value', 'foo bar baz')

Text Content
// partial text match for non-input HTML element
cy.get('#text-example').should('contain', 'welcome to')

// retry until this span does not contain 'click me'


cy.get('a').parent('span.help').should('not.contain', 'click me')

Visibility
// retry until this button is visible
cy.get('button').should('be.visible')

P a g e 18 | 41
Existence
// retry until loading spinner no longer exists
cy.get('#loading').should('not.exist')

State
// retry until our radio is checked
cy.get(':radio').should('be.checked')

CSS
// checks if the web element has a certain CSS property
cy.get('#txt-fld').should('have.css', 'display', 'block')

Multiple assertions
Multiple assertions can be chained by using multiple “.should()”. Alternatively, a second (or
more) assertion can also be written as “.and()”, which is exactly the same as “.should()”, but
makes tests better human readable.

P a g e 19 | 41
Hooks
Cypress provides hooks (borrowed from the underlying Mocha framework).

Hooks are helpful to set conditions that you want to run before a set of tests or before each test.
They’re also helpful to clean up conditions after a set of tests or after each test.

before(() => {
// runs once before all tests in the block
})

after(() =>{
// runs once after all tests in the block
})

beforeEach(() => {
// runs before each test in the block
})

afterEach(() => {
// runs after each test in the block
})

P a g e 20 | 41
Closures and conditional statements
To access what each Cypress command yields use “.then()”:

cy.get('button').then(($btn) => {
// $btn is the object that the previous command yielded us
})

This is a full example of using “.then”:

cy.get('button').then(($btn) => {
// store the button's text
const txt = $btn.text()
// submit a form
cy.get('form').submit()
// compare the two buttons' text
// and make sure they are different
cy.get('button').should(($btn2) => {
expect($btn2.text()).not.to.eq(txt)
})
})

Closures can also be used for conditional testing, for example:

// this only works if there's 100% guarantee


// body has fully rendered without any pending changes
// to its state
cy.get('body').then(($body) => {
// synchronously ask for the body's text
// and do something based on whether it includes
// another string
if ($body.text().includes('some string')) {
// yup found it
cy.get(…).should(…)
} else {
// nope not here
cy.get(…).should(…)
}
})

P a g e 21 | 41
Aliases
Aliases are a way to prevent the usage of “.then()” callback functions in our tests.

Aliases are often used to share objects between hooks and tests. Another great use of aliasing for
sharing contexts is with Cypress fixtures.

Aliases allow sharing and reusing of objects. To alias something you’d like to share use the “.as()”
command.

Cypress aliases can be accessed in two ways:

1. The “this” keyword before the alias is used for (direct) synchronous access.
2. Using the “@” character before the alias is used for asynchronous access (execute and
continue without waiting for the response).

beforeEach(() => {
// alias the $btn.text() as 'text'
cy.get('button').invoke('text').as('text')
})

it('has access to text', () => {


this.text // is now available
})

Aliases have other special characteristics when being used with DOM elements. After you alias DOM
elements, you can then later access them for reuse.

// alias all of the tr's found in the table as 'rows'


cy.get('table').find('tr').as('rows')

Internally, Cypress has made a reference to the “<tr>” collection returned as the alias “rows”. To
reference these same “rows” later, you can use the “cy.get()” command.

// Cypress returns the reference to the <tr>'s


// which allows us to continue to chain commands
// finding the 1st row.
cy.get('@rows').first().click()

Because we’ve used the “@” character in “cy.get()”, instead of querying the DOM for elements,
“cy.get()” looks for an existing alias called “rows” and returns the reference (if it finds it).

P a g e 22 | 41
Stubbing, Spying, and controlling date and time (Clocks)
Most web applications make background calls to (API) services. Cypress makes it easy to control the
responses of these background service calls by replacing or simulating the responses of these service
calls, even if the API’s are not built or available yet (mocking).

Cypress makes it easy to stub a server response and control the body, status, headers, or even delay
of the server response.

Use “cy.request()” instead of “cy.visit()” for API requests


The “cy.request()” command is responsible for making HTTP requests to (API) endpoints. This
command can be used to execute API requests and receive responses without the need to create or
import an external library to make and handle API requests and responses.

Example GET method


cy.request({method:'GET',
url:'https://jsonplaceholder.cypress.io/comments'}).should((response) => {
// the server sometimes gets an extra comment posted from another machine
// which gets returned as 1 extra object
expect(response.body)
.to.have.property('length')
.and.be.oneOf([500, 501])
expect(response.status).to.eq(200)
expect(response).to.have.property('headers')
expect(response).to.have.property('duration')
}
)

Example POST method


cy.request({method:'POST',
url:'https://jsonplaceholder.typicode.com/posts',
body:{title:'foo',body:'bar',userId:1}}).should((response) => {
expect(response.status).to.eq(201)
}
);

Intercept
In version 6, Cypress introduced the “cy.intercept()” command. It replaced and superseded
“cy.route()” and does not require the use of “cy.server()” any more.

“cy.intercept()” offers flexibility and granular control over handling of the network layer. It
has out-of-the-box support for intercepting fetch calls, page loads, and resource loads in addition to
the pre-existing support for XMLHttpRequests (XHR).

“cy.intercept()” can handle “GET”, “POST”, “PUT”, “PATCH”, and “DELETE” methods.

P a g e 23 | 41
“cy.intercept()” must be called before it can be referenced in tests, so that the routes are
recorded before they are called. It is therefore usually part of the “beforeEach()” hook.

The following is an example that shows the “cy.intercept()” command listening for an XHR
response that it expects Cypress to make on initialization of the application. It waits for the route
response to have been called before it completes execution.

The “cy.wait()” command enables waiting for the (stubbed or genuine) response before
proceeding with the next Cypress command. This can make tests more robust. Another benefit of
using “cy.wait()” on requests is that it allows you to access the actual XHR object. This is useful
when you want to make assertions about this object. You can check the URL, Method, Status Code,
Request Body, Request Headers, Response Body, and Response Headers of the XHR object.

describe('Routing a request', () => {


it('can wait for a app initialization', () => {
cy.intercept('POST','**/j/**').as('initializeTodoApp');
cy.visit('https://todomvc.com/examples/react/#/');
cy.wait('@initializeTodoApp'); // wait for intercept
response
})
});

“cy.intercept()”provides the ability to override XHR responses returned by the requests made
by Cypress tests during execution. Overriding the XHR responses is called “stubbing”.

Stubbing with and without using Fixtures


A fixture is a fixed set of data usually located in a file (often of type “*.json”) that is used in your
tests. The purpose of a test fixture is to ensure that there is a well-known fixed environment in
which tests are run, so that results are repeatable. Fixtures are accessed within tests by calling the
“cy.fixture()” command.

The following example uses a fixture file called “activities.json” (that is stored in the default
Cypress fixture folder “/cypress/fixtures”) to automatically stub responses for “GET”
requests that include the substring “/myapi” (for example to
“https://example.com/myapi?_limit=3”):

cy.intercept('GET', '/myapi', {fixture:'activities.json'})

If is also possible to set the stubbed response directly without using a Fixture file:

cy.intercept('GET', '/myapi', {statusCode:200,body:'All OK!'})

Spying
Spying is also very easy with Cypress. It is basically the same as stubbing, but without the third
argument for the payload data.

P a g e 24 | 41
A spy gives you the ability to “spy” on a function, by letting you capture and then assert that the
function was called with the right arguments, or that the function was called a certain number of
times, or even what the return value was, or what context the function was called with.

Spies are only used for verification of working elements or methods in Cypress. Spies do not modify
the behaviour of functions, they leave them perfectly intact.

Spy example:

const obj = {
sum(a, b) {
return a + b
}
}
const spyRequest = cy.spy(obj,'sum')
obj.sum(1, 2) // trigger the spy
expect(spyRequest).to.be.called
expect(spyRequest.returnValues[0]).to.eq(3)

Clocks
There are situations when it is useful to control your application’s date and time in order to override
its behaviour or avoid slow tests.

With “cy.clock()” you can control:

 “Date”
 “setTimeout”
 “setInterval”

P a g e 25 | 41
Data-driven tests
The easiest way for data-driven tests in Cypress is by looping through an array using “.forEach”,
as in this example:

const names = ['foo', 'bar', 'baz']


names.forEach(name => {
it('works for ${name}', () => {
cy.visit('/')
cy.contains(name)
})
})

This example runs and reports 3 test executions (one execution for each array member).

It is of course also possible to run and report just one test execution, but with 3 different assertions
inside the test by declaring and using the array inside the test.

Using “.wrap” for iterations is often helpful, as in this example:

const items = [
{text: 'Buy milk', expectedLength: 1},
{text: 'Buy eggs', expectedLength: 2},
{text: 'Buy bread', expectedLength: 3}
]

cy.wrap(items)
.each(todo => {
cy.get('.my-input')
.type(todo.text)
.type('{enter}')
cy.get('.my-list li')
.should('have.length', todo.expectedLength)
})

P a g e 26 | 41
Reading data from a fixture file for data-driven tests

Reading data from a JSON file


Example fixture file “/cypress/fixtures/testdata.json”:

{
"data": [
{
"city": "Tokyo",
"country": "Japan"
},
{
"city": "Shanghai",
"country": "China"
}
]
}

Example test that iterates through the data from a JSON fixture file:

it('Read and log data from a JSON fixture file', () => {


cy.fixture('testdata.json').then(alldata => {
alldata.data.forEach(data => {
cy.log(data.city)
cy.log(data.country)
})
})
})

Reading data from a Comma-Separated Values (CSV) file


Test data is often held and maintained in CSV files, which are easy to use for business users through
Microsoft Excel.

CSV files can easily be converted to JSON files trough Node parser packages, such as Papa Parse:
https://www.papaparse.com/ . Pease check the excellent documentation for parameters etc.

To work with Papa Parse, you have to install it with:


npm install --save-dev papaparse

For parsing from CSV to JSON, you have to add

import {parse} from "papaparse"


to the program code.

P a g e 27 | 41
Example CSV file “/cypress/fixtures/csv_example.csv”:

city,country
"Tokyo","Japan"
"Shanghai","China"

Example test that converts a CSV fixture file to a JSON file fixture file and iterates through the JSON
data of the newly created JSON fixture file:

/// <reference types="cypress" />

import {parse} from "papaparse"

describe('Convert CSV to JSON (fixture) with Papa Parse', function () {

let allData // "allData" is an object that contains an array called "allData.data"

before(() => {
// convert CSV fixture to JSON fixture
cy.readFile('./cypress/fixtures/csv_example.csv').then(str => {
cy.writeFile('./cypress/fixtures/csv_example.json', parse(str, {header:true}))
})
// read JSON fixture data
cy.fixture('csv_example.json').as('dataJson').then(dataJson => {
allData = dataJson
})
})

it('Convert, read, and log CSV data', function () {


// use JSON fixture data
allData.data.forEach(data => {
cy.log(data.city)
cy.log(data.country)
})
})
})

P a g e 28 | 41
“Cy.visit()” configuration options

Option Default Description

url null The URL to visit. Behaves the same as the url argument.

method GET The HTTP method to use in the visit. Can be GET or POST.

An optional body to send along with a POST request. If it is a string, it


will be passed along unmodified. If it is an object, it will be URL encoded
body null
to a string and sent with a Content-Type: application/x-www-
urlencoded header.

An object that maps HTTP header names to values to be sent along with
headers {} the request. Note: headers will only be sent for the
initial cy.visit() request, not for any subsequent requests.

qs null Query parameters to append to the url of the request

log true Displays the command in the Command log

auth null Adds Basic Authorization headers

failOnStatusCode True Whether to fail on response codes other than 2xx and 3xx

onBeforeLoad function Called before your page has loaded all of its resources.

onLoad function Called once your page has fired its load event.

Whether Cypress should automatically retry status code errors under the
retryOnStatusCodeFailure False
hood. Cypress will retry a request up to 4 times if this is set to true.

Whether Cypress should automatically retry transient network errors


retryOnNetworkFailure True under the hood. Cypress will retry a request up to 4 times if this is set to
true.

timeout pageLoadTimeout Time to wait for cy.visit() to resolve before timing out

P a g e 29 | 41
Browser tab handling (Workaround)
Cypress does not have a specific command to work with browser tabs. However, there is a
workaround method in jQuery through which Cypress can handle browser tabs.

Cypress uses the jQuery method “removeAttr”. It deletes the attribute that is passed as one of
the parameters to the “invoke” method. Once the HTML “target=_blank” is removed, then a
link/button opens in the parent window. Later on after performing the operations on it, you can shift
back to the parent URL with the go command.

/// <reference types="cypress" />

describe('Browser tab handling example', function () {


// test case
it('New tab opened up through a link with a HTML target="_blank" attribute', function () {
// url launch
cy.visit("https://the-internet.herokuapp.com/windows")
// delete target attribute created by the link
cy.get('.example > a').invoke('removeAttr', 'target').click()
// verify tab title
cy.title().should('eq', 'New Window')
// shift back to parent window
cy.go('back');
});
});

P a g e 30 | 41
Frames
To work with (i)Frames, you have to install a Cypress plugin:
npm install --save-dev cypress-iframe

For the frame implementation in Cypress, you have to add the statement

import 'cypress-iframe'
to the program code.

The method “frameLoaded()'“ is used to move the focus from the main page to the frame.
Once the focus is shifted, you can interact with the elements inside the frame. This is done with the
“iframe()“ method.

If you would like to use IntelliSense in Microsoft Visual Studio Code, then you should also add
“<reference types="cypress-iframe" /> “to the program code:

/// <reference types="cypress" />


/// <reference types="cypress-iframe" />

import 'cypress-iframe'

describe('Frame handling example', function () {


// test case
it('Switch to iFrame', function (){
// launch URL
cy.visit("https://jqueryui.com/draggable/");
// frame loading
cy.frameLoaded('.demo-frame');
// shifting focus
cy.iframe().find("#draggable").then(function(t){
const frmtxt = t.text()
// assertion to verify text
expect(frmtxt).to.contains('Drag me around');
cy.log(frmtxt);
})
});
});

P a g e 31 | 41
File uploads
For file uploads, you have to install a Cypress plugin:
npm install --save-dev cypress-file-upload

Once the installation is done, you have to add the statement

import 'cypress-file-upload'

to the “cypress/support/command.js” file.

You also need to add the file that you want to upload (“myfile.png” in this example) to the
“cypress/fixtures” folder.

/// <reference types="cypress" />

describe('Upload example', function () {


// test case
it('Upload a file', function () {
// launch URL
cy.visit("https://the-internet.herokuapp.com/upload")
// upload file with attachFile
cy.get('#file-upload').attachFile('myfile.png')
// click on upload
cy.get('#file-submit').click()
// verify uploaded file
cy.get('#uploaded-files').contains('myfile')
});
});

P a g e 32 | 41
XPath support
Cypress supports CSS selectors by default, but XPath support can be added.

For XPath support in Cypress, you have to install a plugin:


npm install --save-dev cypress-xpath

Once the installation is done, you have to add the statement

require('cypress-xpath')

to the “cypress/support/index. js” file.

This will then enable “cy.xpath()”, for example:

cy.xpath('//ul[@class="todo-list"]//li').should('have.length',3)

P a g e 33 | 41
Behaviour-Driven Development (BDD)
The following recipe uses Cucumber and Gherkin in Cypress with an example Behaviour-Driven
Development (BDD) test case.

The example test case searches for “New York” on Google Search. It then checks, if the search
returns a page with the correct HTML title tag.

With the setup described in this recipe, all “Feature” files must be stored in the
“cypress/integration/features” folder, while all “Step Definition” files must to be stored
in the “cypress/integration/features/step_definitions” folder.

1. Install two plugins:


npm install --save-dev cucumber
npm install --save-dev cypress-cucumber-preprocessor

2. Add this to “package.json”:

"cypress-cucumber-preprocessor": {
"cypress-cucumber-preprocessor": {
"nonGlobalStepDefinitions": false
},
"stepDefinitions": "cypress/integration/features/step_definitions/**/"
}

3. Add this to “cypress.json”:

"testFiles": "**/*.feature"

4. In the “cypress/plugins/index.js” file, add the following:

const cucumber = require('cypress-cucumber-preprocessor').default


module.exports = (on, config) => {
on('file:preprocessor', cucumber())
}

5. Create a new folder “cypress/integration/features”.

P a g e 34 | 41
6. In the just created folder “cypress/integration/features”, generate a new file
called “GoogleSearch.feature” with this content:

Feature: Google Search


This Feature covers Google Search tests

Scenario: Do a successful Google Search


Given I am on the Google home page
When I type New York in the Search field
And I press the Search button
Then I should get a page with the correct title

7. Create a new folder “cypress/integration/features/step_definitions”.

8. In the just created folder


“cypress/integration/features/step_definitions”, generate a new file
called “GoogleSearch.steps.js” with this content:

import { Given, When, Then } from 'cypress-cucumber-preprocessor/steps'

Given('I am on the Google home page', () => {


cy.visit('https://www.google.com/')
})

When('I type New York in the Search field', () => {


cy.get('input[title="Search"]').type('New York')
})

And('I press the Search button', () => {


cy.get('div[class="CqAVzb lJ9FBc"] input[name="btnK"]').click()
})

Then('I should get a page with the correct title', () => {


cy.title().should('eq', 'New York - Google Search')
})

9. You can now run the test, for example with:


npx cypress run

P a g e 35 | 41
Jenkins integration
Cypress can run on many different Continuous Integration servers, such as Jenkins.

Cypress offers a demo web application called “Kitchen Sink” that is available online at
https://example.cypress.io/ . The program code for this demo web application is available at
https://github.com/cypress-io/cypress-example-kitchensink .

There are two demo “Jenkinsfile” for the “Kitchen Sink” application that show how to run Cypress
from Jenkins.

A basic “Jenkinsfile” example is available at https://github.com/cypress-io/cypress-example-


kitchensink/blob/master/basic/Jenkinsfile .

A more advanced “Jenkinsfile” with full parallel configuration (simultaneous execution of tests on
multiple agents/nodes) is available at https://github.com/cypress-io/cypress-example-
kitchensink/blob/master/Jenkinsfile .

Docker
Cypress offers several different pre-configured Docker images with a range of Node versions and
with and without preinstalled browsers: https://github.com/cypress-io/cypress-docker-images . The
Docker images already have the X virtual framebuffer “Xvfb” pre-installed.

If you would like to run Cypress in a Docker container viewable with a Remote Desktop (VNC) client,
then this is great starting point for building your own solution:
https://spin.atomicobject.com/2021/10/14/cypress-running-docker-container/

If you just want to use an already built Docker image viewable with a Remote Desktop (VNC) client,
then check this out:
https://github.com/piopi/cypress-desktop .

P a g e 36 | 41
Reporters
Because Cypress is built on top of the Mocha framework, any reporter built for Mocha can be used
with Cypress.

There are Cypress reporters available for the Junit format, for example:
https://npm.io/package/cypress-junit-reporter .

It is also possible to use multiple Cypress reporters at the same time. Often, users are using the
default “spec” reporter to write to the terminal, but then also generate an actual “junit” report file.

Setup the “cypress-mochawesome-reporter”


Please visit https://npm.io/package/cypress-mochawesome-reporter for details. The following steps
are distilled from these instructions.

1. Install the "cypress-mochawesome-reporter" from command line or terminal:


npm i --save-dev cypress-mochawesome-reporter

2. Add this to the "cypress.json" configuration file:

{
"reporter": "cypress-mochawesome-reporter"
}

3. Add this to the “cypress/support/index.js” file:

import 'cypress-mochawesome-reporter/register'

4. Add this to the “package.json” scripts:

"scripts": {
"cypress:report": "generate-mochawesome-report"
}

Generate the HTML report using the “cypress-mochawesome-reporter”


1. Delete any old report data as described in the next section (“Delete old test results data
before creating a new report”).

2. Run the Cypress tests, for example from command line or terminal with:
“npm run cypress:run”

3. Generate the HTML report from command line or terminal with:


npm run cypress:report

P a g e 37 | 41
4. You can now find the generated HTML report as “index.html” in the
“cypress/reports/html” folder.

Delete old test results data before creating a new report


Old test results data will not automatically get deleted and new test results data will just be added to
the existing test results data. It is therefore usually required to delete old test results data before
any new round of a test execution and reporting.

There are multiple solutions to automate this. One way is to use an operating system command
(such as “rm …”) or batch script to delete all files in the “cypress/results/json” folder.
Another solution is to use a Node module such as “rimraf”, for example:

1. Install “rimraf” with:


npm install --save-dev rimraf

2. Add this to add to the “package.json” scripts:

"scripts": {
"cypress:deleteResults": "rimraf .\\**\\cypress\\results\\json"
},

3. You can now run this script from command line or terminal with:
npm run cypress:deleteResults

P a g e 38 | 41
Intelligent Code Completion in Microsoft Visual Studio Code
There are two ways to get intelligent code completion (“IntelliSense”) in Microsoft Visual Studio.

Option 1: Add “triple slash directives” to every program code page


You can add the following triple slash directive on the top of every page where you want to use
intelligent code completion:

/// <reference types="Cypress" />

Option 2: Add a configuration file


If you automatically want intelligent code completion on all program code pages, then you can add
either a “jsconfig.json” page (for JavaScript), or a “tsconfig.json” page (for TypeScript)
to the root of your project (where the other “*.json” configuration files reside).

“jsconfig.json” (if you use JavaScript)


{
"include": ["./node_modules/cypress", "cypress/**/*.js"]
}

“tsconfig.json” (if you use TypeScript)


{
"compilerOptions": {
"allowJs": true,
"types": ["cypress"]
},
"include": ["**/*.*"]
}

P a g e 39 | 41
Cypress Recorder
The Cypress Recorder is a Google Chrome extension that records user interaction within a web
application and generates Cypress scripts to allow the developer to replicate that particular session.

https://chrome.google.com/webstore/detail/cypress-recorder/glcapdcacdfkokcmicllhcjigeodacab

Features of the Cypress Recorder:

 Record clicks, typing, submits, and navigation in the browser.


 See the scripts render live as they are generated.
 Delete accidental actions.
 Reorder actions as necessary.
 Pause and resume recording within a single session.
 Record navigation within a domain.
 Copy the generated code to your clipboard.

P a g e 40 | 41
Cypress Scenario Recorder
The Cypress Scenario Recorder is another Google Chrome extension that records browser
interactions and generates Cypress scripts. It is based on the Puppeteer recorder, which is no longer
maintained.

https://chrome.google.com/webstore/detail/cypress-scenario-
recorder/fmpgoobcionmfneadjapdabmjfkmfekb

P a g e 41 | 41

You might also like