-
Notifications
You must be signed in to change notification settings - Fork 1.1k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Documentation updates for v12 #4880
Changes from all commits
9c0d2ce
72a55a3
0af2761
efb1390
6615dcd
5df7fdd
356853d
d24098b
757e6b3
c71644c
b725472
b3c5c6d
65db437
5ed169d
2080412
a1c9e8b
9d132e9
9381771
ee157c7
ae995ec
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
@@ -0,0 +1,152 @@ | ||||||||||||||||||||||||||||||||||||
--- | ||||||||||||||||||||||||||||||||||||
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 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`](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. | ||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||
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 │ │ │ │ | ||||||||||||||||||||||||||||||||||||
└─────────────┴───────────┴─────────────────────────┴──────────┴────────────────┴───────┘ | ||||||||||||||||||||||||||||||||||||
``` | ||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||
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) | ||||||||||||||||||||||||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. what is the default port when one isn't explicitly called out in a url? is there one? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. usually |
||||||||||||||||||||||||||||||||||||
- `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: | ||||||||||||||||||||||||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Maybe There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The rules should still apply even without |
||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||
- <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). | ||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||
For practical purposes, this means the following: | ||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||
```javascript | ||||||||||||||||||||||||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This test will run without error: There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. addressed in a1c9e8b |
||||||||||||||||||||||||||||||||||||
// 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 | ||||||||||||||||||||||||||||||||||||
}) | ||||||||||||||||||||||||||||||||||||
``` | ||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||
```javascript | ||||||||||||||||||||||||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The following test changes super-domain mid-test and results in an error after navigation: |
||||||||||||||||||||||||||||||||||||
// this will error because stackoverflow.com doesn't match the cypress.io superdomain | ||||||||||||||||||||||||||||||||||||
it('navigates', () => { | ||||||||||||||||||||||||||||||||||||
cy.visit('https://www.cypress.io') | ||||||||||||||||||||||||||||||||||||
cy.visit('https://stackoverflow.com') | ||||||||||||||||||||||||||||||||||||
cy.get('selector') | ||||||||||||||||||||||||||||||||||||
}) | ||||||||||||||||||||||||||||||||||||
``` | ||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||
To fix the above cross-origin error, use `cy.origin()` to indicate which origin | ||||||||||||||||||||||||||||||||||||
the sequential command should run against: | ||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||
```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 | ||||||||||||||||||||||||||||||||||||
}) | ||||||||||||||||||||||||||||||||||||
}) | ||||||||||||||||||||||||||||||||||||
Comment on lines
+105
to
+112
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. addressed in a1c9e8b. I didn't implement the diff because the contract looks strange next to the other javascript snippets, but added the explainer |
||||||||||||||||||||||||||||||||||||
``` | ||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We should move this passing example to be the second example? The following tests will success without issue because each test visits a unique superdomain: There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I don't think so. I don't think this is a pattern we usually want to encourage, but we want to showcase the exception and let users see if its applicable to their use case or not There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I guess not so much discourage but just not common I think |
||||||||||||||||||||||||||||||||||||
```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 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 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) | ||||||||||||||||||||||||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Can we add Auth0 guide here plz There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. yep I'll do a follow up to address these comments! |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This statement feels like it counters the above statement
I assume you're trying to something like: "by default, cypress runs the commands in a test agains a single origin".
(or is is super domain? this always confuses me since its cy.origin not cy.superdomain)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
it's confusing, but it is superdomain. Once its outside of same superdomain, you have to use
origin()
, which we want an exact match of the said origin and not the origins superdomain. Not exactly easy to digest, but I think what we have gives a pretty good summary.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Without the full context I think it does counter it, but the next sentence
If a navigation occurs that does not meet the same superdomain rule, the [cy.origin](/api/commands/origin) command must be used to execute Cypress commands inside the newly navigated origin.
I feel like addresses that explanation