Cross Origin Testing
As of Cypress v12.0.0, Cypress has the capability to visit multiple origins in a single test via the cy.origin() command!
Cypress limits each test to visiting domains that share the same superdomain. If
a navigation occurs that does not meet the same superdomain rule, the
cy.origin()
command must be used to execute Cypress
commands inside the newly navigated origin.
But what is same superdomain? It is actually very similar to that of same
origin! Two URLs have the same origin if the protocol, port (if specified), and
host match. Cypress automatically handles hosts of the same superdomain by
injecting the
document.domain
property into the visited text/html
pages. This is why navigations without the
use of the cy.origin()
command are solely scope to the
same superdomain.
Disabling document.domain Injection
In some cases, document.domain
injection may cause issues. As of Cypress
v12.4.0, disabling document.domain
injection is available with the experimentalSkipDomainInjection
option. Please
read about this
experiment
for more information
We understand this is a bit complicated to understand, so we have built a nifty chart to help clarify the differences!
Parts of a URL​
Given the URLs below, all have the same superdomain compared to
https://www.cypress.io
.
https://cypress.io
https://docs.cypress.io
https://example.cypress.io/commands/querying
The URLs below, however, will have different superdomains/origins compared to
https://www.cypress.io
.
http://www.cypress.io
(Different protocol)https://docs.cypress.io:81
(Different port)https://www.auth0.com/
(Different host of different superdomain)
The http://localhost
URLs differ if their ports are different. For example,
the http://localhost:3000
URL is considered to be a different origin from the
http://localhost:8080
URL.
The rules are:
- You cannot visit
two domains of different superdomains in the same test and continue to interact
with the page without the use of the
cy.origin()
command. - You can visit
two or more domains of different origin in different tests without needing
cy.origin()
.
For practical purposes, this means the following:
// This test will run without error
it('navigates', () => {
cy.visit('https://www.cypress.io')
cy.visit('https://docs.cypress.io')
cy.get('selector') // yup all good
})
// this will error because cypress-dx.com doesn't match the cypress.io superdomain
it('navigates', () => {
cy.visit('https://www.cypress.io')
cy.visit('https://www.cypress-dx.com')
cy.get('selector')
})
To fix the above cross-origin error, use cy.origin()
to indicate which origin
the sequential command should run against:
it('navigates', () => {
cy.visit('https://example.cypress.io')
cy.visit('https://www.cypress-dx.com')
cy.origin('https://www.cypress-dx.com', () => {
cy.get('selector') // yup all good
})
})
it('navigates', () => {
cy.visit('https://www.cypress.io')
})
// split visiting different origin in another test
it('navigates to new origin', () => {
cy.visit('https://cypress-dx.com')
cy.get('selector') // yup all good
})
This limitation exists because Cypress switches to the domain under each specific test when it runs. For more information on this, please see our Web Security page regarding Different superdomain per test requires cy.origin command.
Other workarounds​
There are other ways of testing the interaction between two superdomains. The
browser has a natural security barrier called origin policy
this means that
state like localStorage
, cookies
, service workers
and many other APIs are
not shared between them anyways. Cypress does offer APIs around localStorage
,
sessionStorage
, and cookies
that are not limited to this restriction.
As a best practice, you should not visit or interact with any website not under your control.
If your organization uses Single Sign On (SSO) or OAuth then you might choose to
test a 3rd party service other than your superdomain, which can be tested with
cy.origin()
.
We've written several other guides specifically about handling this situation.