Migrating cy.route()
to cy.intercept()
This guide details how to change your test code to migrate from cy.route()
to cy.intercept()
. cy.server()
and cy.route()
are deprecated in Cypress 6.0.0. In a future release, support for cy.server()
and cy.route()
will be removed.
Please also refer to the full documentation for cy.intercept()
.
Match simple route
In many use cases, you can replace cy.route()
with cy.intercept()
and remove the call to cy.server()
(which is no longer necessary).
// Set up XHR listeners using cy.route()
cy.server()
cy.route('/users').as('getUsers')
cy.route('POST', '/project').as('createProject')
cy.route('PATCH', '/projects/*').as('updateProject')
After
// Intercept HTTP requests
cy.intercept('/users').as('getUsers')
cy.intercept('POST', '/project').as('createProject')
cy.intercept('PATCH', '/projects/*').as('updateProject')
Match against url
and path
The url
argument to cy.intercept()
matches against the full url, as opposed to the url
or path
in cy.route()
. If you’re using the url
argument in cy.intercept()
, you may need to update your code depending on the route you’re trying to match.
// Match XHRs with a path or url of /users
cy.server()
cy.route({
method: 'POST',
url: '/users'
}).as('getUsers')
After
// Match HTTP requests with a path of /users
cy.route({
method: 'POST',
path: '/users'
}).as('getUsers')
// OR
// Match HTTP requests with an exact url of https://example.cypress.io/users
cy.route({
method: 'POST',
url: 'https://example.cypress.io/users'
}).as('getUsers')
cy.wait()
object
The object returned by cy.wait()
is different from intercepted HTTP requests using cy.intercept()
than the object returned from an awaited cy.route()
XHR.
// Wait for XHR from cy.route()
cy.route('POST', '/users').as('createUser')
// ...
cy.wait('@createUser')
.then(({ requestBody, responseBody, status }) => {
expect(status).to.eq(200)
expect(requestBody.firstName).to.eq('Jane')
expect(responseBody.firstName).to.eq('Jane')
})
After
// Wait for intercepted HTTP request
cy.intercept('POST', '/users').as('createUser')
// ...
cy.wait('@createUser')
.then(({ request, response }) => {
expect(response.statusCode).to.eq(200)
expect(request.body.name).to.eq('Jane')
expect(response.body.name).to.eq('Jane')
})
Fixtures
You can stub requests and response with fixture data by defining a fixture
property in the routeHandler
argument for cy.intercept()
.
// Stub response with fixture data using cy.route()
cy.route('GET', '/projects', 'fx:projects')
After
// Stub response with fixture data using cy.intercept()
cy.intercept('GET', '/projects', {
fixture: 'projects'
})
Override route matchers
Unlike cy.route()
, cy.intercept()
currently does not allow you to override a previous response. For more information on this, see #9302 and this blog post. Overriding responses will be added in a future release.
Migrating to Cypress 6.0
This guide details the changes and how to change your code to migrate to Cypress 6.0. See the full changelog for 6.0.
Non-existent element assertions
Key takeway: Use
.should('not.exist')
to assert that an element does not exist in the DOM (not.should('not.be.visible')
, etc).
In previous versions of Cypress, there was a possibility for tests to falsely pass when asserting a negative state on non-existent elements.
For example, in the tests below we want to test that the search dropdown is no longer visible when the search input is blurred because we hide the element in CSS styles. Except in this test, we’ve mistakenly misspelled one of our selectors.
cy.get('input[type=search]').type('Cypress')
cy.get('#dropdown').should('be.visible')
cy.get('input[type=search]').blur()
// below we misspelled "dropdown" in the selector 😞
// the assertions falsely pass in Cypress < 6.0
// and will correctly fail in Cypress 6.0 +
cy.get('#dropdon').should('not.be.visible')
cy.get('#dropdon').should('not.have.class', 'open')
cy.get('#dropdon').should('not.contain', 'Cypress')

