-
Notifications
You must be signed in to change notification settings - Fork 1k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: add cross origin testing guide
- Loading branch information
1 parent
b725472
commit b3c5c6d
Showing
4 changed files
with
159 additions
and
179 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,148 @@ | ||
--- | ||
title: Cross Origin Testing | ||
--- | ||
|
||
<Alert type="info"> | ||
|
||
<strong class="alert-header"> Note </strong> | ||
|
||
As of Cypress [v12.0.0](https://on.cypress.io/changelog#12-0-0), Cypress has the | ||
capability to visit multiple origins in a single test via the | ||
[cy.origin()](https://on.cypress.io/origin) command! | ||
|
||
</Alert> | ||
|
||
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`](/api/commands/origin) command must be used to execute assertions | ||
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 are the same for both. Cypress automatically handles hosts of the same | ||
superdomain by injecting the | ||
[`document.domain`](https://developer.mozilla.org/en-US/docs/Web/API/Document/domain) | ||
property into the visited `text/html` pages. This is why navigations without the | ||
use of the [`cy.origin()`](/api/commands/origin) command are solely scope to the | ||
same superdomain. | ||
|
||
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: | ||
|
||
- <Icon name="exclamation-triangle" color="red"></Icon> You **cannot** | ||
[visit](/api/commands/visit) two domains of different superdomains in the same | ||
test and continue to interact with the page without the use of the | ||
[`cy.origin`](/api/commands/origin) command. | ||
- <Icon name="check-circle" color="green"></Icon> You **can** | ||
[visit](/api/commands/visit) two or more domains of different origin in | ||
**different** tests without needing [`cy.origin`](/api/commands/origin). | ||
|
||
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 | ||
|
||
``` | ||
┌───────────────────────────────────────────────────────────────────────────────────────┐ | ||
│ href │ | ||
├──────────┬──┬─────────────────────────────────────┬───────────────────────────┬───────┤ | ||
│ protocol │ │ host │ path │ hash │ | ||
│ │ ├──────────────────────────────┬──────┼──────────┬────────────────┤ │ | ||
│ │ │ hostname │ port │ pathname │ search │ │ | ||
| | ├───────────┬──────────────────┤ │ │ │ │ | ||
│ │ │ subdomain │ superdomain (sd) │ │ │ │ │ | ||
| | ├───────────┼─────────┬────────┤ │ ├─┬──────────────┤ │ | ||
│ │ │ │ domain │ TLD │ │ │ │ query │ │ | ||
│ │ │ │ │ │ │ │ │ │ │ | ||
" https: // sub . example . com : 8080 /p/a/t/h ? query=string #hash " | ||
│ │ │ │ │ | ||
│ origin │ | │ │ | ||
├─────────────┬───────────┬─────────────────────────┤ │ │ │ | ||
│ (sd) origin │ │ (sd) origin │ │ │ │ | ||
└─────────────┴───────────┴─────────────────────────┴──────────┴────────────────┴───────┘ | ||
``` | ||
|
||
For practical purposes, this means the following: | ||
|
||
```javascript | ||
it('navigates', () => { | ||
cy.visit('https://www.cypress.io') | ||
cy.visit('https://docs.cypress.io') | ||
cy.get('selector') // yup all good | ||
}) | ||
``` | ||
|
||
```javascript | ||
it('navigates', () => { | ||
cy.visit('https://www.cypress.io') | ||
cy.visit('https://stackoverflow.com') | ||
cy.get('selector') // this will error w/o cy.origin wrap | ||
}) | ||
``` | ||
|
||
```javascript | ||
it('navigates', () => { | ||
cy.visit('https://www.cypress.io') | ||
cy.visit('https://stackoverflow.com') | ||
cy.origin('https://stackoverflow.com', () => { | ||
cy.get('selector') // yup all good | ||
}) | ||
}) | ||
``` | ||
|
||
```javascript | ||
it('navigates', () => { | ||
cy.visit('https://www.cypress.io') | ||
}) | ||
|
||
// split visiting different origin in another test | ||
it('navigates to new origin', () => { | ||
cy.visit('https://stackoverflow.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](/guides/guides/web-security#Different-superdomain-per-test-requires-cy-origin-command). | ||
|
||
#### Other workarounds | ||
|
||
There are other ways of testing the interaction between 2 superdomains. Because | ||
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 a 3rd party service | ||
not under your control. However, there are exceptions! If your organization uses | ||
Single Sign On (SSO) or OAuth then you might involve a 3rd party service other | ||
than your superdomain, which can be safely tested with | ||
[`cy.origin`](/api/commands/origin). | ||
|
||
We've written several other guides specifically about handling this situation. | ||
|
||
- [Best Practices: Visiting external sites](/guides/references/best-practices#Visiting-external-sites) | ||
- [Web Security: Common Workarounds](/guides/guides/web-security#Common-Workarounds) | ||
- [Recipes: Logging In - Single Sign On](/examples/examples/recipes#Logging-In) | ||
- [Guides: Amazon Cognito Authentication](/guides/end-to-end-testing/amazon-cognito-authentication) | ||
- [Guides: Okta Authentication](/guides/end-to-end-testing/okta-authentication) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters