Skip to content

Commit

Permalink
chore: [Multi-origin] Correctly find the spec bridge if chromeWebSecu…
Browse files Browse the repository at this point in the history
…rity set to false. (#21117)

* chore: [Multi-origin] Correctly find the spec bridge if chromeWebSecurity set to false.

* Update packages/runner/injection/multi-domain.js

Co-authored-by: Chris Breiding <chrisbreiding@users.noreply.github.com>

* Attempting a system test

Co-authored-by: Chris Breiding <chrisbreiding@users.noreply.github.com>
  • Loading branch information
mjhenkes and chrisbreiding authored Apr 18, 2022
1 parent 890bde6 commit f02d750
Show file tree
Hide file tree
Showing 5 changed files with 92 additions and 52 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -198,6 +198,15 @@ describe('cy.origin', () => {
.should('equal', 'Welcome TJohnson')
})

it('finds the correct spec bridge even if a previous spec bridge host is a subset of the current host', () => {
// Establish a spec bridge with a 'bar.com' host prior to loading 'foobar.com'
cy.origin('http://www.bar.com:3500', () => undefined)

cy.origin('http://www.app.foobar.com:3500', () => {
cy.visit('/fixtures/multi-domain.html')
})
})

it('uses cy.origin twice', () => {
cy.visit('/fixtures/auth/index.html')
cy.get('[data-cy="login-idp"]').click()
Expand Down
13 changes: 12 additions & 1 deletion packages/runner/injection/multi-domain.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,18 @@ const findCypress = () => {
try {
// If Cypress is defined and we haven't gotten a cross origin error we have found the correct bridge.
if (frame.Cypress) {
return frame.Cypress
// If the ending $ is included in the template string, it breaks transpilation
// eslint-disable-next-line no-useless-concat
const frameHostRegex = new RegExp(`(^|\\.)${ frame.location.host.replaceAll('.', '\\.') }` + '$')

// Compare the locations origin policy without pulling in more dependencies.
// Compare host, protocol and test that the window's host ends with the frame's host.
// This works because the spec bridge's host is always created without a sub domain.
if (window.location.port === frame.location.port
&& window.location.protocol === frame.location.protocol
&& frameHostRegex.test(window.location.host)) {
return frame.Cypress
}
}
} catch (error) {
// Catch DOMException: Blocked a frame from accessing a cross-origin frame.
Expand Down
106 changes: 55 additions & 51 deletions system-tests/__snapshots__/web_security_spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,11 @@ exports['e2e web security / when enabled / fails'] = `
(Run Starting)
┌────────────────────────────────────────────────────────────────────────────────────────────────┐
│ Cypress: 1.2.3 │
│ Browser: FooBrowser 88 │
│ Specs: 1 found (web_security_spec.js) │
│ Searched: cypress/integration/web_security_spec.js │
│ Cypress: 1.2.3 │
│ Browser: FooBrowser 88 │
│ Specs: 1 found (web_security_spec.js) │
│ Searched: cypress/integration/web_security_spec.js │
│ Experiments: experimentalSessionAndOrigin=true │
└────────────────────────────────────────────────────────────────────────────────────────────────┘
Expand All @@ -22,78 +23,79 @@ exports['e2e web security / when enabled / fails'] = `
2) fails when submitted a form and being redirected to another origin
3) fails when using a javascript redirect to another origin
4) fails when doing a CORS request cross-origin
✓ finds the correct spec bridge even if a previous spec bridge host is a subset of the current host
0 passing
1 passing
4 failing
1) web security
fails when clicking <a> to another origin:
CypressError: Cypress detected a cross origin error happened on page load:
CypressError: Timed out after waiting \`5000ms\` for your remote page to load on origin(s):
> [Cross origin error message]
- \`http://localhost:4466\`
Before the page load, you were bound to the origin policy:
A cross-origin request for \`https://www.foo.com:44665/cross_origin\` was detected.
> http://localhost:4466
A command that triggers cross-origin navigation must be immediately followed by a \`cy.origin()\` command:
A cross origin error happens when your application navigates to a new URL which does not match the origin policy above.
\`cy.origin('https://foo.com:44665', () => {\`
\` <commands targeting https://www.foo.com:44665 go here>\`
\`})\`
A new URL does not match the origin policy if the 'protocol', 'port' (if specified), and/or 'host' (unless of the same superdomain) are different.
If the cross-origin request was an intermediary state, you can try increasing the \`pageLoadTimeout\` value in \`cypress.json\` to wait longer.
Cypress does not allow you to navigate to a different origin URL within a single test.
Browsers will not fire the \`load\` event until all stylesheets and scripts are done downloading.
You may need to restructure some of your test code to avoid this problem.
When this \`load\` event occurs, Cypress will continue running commands.
Alternatively you can also disable Chrome Web Security in Chromium-based browsers which will turn off this restriction by setting { chromeWebSecurity: false } in \`cypress.json\`.
https://on.cypress.io/cross-origin-violation
https://on.cypress.io/origin
[stack trace lines]
2) web security
fails when submitted a form and being redirected to another origin:
CypressError: Cypress detected a cross origin error happened on page load:
> [Cross origin error message]
CypressError: Timed out after waiting \`5000ms\` for your remote page to load on origin(s):
Before the page load, you were bound to the origin policy:
- \`http://localhost:4466\`
> http://localhost:4466
A cross-origin request for \`https://www.foo.com:44665/cross_origin\` was detected.
A cross origin error happens when your application navigates to a new URL which does not match the origin policy above.
A command that triggers cross-origin navigation must be immediately followed by a \`cy.origin()\` command:
A new URL does not match the origin policy if the 'protocol', 'port' (if specified), and/or 'host' (unless of the same superdomain) are different.
\`cy.origin('https://foo.com:44665', () => {\`
\` <commands targeting https://www.foo.com:44665 go here>\`
\`})\`
Cypress does not allow you to navigate to a different origin URL within a single test.
If the cross-origin request was an intermediary state, you can try increasing the \`pageLoadTimeout\` value in \`cypress.json\` to wait longer.
You may need to restructure some of your test code to avoid this problem.
Browsers will not fire the \`load\` event until all stylesheets and scripts are done downloading.
Alternatively you can also disable Chrome Web Security in Chromium-based browsers which will turn off this restriction by setting { chromeWebSecurity: false } in \`cypress.json\`.
When this \`load\` event occurs, Cypress will continue running commands.
https://on.cypress.io/cross-origin-violation
https://on.cypress.io/origin
[stack trace lines]
3) web security
fails when using a javascript redirect to another origin:
CypressError: Cypress detected a cross origin error happened on page load:
CypressError: Timed out after waiting \`5000ms\` for your remote page to load on origin(s):
> [Cross origin error message]
- \`http://localhost:4466\`
Before the page load, you were bound to the origin policy:
A cross-origin request for \`https://www.foo.com:44665/cross_origin\` was detected.
> http://localhost:4466
A command that triggers cross-origin navigation must be immediately followed by a \`cy.origin()\` command:
A cross origin error happens when your application navigates to a new URL which does not match the origin policy above.
\`cy.origin('https://foo.com:44665', () => {\`
\` <commands targeting https://www.foo.com:44665 go here>\`
\`})\`
A new URL does not match the origin policy if the 'protocol', 'port' (if specified), and/or 'host' (unless of the same superdomain) are different.
If the cross-origin request was an intermediary state, you can try increasing the \`pageLoadTimeout\` value in \`cypress.json\` to wait longer.
Cypress does not allow you to navigate to a different origin URL within a single test.
Browsers will not fire the \`load\` event until all stylesheets and scripts are done downloading.
You may need to restructure some of your test code to avoid this problem.
When this \`load\` event occurs, Cypress will continue running commands.
Alternatively you can also disable Chrome Web Security in Chromium-based browsers which will turn off this restriction by setting { chromeWebSecurity: false } in \`cypress.json\`.
https://on.cypress.io/cross-origin-violation
https://on.cypress.io/origin
[stack trace lines]
4) web security
Expand All @@ -107,8 +109,8 @@ https://on.cypress.io/cross-origin-violation
(Results)
┌────────────────────────────────────────────────────────────────────────────────────────────────┐
│ Tests: 4
│ Passing: 0
│ Tests: 5
│ Passing: 1
│ Failing: 4 │
│ Pending: 0 │
│ Skipped: 0 │
Expand Down Expand Up @@ -144,9 +146,9 @@ https://on.cypress.io/cross-origin-violation
Spec Tests Passing Failing Pending Skipped
┌────────────────────────────────────────────────────────────────────────────────────────────────┐
│ ✖ web_security_spec.js XX:XX 4 - 4 - - │
│ ✖ web_security_spec.js XX:XX 5 1 4 - - │
└────────────────────────────────────────────────────────────────────────────────────────────────┘
✖ 1 of 1 failed (100%) XX:XX 4 - 4 - -
✖ 1 of 1 failed (100%) XX:XX 5 1 4 - -
`
Expand All @@ -158,10 +160,11 @@ exports['e2e web security / when disabled / passes'] = `
(Run Starting)
┌────────────────────────────────────────────────────────────────────────────────────────────────┐
│ Cypress: 1.2.3 │
│ Browser: FooBrowser 88 │
│ Specs: 1 found (web_security_spec.js) │
│ Searched: cypress/integration/web_security_spec.js │
│ Cypress: 1.2.3 │
│ Browser: FooBrowser 88 │
│ Specs: 1 found (web_security_spec.js) │
│ Searched: cypress/integration/web_security_spec.js │
│ Experiments: experimentalSessionAndOrigin=true │
└────────────────────────────────────────────────────────────────────────────────────────────────┘
Expand All @@ -175,16 +178,17 @@ exports['e2e web security / when disabled / passes'] = `
✓ fails when submitted a form and being redirected to another origin
✓ fails when using a javascript redirect to another origin
✓ fails when doing a CORS request cross-origin
✓ finds the correct spec bridge even if a previous spec bridge host is a subset of the current host
4 passing
5 passing
(Results)
┌────────────────────────────────────────────────────────────────────────────────────────────────┐
│ Tests: 4
│ Passing: 4
│ Tests: 5
│ Passing: 5
│ Failing: 0 │
│ Pending: 0 │
│ Skipped: 0 │
Expand All @@ -208,9 +212,9 @@ exports['e2e web security / when disabled / passes'] = `
Spec Tests Passing Failing Pending Skipped
┌────────────────────────────────────────────────────────────────────────────────────────────────┐
│ ✔ web_security_spec.js XX:XX 4 4 - - - │
│ ✔ web_security_spec.js XX:XX 5 5 - - - │
└────────────────────────────────────────────────────────────────────────────────────────────────┘
✔ All specs passed! XX:XX 4 4 - - -
✔ All specs passed! XX:XX 5 5 - - -
`
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,4 +24,13 @@ describe('web security', function () {
cy.visit('http://localhost:4466/cors')
.contains('success!', { timeout: 500 })
})

it('finds the correct spec bridge even if a previous spec bridge host is a subset of the current host', () => {
// Establish a spec bridge with a 'bar.com' host prior to loading 'foobar.com'
cy.origin('http://www.bar.com:4466', () => undefined)

cy.origin('http://www.app.foobar.com:4466', () => {
cy.visit('/link')
})
})
})
7 changes: 7 additions & 0 deletions system-tests/test/web_security_spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -63,13 +63,19 @@ describe('e2e web security', () => {
settings: {
hosts: {
'*.foo.com': '127.0.0.1',
'*.bar.com': '127.0.0.1',
'*.foobar.com': '127.0.0.1',
},
},
})