In 6.0, these assertions will now correctly fail, telling us that the #dropdon
element doesn’t exist in the DOM.

Assertions on non-existent elements
This fix may cause some breaking changes in your tests if you are relying on assertions such as not.be.visible
or not.contains
to test that the DOM element did not exist in the DOM. This means you’ll need to update your test code to be more specific about your assertions on non-existent elements.
Before Assert that non existent element was not visible
it('test', () => {
// the .modal element is removed from the DOM on click
cy.get('.modal').find('.close').click()
// assertions below pass in < 6.0, but properly fail in 6.0+
cy.get('.modal').should('not.be.visible')
cy.get('.modal').should('not.contain', 'Upgrade')
})
After Assert that non existent element does not exist
it('test', () => {
// the .modal element is removed from the DOM on click
cy.get('.modal').find('.close').click()
// we should instead assert that the element doesn't exist
cy.get('.modal').should('not.exist')
})
Opacity visibility
DOM elements with opacity: 0
style are no longer considered to be visible. This includes elements with an ancestor that has opacity: 0
since a child element can never have a computed opacity greater than that of an ancestor.
Elements where the CSS property (or ancestors) is opacity: 0
are still considered actionable however and any action commands used to interact with the element will perform the action. This matches browser’s implementation on how they regard elements with opacity: 0
.
Assert visibility of opacity: 0
element
Before Failed assertion that opacity: 0
element is not visible.
it('test', () => {
// '.hidden' has 'opacity: 0' style.
// In < 5.0 this assertion would fail
cy.get('.hidden').should('not.be.visible')
})
After Passed assertion that opacity: 0
element is not visible.
it('test', () => {
// '.hidden' has 'opacity: 0' style.
// In 6.0 this assertion will pass
cy.get('.hidden').should('not.be.visible')
})
Perform actions on opacity: 0
element
In all versions of Cypress, you can interact with elements that have opacity: 0
style.
it('test', () => {
// '.hidden' has 'opacity: 0' style.
cy.get('.hidden').click() // ✅ clicks on element
cy.get('.hidden').type('hi') // ✅ types into element
cy.get('.hidden').check() // ✅ checks element
cy.get('.hidden').select('yes') // ✅ selects element
})
cy.wait(alias)
type
cy.route()
is deprecated in 6.0.0. We encourage the use of cy.intercept()
instead. Due to this deprecation, the type yielded by cy.wait(alias)
has changed.
Before Before 6.0.0, cy.wait(alias)
would yield an object of type WaitXHR
.
After In 6.0.0 and onwards, cy.wait(alias)
will yield an object of type Interception
. This matches the new interception object type used for cy.intercept()
.
Restore old behavior
If you need to restore the type behavior prior to 6.0.0 for cy.wait(alias)
, you can declare a global override for cy.wait()
like so:
declare global {
namespace Cypress {
interface Chainable<Subject = any> {
wait(alias: string): Chainable<Cypress.WaitXHR>
}
}
}
—disable-dev-shm-usage
We now pass —disable-dev-shm-usage
to the Chrome browser flags by default. If you’re passing this flag in your plugins
file, you can now remove this code.
Before Passing flag in plugins file.
// cypress/plugins/index.js
module.exports = (on, config) => {
on('before:browser:launch', (browser = {}, launchOptions) => {
if (browser.family === 'chromium' && browser.name !== 'electron') {
launchOptions.args.push('--disable-dev-shm-usage')
}
return launchOptions
})
}
After Remove flag from plugins file.
// cypress/plugins/index.js
module.exports = (on, config) => {}
Restore old behavior
If you need to remove the flag in 6.0.0+, you can follow the workaround documented here: #9242.
Migrating to Cypress 5.0
This guide details the changes and how to change your code to migrate to Cypress 5.0. See the full changelog for 5.0.
Tests retries
Test retries are available in Cypress 5.0. This means that tests can be re-run a number of times before potentially being marked as a failed test. Read the Test Retries doc for more information on how this works and how to turn on test retries.
When test retries are turned on, there will now be a screenshot taken for every failed attempt, so there could potentially be more than 1 screenshot per test failure. Read the Test Retries doc for more information on how this works.
The cypress-plugin-retries
plugin has been deprecated in favor of test retries built into Cypress. There’s guidance below on how to migrate from the cypress-plugin-retries
plugin to Cypress’s built-in test retries.
Configure test retries via the CLI
Before Setting retries with cypress-plugin-retries
via env vars
CYPRESS_RETRIES=2 cypress run
After Setting test retries in Cypress 5.0 via env vars
CYPRESS_RETRIES=2 cypress run
Configure test retries in the configuration file
Before Setting retries with cypress-plugin-retries
via configuration
{
"env":
{
"RETRIES": 2
}
}
After Setting test retries in Cypress 5.0 via configuration
{
"retries": 1
}
runMode
allows you to define the number of test retries when runningcypress run
openMode
allows you to define the number of test retries when runningcypress open
{
"retries": {
"runMode": 1,
"openMode": 3
}
}
Configure test retries per test
Before Setting retries with cypress-plugin-retries
via the test
it('test', () => {
Cypress.currentTest.retries(2)
})
After Setting test retries in Cypress 5.0 via test options
it('allows user to login', {
retries: 2
}, () => {
// ...
})
runMode
allows you to define the number of test retries when runningcypress run
openMode
allows you to define the number of test retries when runningcypress open
it('allows user to login', {
retries: {
runMode: 2,
openMode: 3
}
}, () => {
// ...
})
Module API results
To more accurately reflect result data for runs with test retries, the structure of each run’s runs
array resolved from the Promise
returned from cypress.run()
of the Module API has changed.
Mainly there is a new attempts
Array on each test
which will reflect the result of each test retry.
Before results.runs
Module API results
{
// ...
"runs": [{
// ...
"hooks": [{
"hookId": "h1",
"hookName": "before each",
"title": [ "before each hook" ],
"body": "function () {\n expect(true).to.be["true"];\n}"
}],
// ...
"screenshots": [{
"screenshotId": "8ddmk",
"name": null,
"testId": "r2",
"takenAt": "2020-08-05T08:52:20.432Z",
"path": "User/janelane/my-app/cypress/screenshots/spec.js/test (failed).png",
"height": 720,
"width": 1280
}],
"stats": {
// ...
"wallClockStartedAt": "2020-08-05T08:38:37.589Z",
"wallClockEndedAt": "2018-07-11T17:53:35.675Z",
"wallClockDuration": 1171
},
"tests": [{
"testId": "r2",
"title": [ "test" ],
"state": "failed",
"body": "function () {\n expect(true).to.be["false"];\n}",
"stack": "AssertionError: expected true to be false\n' +
' at Context.eval (...cypress/integration/spec.js:5:21",
"error": "expected true to be false",
"timings": {
"lifecycle": 16,
"test": {...}
},
"failedFromHookId": null,
"wallClockStartedAt": "2020-08-05T08:38:37.589Z",
"wallClockDuration": 1171,
"videoTimestamp": 4486
}],
}],
// ...
}
After results.runs
Module API results
{
// ...
"runs": [{
// ...
"hooks": [{
"hookName": "before each",
"title": [ "before each hook" ],
"body": "function () {\n expect(true).to.be["true"];\n}"
}],
// ...
"stats": {
// ...
"startedAt": "2020-08-05T08:38:37.589Z",
"endedAt": "2018-07-11T17:53:35.675Z",
"duration": 1171
},
"tests": [{
"title": [ "test" ],
"state": "failed",
"body": "function () {\n expect(true).to.be["false"];\n}",
"displayError": "AssertionError: expected true to be false\n' +
' at Context.eval (...cypress/integration/spec.js:5:21",
"attempts": [{
"state": "failed",
"error": {
"message": "expected true to be false",
"name": "AssertionError",
"stack": "AssertionError: expected true to be false\n' +
' at Context.eval (...cypress/integration/spec.js:5:21"
},
"screenshots": [{
"name": null,
"takenAt": "2020-08-05T08:52:20.432Z",
"path": "User/janelane/my-app/cypress/screenshots/spec.js/test (failed).png",
"height": 720,
"width": 1280
}],
"startedAt": "2020-08-05T08:38:37.589Z",
"duration": 1171,
"videoTimestamp": 4486
}]
}],
}],
// ...
}
Cookies whitelist
option renamed
The Cypress.Cookies.defaults()
whitelist
option has been renamed to preserve
to more closely reflect its behavior.
Before whitelist
option
Cypress.Cookies.defaults({
whitelist: 'session_id'
})
After preserve
option
Cypress.Cookies.defaults({
preserve: 'session_id'
})
blacklistHosts
configuration renamed
The blacklistHosts
configuration has been renamed to blockHosts
to more closely reflect its behavior.
This should be updated in all places where Cypress configuration can be set including the via the configuration file (cypress.json
by default), command line arguments, the pluginsFile
, Cypress.config()
or environment variables.
Before blacklistHosts
configuration in cypress.json
{
"blacklistHosts": "www.google-analytics.com"
}
After blockHosts
configuration in cypress.json
{
"blockHosts": "www.google-analytics.com"
}
Return type of Cypress.Blob
changed
We updated the Blob library used behind Cypress.Blob
from 1.3.3
to 2.0.2
.
The return type of the Cypress.Blob
methods arrayBufferToBlob
, base64StringToBlob
, binaryStringToBlob
, and dataURLToBlob
have changed from Promise<Blob>
to Blob
.
Before Cypress.Blob
methods returned a Promise
Cypress.Blob.base64StringToBlob(this.logo, 'image/png')
.then((blob) => {
// work with the returned blob
})
After Cypress.Blob
methods return a Blob
const blob = Cypress.Blob.base64StringToBlob(this.logo, 'image/png')
// work with the returned blob
cy.server()
whitelist
option renamed
The cy.server()
whitelist
option has been renamed to ignore
to more closely reflect its behavior.
Before whitelist
option
cy.server({
whitelist: (xhr) => {
return xhr.method === 'GET' && /\.(jsx?|html|css)(\?.*)?$/.test(xhr.url)
}
})
After ignore
option
cy.server({
ignore: (xhr) => {
return xhr.method === 'GET' && /\.(jsx?|html|css)(\?.*)?$/.test(xhr.url)
}
})
Cookies sameSite
property
Values yielded by cy.setCookie()
, cy.getCookie()
, and cy.getCookies()
will now contain the sameSite
property if specified.
If you were using the experimentalGetCookiesSameSite
configuration to get the sameSite
property previously, this should be removed.
Before Cookies yielded before had no sameSite
property.
cy.getCookie('token').then((cookie) => {
// cy.getCookie() yields a cookie object
// {
// domain: "localhost",
// expiry: 1593551644,
// httpOnly: false,
// name: "token",
// path: "/commands",
// secure: false,
// value: "123ABC"
// }
})
After Cookies yielded now have sameSite
property if specified.
cy.getCookie('token').then((cookie) => {
// cy.getCookie() yields a cookie object
// {
// domain: "localhost",
// expiry: 1593551644,
// httpOnly: false,
// name: "token",
// path: "/commands",
// sameSite: "strict",
// secure: false,
// value: "123ABC"
// }
})
dirname / filename
The globals __dirname
and __filename
no longer include a leading slash.
Before __dirname
/ __filename
// cypress/integration/app_spec.js
it('include leading slash < 5.0', () => {
expect(__dirname).to.equal('/cypress/integration')
expect(__filename).to.equal('/cypress/integration/app_spec.js')
})
After __dirname
/ __filename
// cypress/integration/app_spec.js
it('do not include leading slash >= 5.0', () => {
expect(__dirname).to.equal('cypress/integration')
expect(__filename).to.equal('cypress/integration/app_spec.js')
})
Linux dependencies
Running Cypress on Linux now requires the libgbm
dependency (on Debian-based systems, this is available as libgbm-dev
). To install all required dependencies on Ubuntu/Debian, you can run the script below:
apt-get install libgtk2.0-0 libgtk-3-0 libgbm-dev libnotify-dev libgconf-2-4 libnss3 libxss1 libasound2 libxtst6 xauth xvfb
TypeScript esModuleInterop
Cypress no longer forces the esModuleInterop
compiler option for TypeScript to be true
for spec, support, and plugin files. We recommend setting it in your project’s tsconfig.json
instead if you need to.
// tsconfig.json
{
"compilerOptions": {
"esModuleInterop": true,
/* ... other compiler options ... */
}
}
TypeScript 3.4+ support
Cypress 5.0 raises minimum required TypeScript version from 2.9+ to 3.4+. You’ll need to have TypeScript 3.4+ installed within your project to have TypeScript support within Cypress.
Node.js 10+ support
Cypress comes bundled with it’s own Node.js version. However, installing the cypress
npm package uses the Node.js version installed on your system.
Node.js 8 reached its end of life on Dec 31, 2019 and Node.js 11 reached its end of life on June 1, 2019. See Node’s release schedule. These Node.js versions will no longer be supported when installing Cypress. The minimum Node.js version supported to install Cypress is Node.js 10 or Node.js 12+.
Migrating to Cypress 4.0
This guide details the changes and how to change your code to migrate to Cypress 4.0. See the full changelog for 4.0.
Mocha upgrade
Mocha was upgraded from 2.5.3
to 7.0.1
, which includes a number of breaking changes and new features outlined in their changelog. Some changes you might notice are described below.
Breaking Change: invoke done
callback and return a promise
Starting with Mocha 3.0.0, invoking a done
callback and returning a promise in a test results in an error.
This error originates from Mocha and is discussed at length here and here.
The reason is that using two different ways to signal that a test is finished is usually a mistake and there is always a way to only use one. There is a proposal to handle this situation without erroring that may be released in a future version of Mocha.
In the meantime, you can fix the error by choosing a single way to signal the end of your test’s execution.
Example #1
Before This test has a done callback and a promise
it('uses invokes done and returns promise', (done) => {
return codeUnderTest.doSomethingThatReturnsPromise().then((result) => {
// assertions here
done()
})
})
After You can remove the done
callback and return the promise instead:
it('uses invokes done and returns promise', () => {
return codeUnderTest.doSomethingThatReturnsPromise().then((result) => {
// assertions here
})
})
Example #2
Before Sometimes it might make more sense to use the done
callback and not return a promise:
it('uses invokes done and returns promise', (done) => {
eventEmitter.on('change', () => {
// assertions
done()
})
return eventEmitter.doSomethingThatEmitsChange()
})
After In this case, you don’t need to return the promise:
it('uses invokes done and returns promise', (done) => {
eventEmitter.on('change', () => {
// assertions
done()
})
eventEmitter.doSomethingThatEmitsChange()
})
Example #3
Test functions using async/await
automatically return a promise, so they need to be refactored to not use a done
callback.
Before This will cause an overspecified error.
it('uses async/await', async (done) => {
const eventEmitter = await getEventEmitter()
eventEmitter.on('change', () => done())
eventEmitter.doSomethingThatEmitsChange()
})
After Update to the test code below.
it('uses async/await', async () => {
const eventEmitter = await getEventEmitter()
return new Promise((resolve) => {
eventEmitter.on('change', () => resolve())
eventEmitter.doSomethingThatEmitsChange()
})
})
Tests require a title
Tests now require a title and will error when not provided one.
// Would show as pending in Cypress 3
// Will throw type error in Cypress 4:
it() // Test argument "title" should be a string. Received type "undefined"
Chai upgrade
Chai was upgraded from 3.5.0
to 4.2.0
, which includes a number of breaking changes and new features outlined in Chai’s migration guide. Some changes you might notice are described below.
Breaking Change: assertions expecting numbers
Some assertions will now throw an error if the assertion’s target or arguments are not numbers, including within
, above
, least
, below
, most
, increase
and decrease
.
// These will now throw errors:
expect(null).to.be.within(0, 1)
expect(null).to.be.above(10)
// This will not throw errors:
expect('string').to.have.a.length.of.at.least(3)
Breaking Change: empty
assertions
The .empty
assertion will now throw when it is passed non-string primitives and functions.
// These will now throw TypeErrors
expect(Symbol()).to.be.empty
expect(() => {}).to.be.empty
Breaking Change: non-existent properties
An error will throw when a non-existent property is read. If there are typos in property assertions, they will now appear as failures.
// Would pass in Cypress 3 but will fail correctly in 4
expect(true).to.be.ture
Breaking Change: include
checks strict equality
include
now always use strict equality unless the deep
property is set.
Before include
would always use deep equality
// Would pass in Cypress 3 but will fail correctly in 4
cy.wrap([{
first: 'Jane',
last: 'Lane'
}])
.should('include', {
first: 'Jane',
last: 'Lane'
})
After Need to specificy deep.include
for deep equality
// Specifically check for deep.include to pass in Cypress 4
cy.wrap([{
first: 'Jane',
last: 'Lane'
}])
.should('deep.include', {
first: 'Jane',
last: 'Lane'
})
Sinon.JS upgrade
Sinon.JS was upgraded from 3.2.0
to 8.1.1
, which includes a number of breaking changes and new features outlined in Sinon.JS’s migration guide. Some changes you might notice are described below.
Breaking Change: stub non-existent properties
An error will throw when trying to stub a non-existent property.
// Would pass in Cypress 3 but will fail in 4
cy.stub(obj, 'nonExistingProperty')
Breaking Change: reset()
replaced by resetHistory()
For spies and stubs, the reset()
method was replaced by resetHistory()
.
Before Spies and stubs using reset()
.
const spy = cy.spy()
const stub = cy.stub()
spy.reset()
stub.reset()
After Update spies and stubs should now use resetHistory()
.
const spy = cy.spy()
const stub = cy.stub()
spy.resetHistory()
stub.resetHistory()
Plugin Event before:browser:launch
Since we now support more advanced browser launch options, during before:browser:launch
we no longer yield the second argument as an array of browser arguments and instead yield a launchOptions
object with an args
property.
You can see more examples of the new launchOptions
in use in the Browser Launch API doc.
Before The second argument is no longer an array.
on('before:browser:launch', (browser, args) => {
// will print a deprecation warning telling you
// to change your code to the new signature
args.push('--another-arg')
return args
})
After Access the args
property off launchOptions
on('before:browser:launch', (browser, launchOptions) => {
launchOptions.args.push('--another-arg')
return launchOptions
})
Electron options in before:browser:launch
Previously, you could pass options to the launched Electron BrowserWindow in before:browser:launch
by modifying the launchOptions
object.
Now, you must pass those options as launchOptions.preferences
:
Before Passing BrowserWindow options on the launchOptions
object is no longer supported.
on('before:browser:launch', (browser, args) => {
args.darkTheme = true
return args
})
After Pass BrowserWindow options on the options.preferences
object instead.
on('before:browser:launch', (browser, launchOptions) => {
launchOptions.preferences.darkTheme = true
return launchOptions
})
Launching Chrome Canary with --browser
Before 4.0, cypress run --browser canary
would run tests in Chrome Canary.
Now, you must pass --browser chrome:canary
to select Chrome Canary.
See the docs for cypress run --browser
for more information.
Before Passing canary
will no longer find a browser
cypress run --browser canary
After Pass chrome:canary
to launch Chrome Canary
cypress run --browser chrome:canary
Chromium-based browser family
We updated the Cypress browser objects of all Chromium-based browsers, including Electron, to have chromium
set as their family
field.
module.exports = (on, config) => {
on('before:browser:launch', (browser = {}, launchOptions) => {
if (browser.family === 'electron') {
// would match Electron in 3.x
// will match no browsers in 4.0.0
return launchOptions
}
if (browser.family === 'chromium') {
// would match no browsers in 3.x
// will match any Chromium-based browser in 4.0.0
// ie Chrome, Canary, Chromium, Electron, Edge (Chromium-based)
return launchOptions
}
})
}
Example #1 (Finding Electron)
Before This will no longer find the Electron browser.
module.exports = (on, config) => {
on('before:browser:launch', (browser = {}, args) => {
if (browser.family === 'electron') {
// run code for Electron browser in 3.x
return args
}
})
}
After Use browser.name
to check for Electron
module.exports = (on, config) => {
on('before:browser:launch', (browser = {}, launchOptions) => {
if (browser.name === 'electron') {
// run code for Electron browser in 4.0.0
return launchOptions
}
})
}
Example #2 (Finding Chromium-based browsers)
Before This will no longer find any browsers.
module.exports = (on, config) => {
on('before:browser:launch', (browser = {}, args) => {
if (browser.family === 'chrome') {
// in 4.x, `family` was changed to 'chromium' for all Chromium-based browsers
return args
}
})
}
After Use browser.name
and browser.family
to select non-Electron Chromium-based browsers
module.exports = (on, config) => {
on('before:browser:launch', (browser = {}, launchOptions) => {
if (browser.family === 'chromium' && browser.name !== 'electron') {
// pass launchOptions to Chromium-based browsers in 4.0
return launchOptions
}
})
}
cy.writeFile()
yields null
cy.writeFile()
now yields null
instead of the contents
written to the file. This change was made to more closely align with the behavior of Node.js fs.writeFile
.
Before This assertion will no longer pass
cy.writeFile('path/to/message.txt', 'Hello World')
.then((text) => {
// Would pass in Cypress 3 but will fail in 4
expect(text).to.equal('Hello World') // false
})
After Instead read the contents of the file
cy.writeFile('path/to/message.txt', 'Hello World')
cy.readFile('path/to/message.txt').then((text) => {
expect(text).to.equal('Hello World') // true
})
cy.contains() ignores invisible whitespaces
Browsers ignore leading, trailing, duplicate whitespaces. And Cypress now does that, too.
<p>hello
world</p>
cy.get('p').contains('hello world') // Fail in 3.x. Pass in 4.0.0.
cy.get('p').contains('hello\nworld') // Pass in 3.x. Fail in 4.0.0.
Node.js 8+ support
Cypress comes bundled with it’s own Node.js version. However, installing the cypress
npm package uses the Node.js version installed on your system.
Node.js 4 reached its end of life on April 30, 2018 and Node.js 6 reached its end of life on April 30, 2019. See Node’s release schedule. These Node.js versions will no longer be supported when installing Cypress. The minimum Node.js version supported to install Cypress is Node.js 8.
CJSX is no longer supported
Cypress no longer supports CJSX (CoffeeScript + JSX), because the library used to transpile it is no longer maintained.
If you need CJSX support, you can use a pre-2.x version of the Browserify preprocessor.
npm install @cypress/[email protected]
// cypress/plugins/index.js
const browserify = require('@cypress/browserify-preprocessor')
module.exports = (on) => {
on('file:preprocessor', browserify())
}