Skip to content
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

feat: same origin spec bridges #23885

Merged
merged 11 commits into from
Oct 4, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ describe('./lib/cross-origin-callback-loader', () => {

it('is a noop when cy.origin() callback does not contain Cypress.require()', () => {
const source = `it('test', () => {
cy.origin('http://foobar.com:3500', () => {})
cy.origin('http://www.foobar.com:3500', () => {})
})`
const { originalMap, resultingSource, resultingMap, store } = callLoader(source)

Expand All @@ -74,7 +74,7 @@ describe('./lib/cross-origin-callback-loader', () => {

it('is a noop when last argument to cy.origin() is not a callback', () => {
const source = `it('test', () => {
cy.origin('http://foobar.com:3500', {})
cy.origin('http://www.foobar.com:3500', {})
})`
const { originalMap, resultingSource, resultingMap, store } = callLoader(source)

Expand All @@ -93,14 +93,14 @@ describe('./lib/cross-origin-callback-loader', () => {
it('replaces cy.origin() callback with an object', () => {
const { resultingSource, resultingMap } = callLoader(stripIndent`
it('test', () => {
cy.origin('http://foobar.com:3500', () => {
cy.origin('http://www.foobar.com:3500', () => {
Cypress.require('../support/utils')
})
})`)

expect(resultingSource).to.equal(stripIndent`
it('test', () => {
cy.origin('http://foobar.com:3500', {
cy.origin('http://www.foobar.com:3500', {
"callbackName": "__cypressCrossOriginCallback",
"outputFilePath": "/path/to/tmp/cross-origin-cb-abc123.js"
});
Expand All @@ -112,15 +112,15 @@ describe('./lib/cross-origin-callback-loader', () => {
it('replaces cy.other() when specified in commands', () => {
const { resultingSource, resultingMap } = callLoader(stripIndent`
it('test', () => {
cy.other('http://foobar.com:3500', () => {
cy.other('http://www.foobar.com:3500', () => {
Cypress.require('../support/utils')
})
})`,
['other'])

expect(resultingSource).to.equal(stripIndent`
it('test', () => {
cy.other('http://foobar.com:3500', {
cy.other('http://www.foobar.com:3500', {
"callbackName": "__cypressCrossOriginCallback",
"outputFilePath": "/path/to/tmp/cross-origin-cb-abc123.js"
});
Expand All @@ -132,7 +132,7 @@ describe('./lib/cross-origin-callback-loader', () => {
it('adds the file to the store, replacing Cypress.require() with require()', () => {
const { store } = callLoader(
`it('test', () => {
cy.origin('http://foobar.com:3500', () => {
cy.origin('http://www.foobar.com:3500', () => {
Cypress.require('../support/utils')
})
})`,
Expand All @@ -148,7 +148,7 @@ describe('./lib/cross-origin-callback-loader', () => {
it('works when callback is a function expression', () => {
const { store } = callLoader(
`it('test', () => {
cy.origin('http://foobar.com:3500', function () {
cy.origin('http://www.foobar.com:3500', function () {
Cypress.require('../support/utils')
})
})`,
Expand All @@ -163,7 +163,7 @@ describe('./lib/cross-origin-callback-loader', () => {
it('works when dep is not assigned to a variable', () => {
const { store } = callLoader(
`it('test', () => {
cy.origin('http://foobar.com:3500', () => {
cy.origin('http://www.foobar.com:3500', () => {
Cypress.require('../support/utils')
})
})`,
Expand All @@ -178,7 +178,7 @@ describe('./lib/cross-origin-callback-loader', () => {
it('works when dep is assigned to a variable', () => {
const { store } = callLoader(
`it('test', () => {
cy.origin('http://foobar.com:3500', () => {
cy.origin('http://www.foobar.com:3500', () => {
const utils = Cypress.require('../support/utils')
utils.foo()
})
Expand All @@ -196,7 +196,7 @@ describe('./lib/cross-origin-callback-loader', () => {
it('works with multiple Cypress.require()s', () => {
const { store } = callLoader(
`it('test', () => {
cy.origin('http://foobar.com:3500', () => {
cy.origin('http://www.foobar.com:3500', () => {
Cypress.require('../support/commands')
const utils = Cypress.require('../support/utils')
const _ = Cypress.require('lodash')
Expand All @@ -219,7 +219,7 @@ describe('./lib/cross-origin-callback-loader', () => {
`it('test', () => {
cy
.wrap({})
.origin('http://foobar.com:3500', () => {
.origin('http://www.foobar.com:3500', () => {
Cypress.require('../support/commands')
})
})`,
Expand All @@ -234,7 +234,7 @@ describe('./lib/cross-origin-callback-loader', () => {
it('works when result of require() is invoked', () => {
const { store } = callLoader(
`it('test', () => {
cy.origin('http://foobar.com:3500', () => {
cy.origin('http://www.foobar.com:3500', () => {
const someVar = 'someValue'
const result = Cypress.require('./fn')(someVar)
expect(result).to.equal('mutated someVar')
Expand All @@ -255,7 +255,7 @@ describe('./lib/cross-origin-callback-loader', () => {
it('works when dependencies passed into called', () => {
const { store } = callLoader(
`it('test', () => {
cy.origin('http://foobar.com:3500', { args: { foo: 'foo'}}, ({ foo }) => {
cy.origin('http://www.foobar.com:3500', { args: { foo: 'foo'}}, ({ foo }) => {
const result = Cypress.require('./fn')(foo)
expect(result).to.equal('mutated someVar')
})
Expand Down
8 changes: 4 additions & 4 deletions packages/app/src/runner/aut-iframe.ts
Original file line number Diff line number Diff line change
Expand Up @@ -92,9 +92,9 @@ export class AutIframe {
}

/**
* If the AUT is cross origin relative to top, a security error is thrown and the method returns false
* If the AUT is cross origin relative to top and chromeWebSecurity is false, origins of the AUT and top need to be compared and returns false
* Otherwise, if top and the AUT match origins, the method returns true.
* If the AUT is cross super domain origin relative to top, a security error is thrown and the method returns false
* If the AUT is cross super domain origin relative to top and chromeWebSecurity is false, origins of the AUT and top need to be compared and returns false
* Otherwise, if top and the AUT match super domain origins, the method returns true.
* If the AUT origin is "about://blank", that means the src attribute has been stripped off the iframe and is adhering to same origin policy
*/
doesAUTMatchTopSuperDomainOrigin = () => {
AtofStryker marked this conversation as resolved.
Show resolved Hide resolved
Expand Down Expand Up @@ -163,7 +163,7 @@ export class AutIframe {
})

// The iframe is in a cross origin state.
// Remove the src attribute to adhere to same super domain origin policy so we can interact with the frame. NOTE: This should only be done ONCE.
// Remove the src attribute to adhere to same super domain origin so we can interact with the frame. NOTE: This should only be done ONCE.
this.removeSrcAttribute()

return
Expand Down
20 changes: 10 additions & 10 deletions packages/app/src/runner/event-manager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -611,8 +611,8 @@ export class EventManager {
})

// Reflect back to the requesting origin the status of the 'duringUserTestExecution' state
Cypress.primaryOriginCommunicator.on('sync:during:user:test:execution', ({ specBridgeResponseEvent }, superDomainOrigin) => {
Cypress.primaryOriginCommunicator.toSpecBridge(superDomainOrigin, specBridgeResponseEvent, cy.state('duringUserTestExecution'))
Cypress.primaryOriginCommunicator.on('sync:during:user:test:execution', ({ specBridgeResponseEvent }, origin) => {
Cypress.primaryOriginCommunicator.toSpecBridge(origin, specBridgeResponseEvent, cy.state('duringUserTestExecution'))
})

Cypress.on('request:snapshot:from:spec:bridge', ({ log, name, options, specBridge, addSnapshot }: {
Expand Down Expand Up @@ -653,22 +653,22 @@ export class EventManager {
Cypress.primaryOriginCommunicator.toAllSpecBridges('before:unload', origin)
})

Cypress.primaryOriginCommunicator.on('expect:origin', (superDomainOrigin) => {
this.localBus.emit('expect:origin', superDomainOrigin)
Cypress.primaryOriginCommunicator.on('expect:origin', (origin) => {
this.localBus.emit('expect:origin', origin)
})

Cypress.primaryOriginCommunicator.on('viewport:changed', (viewport, superDomainOrigin) => {
Cypress.primaryOriginCommunicator.on('viewport:changed', (viewport, origin) => {
const callback = () => {
Cypress.primaryOriginCommunicator.toSpecBridge(superDomainOrigin, 'viewport:changed:end')
Cypress.primaryOriginCommunicator.toSpecBridge(origin, 'viewport:changed:end')
}

Cypress.primaryOriginCommunicator.emit('sync:viewport', viewport)
this.localBus.emit('viewport:changed', viewport, callback)
})

Cypress.primaryOriginCommunicator.on('before:screenshot', (config, superDomainOrigin) => {
Cypress.primaryOriginCommunicator.on('before:screenshot', (config, origin) => {
const callback = () => {
Cypress.primaryOriginCommunicator.toSpecBridge(superDomainOrigin, 'before:screenshot:end')
Cypress.primaryOriginCommunicator.toSpecBridge(origin, 'before:screenshot:end')
}

handleBeforeScreenshot(config, callback)
Expand Down Expand Up @@ -861,9 +861,9 @@ export class EventManager {
this.ws.emit('spec:changed', specFile)
}

notifyCrossOriginBridgeReady (superDomainOrigin) {
notifyCrossOriginBridgeReady (origin) {
// Any multi-origin event appends the origin as the third parameter and we do the same here for this short circuit
Cypress.primaryOriginCommunicator.emit('bridge:ready', undefined, superDomainOrigin)
Cypress.primaryOriginCommunicator.emit('bridge:ready', undefined, origin)
}

snapshotUnpinned () {
Expand Down
6 changes: 3 additions & 3 deletions packages/app/src/runner/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -194,11 +194,11 @@ export async function teardown () {
* Add a cross origin iframe for cy.origin support
*/
export function addCrossOriginIframe (location) {
const id = `Spec Bridge: ${location.superDomainOrigin}`
const id = `Spec Bridge: ${location.origin}`

// if it already exists, don't add another one
if (document.getElementById(id)) {
getEventManager().notifyCrossOriginBridgeReady(location.superDomainOrigin)
getEventManager().notifyCrossOriginBridgeReady(location.origin)

return
}
Expand All @@ -209,7 +209,7 @@ export function addCrossOriginIframe (location) {
// container since it needs to match the size of the top window for screenshots
$container: document.body,
className: 'spec-bridge-iframe',
src: `${location.superDomainOrigin}/${getRunnerConfigFromWindow().namespace}/spec-bridge-iframes`,
src: `${location.origin}/${getRunnerConfigFromWindow().namespace}/spec-bridge-iframes`,
})
}

Expand Down
8 changes: 4 additions & 4 deletions packages/driver/cypress/e2e/commands/navigation.cy.js
Original file line number Diff line number Diff line change
Expand Up @@ -1553,7 +1553,7 @@ describe('src/cy/commands/navigation', () => {
${experimentalMessage}
\`cy.visit('http://localhost:3500/fixtures/generic.html')\`
\`<commands targeting http://localhost:3500 go here>\`\n
\`cy.origin('http://foobar.com:3500', () => {\`
\`cy.origin('http://www.foobar.com:3500', () => {\`
\` cy.visit('http://www.foobar.com:3500/fixtures/generic.html')\`
\` <commands targeting http://www.foobar.com:3500 go here>\`
\`})\`\n
Expand Down Expand Up @@ -2241,10 +2241,10 @@ describe('src/cy/commands/navigation', () => {
expect(err.message).to.contain(stripIndent`\
Cypress detected a cross origin error happened on page load:\n
> ${error}\n
Before the page load, you were bound to the origin policy:\n
Before the page load, you were bound to the origin:\n
> http://localhost:3500\n
A cross origin error happens when your application navigates to a new URL which does not match the origin policy above.\n
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.\n
A cross origin error happens when your application navigates to a new URL which does not match the origin above.\n
A new URL does not match the origin if the 'protocol', 'port' (if specified), and/or 'host' are different.\n
Cypress does not allow you to navigate to a different origin URL within a single test.\n
You may need to restructure some of your test code to avoid this problem.\n
Alternatively you can also disable Chrome Web Security in Chromium-based browsers which will turn off this restriction by setting { chromeWebSecurity: false }`)
Expand Down
34 changes: 17 additions & 17 deletions packages/driver/cypress/e2e/e2e/origin/basic_login.cy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ describe('basic login', () => {
it('logs in with idp redirect', () => {
cy.visit('/fixtures/auth/index.html') // Establishes primary origin
cy.get('[data-cy="login-idp"]').click() // Takes you to idp.com
cy.origin('http://idp.com:3500', () => {
cy.origin('http://www.idp.com:3500', () => {
cy.get('[data-cy="username"]').type('BJohnson')
cy.get('[data-cy="login"]').click()
})
Expand All @@ -23,7 +23,7 @@ describe('basic login', () => {
win.location.href = 'http://www.idp.com:3500/fixtures/auth/idp.html'
})

cy.origin('http://idp.com:3500', () => {
cy.origin('http://www.idp.com:3500', () => {
cy.get('[data-cy="username"]').type('FJohnson')
cy.get('[data-cy="login"]').click()
})
Expand All @@ -37,7 +37,7 @@ describe('basic login', () => {
it('visits foobar first', () => {
cy.visit('http://www.foobar.com:3500/fixtures/auth/index.html') // Establishes primary origin
cy.get('[data-cy="login-idp"]').click() // Takes you to idp.com
cy.origin('http://idp.com:3500', () => {
cy.origin('http://www.idp.com:3500', () => {
cy.get('[data-cy="username"]').type('BJohnson')
cy.get('[data-cy="login"]').click()
})
Expand All @@ -60,7 +60,7 @@ describe('basic login', () => {
// Primary established via base url
// TODO: baseUrl does not establish primary without a visit
it.skip('logs in with primary set via baseurl', { baseUrl: 'http://localhost:3500' }, () => {
cy.origin('http://idp.com:3500', () => { // primary origin is localhost
cy.origin('http://www.idp.com:3500', () => { // primary origin is localhost
cy.visit('http://www.idp.com:3500/fixtures/auth/idp.html')
cy.get('[data-cy="username"]').type('FJohnson')
cy.get('[data-cy="login"]').click()
Expand All @@ -77,7 +77,7 @@ describe('basic login', () => {

it('logs in with primary set via visit', () => {
cy.visit('/fixtures/auth/index.html')
cy.origin('http://idp.com:3500', () => { // primary origin is localhost
cy.origin('http://www.idp.com:3500', () => { // primary origin is localhost
cy.visit('http://www.idp.com:3500/fixtures/auth/idp.html')
cy.get('[data-cy="username"]').type('FJohnson')
cy.get('[data-cy="login"]').click()
Expand All @@ -94,7 +94,7 @@ describe('basic login', () => {
const login = (name) => {
cy.session(name, () => {
// Note, this assumes localhost is the primary origin, ideally we'd be able to specify this directly.
cy.origin('http://idp.com:3500', { args: name }, (name) => {
cy.origin('http://www.idp.com:3500', { args: name }, (name) => {
cy.visit('http://www.idp.com:3500/fixtures/auth/idp.html')
cy.get('[data-cy="username"]').type(name)
cy.get('[data-cy="login"]').click()
Expand Down Expand Up @@ -154,9 +154,9 @@ describe('Multi-step Auth', () => {
cy.visit('/fixtures/auth/index.html')
cy.get('[data-cy="login-with-approval"]').click() // takes you to foobar.com.../approval
cy.url() //fail
cy.origin('http://foobar.com:3500', () => { // Parent origin is localhost
cy.origin('http://www.foobar.com:3500', () => { // Parent origin is localhost
cy.get('[data-cy="approve-orig"]').click() // takes you to idp.com
cy.origin('http://idp.com:3500', () => { // Parent origin is foobar.com
cy.origin('http://www.idp.com:3500', () => { // Parent origin is foobar.com
cy.get('[data-cy="username"]').type('MarkyMark')
cy.get('[data-cy="login"]').click() // Takes you back to localhost
}) // Does not wait on foobar.com because there are no subsequent commands (would wait forever)
Expand All @@ -172,11 +172,11 @@ describe('Multi-step Auth', () => {
it.skip('final-auth redirects back to localhost - flat', () => {
cy.visit('/fixtures/auth/index.html')
cy.get('[data-cy="login-with-approval"]').click() // takes you to foobar.com.../approval
cy.origin('http://foobar.com:3500', () => { // Parent origin is localhost
cy.origin('http://www.foobar.com:3500', () => { // Parent origin is localhost
cy.get('[data-cy="approve-orig"]').click() // takes you to idp.com
}) // Exits and moves on to the next command

cy.origin('http://idp.com:3500', () => { // Parent origin is localhost
cy.origin('http://www.idp.com:3500', () => { // Parent origin is localhost
cy.get('[data-cy="username"]').type('MarkyMark')
cy.get('[data-cy="login"]').click() // Takes you back to localhost
}) // Exits and moves on to the next command
Expand All @@ -189,10 +189,10 @@ describe('Multi-step Auth', () => {

// TODO: cy.origin does not work in cy.origin yet.
it.skip('final auth redirects back to localhost - nested - approval first', () => {
cy.origin('http://foobar.com:3500', () => { // parent origin is localhost
cy.origin('http://www.foobar.com:3500', () => { // parent origin is localhost
cy.visit('http://www.foobar.com:3500/fixtures/auth/approval.html')
cy.get('[data-cy="approve-orig"]').click() // takes you to idp.com
cy.origin('http://idp.com:3500', () => { // parent origin is foobar.com
cy.origin('http://www.idp.com:3500', () => { // parent origin is foobar.com
cy.get('[data-cy="username"]').type('MarkyMark')
cy.get('[data-cy="login"]').click() // Takes you back to localhost
}) // Does not wait on foobar.com because there are no subsequent commands (would wait forever)
Expand All @@ -208,9 +208,9 @@ describe('Multi-step Auth', () => {
it.skip('final auth redirects back to approval page - nested', () => {
cy.visit('/fixtures/auth/index.html')
cy.get('[data-cy="login-with-approval"]').click() // takes you to foobar.com.../approval
cy.origin('http://foobar.com:3500', () => { // parent origin is localhost
cy.origin('http://www.foobar.com:3500', () => { // parent origin is localhost
cy.get('[data-cy="approve-me"]').click() // takes you to idp.com
cy.origin('http://idp.com:3500', () => { // parent origin is foobar.com
cy.origin('http://www.idp.com:3500', () => { // parent origin is foobar.com
cy.get('[data-cy="username"]').type('MarkyMark')
cy.get('[data-cy="login"]').click() // Takes you back to foobar.com.../approval
}) // Exits and moves on to the next command
Expand All @@ -227,16 +227,16 @@ describe('Multi-step Auth', () => {
it('final auth redirects back to approval page - flat', () => {
cy.visit('/fixtures/auth/index.html')
cy.get('[data-cy="login-with-approval"]').click() // takes you to foobar.com.../approval
cy.origin('http://foobar.com:3500', () => { // parent origin is localhost
cy.origin('http://www.foobar.com:3500', () => { // parent origin is localhost
cy.get('[data-cy="approve-me"]').click() // takes you to idp.com
}) // waits on localhost forever, this breaks

cy.origin('http://idp.com:3500', () => { // parent origin is localhost
cy.origin('http://www.idp.com:3500', () => { // parent origin is localhost
cy.get('[data-cy="username"]').type('MarkyMark')
cy.get('[data-cy="login"]').click() // Takes you back to foobar.com.../approval
}) // Exits and moves on to the next command

cy.origin('http://foobar.com:3500', () => { // parent origin is localhost
cy.origin('http://www.foobar.com:3500', () => { // parent origin is localhost
cy.get('[data-cy="login-success"]').click() // Takes you back to localhost
}) // Exits and moves on to the next command

Expand Down
Loading