context('when enabled', () => {
systemTests.it('fails', {
spec: 'web_security_spec.js',
config: {
experimentalSessionAndOrigin: true,
pageLoadTimeout: 5000,
},
snapshot: true,
expectedExitCode: 4,
})
Expand All @@ -80,6 +86,7 @@ describe('e2e web security', () => {
spec: 'web_security_spec.js',
config: {
chromeWebSecurity: false,
experimentalSessionAndOrigin: true,
},
snapshot: true,
browser: ['chrome', 'electron'],
Expand Down

2 comments on commit f02d750

@cypress-bot
Copy link
Contributor

@cypress-bot cypress-bot bot commented on f02d750 Apr 18, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Circle has built the darwin x64 version of the Test Runner.

Learn more about this pre-release platform-specific build at https://on.cypress.io/installing-cypress#Install-pre-release-version.

Run this command to install the pre-release locally:

npm install https://cdn.cypress.io/beta/npm/9.6.0/darwin-x64/feature-multidomain-f02d7509b07bf715a8c1a32ab06f1295abc65112/cypress.tgz

@cypress-bot
Copy link
Contributor

@cypress-bot cypress-bot bot commented on f02d750 Apr 18, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Circle has built the win32 x64 version of the Test Runner.

Learn more about this pre-release platform-specific build at https://on.cypress.io/installing-cypress#Install-pre-release-version.

Run this command to install the pre-release locally:

npm install https://cdn.cypress.io/beta/npm/9.6.0/win32-x64/feature-multidomain-f02d7509b07bf715a8c1a32ab06f1295abc65112/cypress.tgz

Please sign in to comment.