diff --git a/packages/app/src/runner/aut-iframe.ts b/packages/app/src/runner/aut-iframe.ts index c5d0342f1a92..8f82ab4e2644 100644 --- a/packages/app/src/runner/aut-iframe.ts +++ b/packages/app/src/runner/aut-iframe.ts @@ -93,7 +93,7 @@ export class AutIframe { * Otherwise, if top and the AUT match 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 */ - doesAUTMatchTopSuperOriginPolicy = () => { + doesAUTMatchTopOriginPolicy = () => { const Cypress = this.eventManager.getCypress() if (!Cypress) return true @@ -103,7 +103,7 @@ export class AutIframe { const locationTop = Cypress.Location.create(window.location.href) const locationAUT = Cypress.Location.create(currentHref) - return locationTop.superDomainOriginPolicy === locationAUT.superDomainOriginPolicy || locationAUT.superDomainOriginPolicy === 'about://blank' + return locationTop.originPolicy === locationAUT.originPolicy || locationAUT.originPolicy === 'about://blank' } catch (err) { if (err.name === 'SecurityError') { return false @@ -147,7 +147,7 @@ export class AutIframe { } restoreDom = (snapshot) => { - if (!this.doesAUTMatchTopSuperOriginPolicy()) { + if (!this.doesAUTMatchTopOriginPolicy()) { /** * A load event fires here when the src is removed (as does an unload event). * This is equivalent to loading about:blank (see https://developer.mozilla.org/en-US/docs/Web/HTML/Element/iframe#attr-src). diff --git a/packages/app/src/runner/event-manager.ts b/packages/app/src/runner/event-manager.ts index 2b57d9184115..a07e8dab98f3 100644 --- a/packages/app/src/runner/event-manager.ts +++ b/packages/app/src/runner/event-manager.ts @@ -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 }, superDomainOriginPolicy) => { - Cypress.primaryOriginCommunicator.toSpecBridge(superDomainOriginPolicy, specBridgeResponseEvent, cy.state('duringUserTestExecution')) + Cypress.primaryOriginCommunicator.on('sync:during:user:test:execution', ({ specBridgeResponseEvent }, originPolicy) => { + Cypress.primaryOriginCommunicator.toSpecBridge(originPolicy, specBridgeResponseEvent, cy.state('duringUserTestExecution')) }) Cypress.on('request:snapshot:from:spec:bridge', ({ log, name, options, specBridge, addSnapshot }: { @@ -653,22 +653,22 @@ export class EventManager { Cypress.primaryOriginCommunicator.toAllSpecBridges('before:unload', origin) }) - Cypress.primaryOriginCommunicator.on('expect:origin', (superDomainOriginPolicy) => { - this.localBus.emit('expect:origin', superDomainOriginPolicy) + Cypress.primaryOriginCommunicator.on('expect:origin', (originPolicy) => { + this.localBus.emit('expect:origin', originPolicy) }) - Cypress.primaryOriginCommunicator.on('viewport:changed', (viewport, superDomainOriginPolicy) => { + Cypress.primaryOriginCommunicator.on('viewport:changed', (viewport, originPolicy) => { const callback = () => { - Cypress.primaryOriginCommunicator.toSpecBridge(superDomainOriginPolicy, 'viewport:changed:end') + Cypress.primaryOriginCommunicator.toSpecBridge(originPolicy, 'viewport:changed:end') } Cypress.primaryOriginCommunicator.emit('sync:viewport', viewport) this.localBus.emit('viewport:changed', viewport, callback) }) - Cypress.primaryOriginCommunicator.on('before:screenshot', (config, superDomainOriginPolicy) => { + Cypress.primaryOriginCommunicator.on('before:screenshot', (config, originPolicy) => { const callback = () => { - Cypress.primaryOriginCommunicator.toSpecBridge(superDomainOriginPolicy, 'before:screenshot:end') + Cypress.primaryOriginCommunicator.toSpecBridge(originPolicy, 'before:screenshot:end') } handleBeforeScreenshot(config, callback) @@ -861,9 +861,9 @@ export class EventManager { this.ws.emit('spec:changed', specFile) } - notifyCrossOriginBridgeReady (superDomainOriginPolicy) { + notifyCrossOriginBridgeReady (originPolicy) { // 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, superDomainOriginPolicy) + Cypress.primaryOriginCommunicator.emit('bridge:ready', undefined, originPolicy) } snapshotUnpinned () { diff --git a/packages/app/src/runner/index.ts b/packages/app/src/runner/index.ts index f68b25d657be..ad7ccf599662 100644 --- a/packages/app/src/runner/index.ts +++ b/packages/app/src/runner/index.ts @@ -98,7 +98,7 @@ function createIframeModel () { autIframe.detachDom, autIframe.restoreDom, autIframe.highlightEl, - autIframe.doesAUTMatchTopSuperOriginPolicy, + autIframe.doesAUTMatchTopOriginPolicy, getEventManager(), { selectorPlaygroundModel: getEventManager().selectorPlaygroundModel, @@ -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.superDomainOriginPolicy}` + const id = `Spec Bridge: ${location.originPolicy}` // if it already exists, don't add another one if (document.getElementById(id)) { - getEventManager().notifyCrossOriginBridgeReady(location.superDomainOriginPolicy) + getEventManager().notifyCrossOriginBridgeReady(location.originPolicy) return } @@ -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.superDomainOriginPolicy}/${getRunnerConfigFromWindow().namespace}/spec-bridge-iframes`, + src: `${location.originPolicy}/${getRunnerConfigFromWindow().namespace}/spec-bridge-iframes`, }) } diff --git a/packages/driver/cypress/e2e/e2e/origin/navigation.cy.ts b/packages/driver/cypress/e2e/e2e/origin/navigation.cy.ts index 3a0ecb5fb231..8d12f03066e3 100644 --- a/packages/driver/cypress/e2e/e2e/origin/navigation.cy.ts +++ b/packages/driver/cypress/e2e/e2e/origin/navigation.cy.ts @@ -27,7 +27,7 @@ describe('navigation events', () => { describe('navigation:changed', () => { it('navigation:changed via hashChange', () => { - cy.origin('http://foobar.com:3500', () => { + cy.origin('http://www.foobar.com:3500', () => { const afterNavigationChanged = new Promise((resolve) => { const listener = () => { const loc = cy.getRemoteLocation() @@ -48,7 +48,7 @@ describe('navigation events', () => { }) it('navigates forward and back using history', () => { - cy.origin('http://foobar.com:3500', () => { + cy.origin('http://www.foobar.com:3500', () => { const onLoad = (cb) => { const onNavChanged = (event) => { if (event === 'page navigation event (load)') { @@ -80,7 +80,7 @@ describe('navigation events', () => { describe('window:load', () => { it('reloads', () => { - cy.origin('http://foobar.com:3500', () => { + cy.origin('http://www.foobar.com:3500', () => { const logs: any[] = [] cy.on('log:added', (attrs, log) => { @@ -111,7 +111,7 @@ describe('navigation events', () => { }) it('navigates to a new page', () => { - cy.origin('http://foobar.com:3500', () => { + cy.origin('http://www.foobar.com:3500', () => { const logs: any[] = [] cy.on('log:added', (attrs, log) => { @@ -144,7 +144,7 @@ describe('navigation events', () => { describe('url:changed', () => { it('reloads', () => { - cy.origin('http://foobar.com:3500', () => { + cy.origin('http://www.foobar.com:3500', () => { const afterUrlChanged = new Promise((resolve) => { cy.once('url:changed', (url) => { expect(url).to.equal('http://www.foobar.com:3500/fixtures/secondary-origin.html') @@ -158,7 +158,7 @@ describe('navigation events', () => { }) it('navigates to a new page', () => { - cy.origin('http://foobar.com:3500', () => { + cy.origin('http://www.foobar.com:3500', () => { const afterUrlChanged = new Promise((resolve) => { const listener = (url) => { cy.removeListener('url:changed', listener) @@ -177,7 +177,7 @@ describe('navigation events', () => { // TODO: this test should re revisited with the cypress in cypress tests available in 10.0 // https://github.com/cypress-io/cypress/issues/20973 it.skip('the runner url updates appropriately', () => { - cy.origin('http://foobar.com:3500', () => { + cy.origin('http://www.foobar.com:3500', () => { cy.get('a[data-cy="cross-origin-page"]').click() }) }) @@ -190,7 +190,7 @@ describe('event timing', () => { cy.visit('/fixtures/primary-origin.html') cy.get('a[data-cy="cross-origin-secondary-link"]').click() - cy.origin('http://foobar.com:3500', () => { + cy.origin('http://www.foobar.com:3500', () => { cy.log('inside cy.origin foobar') }) @@ -199,7 +199,7 @@ describe('event timing', () => { win.location.href = 'http://www.idp.com:3500/fixtures/primary-origin.html' }) - cy.origin('http://idp.com:3500', () => { + cy.origin('http://www.idp.com:3500', () => { cy.log('inside cy.origin idp') }) }) @@ -216,14 +216,14 @@ describe('delayed navigation', { defaultCommandTimeout: 2000 }, () => { it('localhost -> foobar, delay in', () => { cy.visit('/fixtures/auth/delayedNavigate.html') cy.get('[data-cy="to-foobar"]').click() - cy.origin('http://foobar.com:3500', () => { + cy.origin('http://www.foobar.com:3500', () => { cy.get('[data-cy="login-idp"]') }) }) it('foobar -> localhost, delay out', () => { cy.visit('/fixtures/auth/index.html') - cy.origin('http://foobar.com:3500', () => { + cy.origin('http://www.foobar.com:3500', () => { cy.visit('http://www.foobar.com:3500/fixtures/auth/delayedNavigate.html') cy.get('[data-cy="to-localhost"]').click() }) @@ -233,12 +233,12 @@ describe('delayed navigation', { defaultCommandTimeout: 2000 }, () => { it('foobar -> idp, delay out', () => { cy.visit('/fixtures/auth/index.html') - cy.origin('http://foobar.com:3500', () => { + cy.origin('http://www.foobar.com:3500', () => { cy.visit('http://www.foobar.com:3500/fixtures/auth/delayedNavigate.html') cy.get('[data-cy="to-idp"]').click() }) - cy.origin('http://idp.com:3500', () => { + cy.origin('http://www.idp.com:3500', () => { cy.get('[data-cy="login-idp"]') }) }) @@ -249,7 +249,7 @@ describe('errors', () => { it('never calls cy.origin', { defaultCommandTimeout: 50 }, (done) => { cy.on('fail', (err) => { expect(err.message).to.include(`Timed out retrying after 50ms:`) - expect(err.message).to.include(`The command was expected to run against origin \`http://localhost:3500\` but the application is at origin \`http://foobar.com:3500\`.`) + expect(err.message).to.include(`The command was expected to run against origin \`http://localhost:3500\` but the application is at origin \`http://www.foobar.com:3500\`.`) expect(err.message).to.include(`This commonly happens when you have either not navigated to the expected origin or have navigated away unexpectedly.`) // make sure that the secondary origin failures do NOT show up as spec failures or AUT failures expect(err.message).not.to.include(`The following error originated from your test code, not from Cypress`) @@ -265,7 +265,7 @@ describe('errors', () => { it('never redirects to the cross-origin', { defaultCommandTimeout: 50 }, (done) => { cy.on('fail', (err) => { expect(err.message).to.include(`Timed out retrying after 50ms:`) - expect(err.message).to.include(`The command was expected to run against origin \`http://idp.com:3500\` but the application is at origin \`http://localhost:3500\`.`) + expect(err.message).to.include(`The command was expected to run against origin \`http://www.idp.com:3500\` but the application is at origin \`http://localhost:3500\`.`) expect(err.message).to.include(`This commonly happens when you have either not navigated to the expected origin or have navigated away unexpectedly.`) // make sure that the secondary origin failures do NOT show up as spec failures or AUT failures expect(err.message).not.to.include(`The following error originated from your test code, not from Cypress`) @@ -275,7 +275,7 @@ describe('errors', () => { cy.visit('/fixtures/auth/index.html') cy.get('[data-cy="login-idp"]') - cy.origin('http://idp.com:3500', () => { + cy.origin('http://www.idp.com:3500', () => { cy.get('[data-cy="username"]').type('BJohnson') // Timeout here on command, cannot find element cy.get('[data-cy="login"]').click() }) @@ -288,7 +288,7 @@ describe('errors', () => { it('redirects to the wrong cross-origin', { defaultCommandTimeout: 50 }, (done) => { cy.on('fail', (err) => { expect(err.message).to.include(`Timed out retrying after 50ms:`) - expect(err.message).to.include(`The command was expected to run against origin \`http://idp.com:3500\` but the application is at origin \`http://foobar.com:3500\`.`) + expect(err.message).to.include(`The command was expected to run against origin \`http://www.idp.com:3500\` but the application is at origin \`http://www.foobar.com:3500\`.`) expect(err.message).to.include(`This commonly happens when you have either not navigated to the expected origin or have navigated away unexpectedly.`) // make sure that the secondary origin failures do NOT show up as spec failures or AUT failures expect(err.message).not.to.include(`The following error originated from your test code, not from Cypress`) @@ -298,7 +298,7 @@ describe('errors', () => { cy.visit('/fixtures/auth/index.html') cy.get('[data-cy="login-foobar"]').click() // Timeout on page load here, we never reach the expected origin - 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() }) @@ -312,7 +312,7 @@ describe('errors', () => { it('never returns to the primary origin', { defaultCommandTimeout: 50 }, (done) => { cy.on('fail', (err) => { expect(err.message).to.include(`Timed out retrying after 50ms:`) - expect(err.message).to.include(`The command was expected to run against origin \`http://localhost:3500\` but the application is at origin \`http://idp.com:3500\`.`) + expect(err.message).to.include(`The command was expected to run against origin \`http://localhost:3500\` but the application is at origin \`http://www.idp.com:3500\`.`) // make sure that the secondary origin failures do NOT show up as spec failures or AUT failures expect(err.message).not.to.include(`The following error originated from your test code, not from Cypress`) expect(err.message).not.to.include(`The following error originated from your application code, not from Cypress`) @@ -321,7 +321,7 @@ describe('errors', () => { cy.visit('/fixtures/auth/index.html') cy.get('[data-cy="login-idp"]').click() - cy.origin('http://idp.com:3500', () => { + cy.origin('http://www.idp.com:3500', () => { cy.get('[data-cy="username"]').type('BJohnson') }) // cy.origin is stable so the command exits @@ -334,7 +334,7 @@ describe('errors', () => { it('redirects to an unexpected cross-origin', { defaultCommandTimeout: 50 }, (done) => { cy.on('fail', (err) => { expect(err.message).to.include(`Timed out retrying after 50ms:`) - expect(err.message).to.include(`The command was expected to run against origin \`http://localhost:3500\` but the application is at origin \`http://foobar.com:3500\`.`) + expect(err.message).to.include(`The command was expected to run against origin \`http://localhost:3500\` but the application is at origin \`http://www.foobar.com:3500\`.`) // make sure that the secondary origin failures do NOT show up as spec failures or AUT failures expect(err.message).not.to.include(`The following error originated from your test code, not from Cypress`) expect(err.message).not.to.include(`The following error originated from your application code, not from Cypress`) @@ -343,7 +343,7 @@ describe('errors', () => { cy.visit('/fixtures/auth/index.html') cy.get('[data-cy="login-idp"]').click() - cy.origin('http://idp.com:3500', () => { + cy.origin('http://www.idp.com:3500', () => { cy.get('[data-cy="username"]').type('BJohnson') cy.window().then((win) => { win.location.href = 'http://www.foobar.com:3500/fixtures/auth/index.html' @@ -359,7 +359,7 @@ describe('errors', () => { it('redirects to an unexpected cross-origin and calls another command in the cy.origin command', { pageLoadTimeout: 5000, defaultCommandTimeout: 50 }, (done) => { cy.on('fail', (err) => { expect(err.message).to.include(`Timed out retrying after 50ms:`) - expect(err.message).to.include(`The command was expected to run against origin \`http://idp.com:3500\` but the application is at origin \`http://foobar.com:3500\`.`) + expect(err.message).to.include(`The command was expected to run against origin \`http://www.idp.com:3500\` but the application is at origin \`http://www.foobar.com:3500\`.`) // make sure that the secondary origin failures do NOT show up as spec failures or AUT failures expect(err.message).not.to.include(`The following error originated from your test code, not from Cypress`) expect(err.message).not.to.include(`The following error originated from your application code, not from Cypress`) @@ -368,7 +368,7 @@ describe('errors', () => { cy.visit('/fixtures/auth/index.html') cy.get('[data-cy="login-idp"]').click() - cy.origin('http://idp.com:3500', () => { + cy.origin('http://www.idp.com:3500', () => { cy.get('[data-cy="username"]').type('BJohnson') cy.window().then((win) => { win.location.href = 'http://www.foobar.com:3500/fixtures/auth/index.html' @@ -387,7 +387,7 @@ describe('errors', () => { it.skip('fails in cy.origin when a command is run after we return to localhost', { defaultCommandTimeout: 50 }, (done) => { cy.on('fail', (err) => { expect(err.message).to.include(`Timed out retrying after 50ms:`) - expect(err.message).to.include(`The command was expected to run against origin \`http://idp.com:3500\` but the application is at origin \`http://localhost:3500\`.`) + expect(err.message).to.include(`The command was expected to run against origin \`http://www.idp.com:3500\` but the application is at origin \`http://localhost:3500\`.`) // make sure that the secondary origin failures do NOT show up as spec failures or AUT failures expect(err.message).not.to.include(`The following error originated from your test code, not from Cypress`) expect(err.message).not.to.include(`The following error originated from your application code, not from Cypress`) @@ -396,7 +396,7 @@ describe('errors', () => { 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() cy.get('[data-cy="cannot_find"]') // Timeout here on command stability achieved by primary origin, this command times out. @@ -420,7 +420,7 @@ describe('errors', () => { 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="cannot_find"]') // Timeout here on command stability achieved by primary origin, this command times out. }) }) @@ -431,7 +431,7 @@ describe('errors', () => { it('times out in cy.origin with foobar spec bridge undefined', { defaultCommandTimeout: 50 }, (done) => { cy.on('fail', (err) => { expect(err.message).to.include(`Timed out retrying after 50ms:`) - expect(err.message).to.include(`The command was expected to run against origin \`http://localhost:3500\` but the application is at origin \`http://foobar.com:3500\`.`) + expect(err.message).to.include(`The command was expected to run against origin \`http://localhost:3500\` but the application is at origin \`http://www.foobar.com:3500\`.`) // make sure that the secondary origin failures do NOT show up as spec failures or AUT failures expect(err.message).not.to.include(`The following error originated from your test code, not from Cypress`) expect(err.message).not.to.include(`The following error originated from your application code, not from Cypress`) @@ -439,13 +439,13 @@ describe('errors', () => { }) cy.visit('/fixtures/auth/index.html') // Establishes primary origin - cy.origin('http://foobar.com:3500', () => {}).then(() => { + cy.origin('http://www.foobar.com:3500', () => {}).then(() => { // Force remove the spec bridge - window?.top?.document.getElementById('Spec Bridge: http://foobar.com:3500')?.remove() + window?.top?.document.getElementById('Spec Bridge: http://www.foobar.com:3500')?.remove() }) 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.window().then((win) => { win.location.href = 'http://www.foobar.com:3500/fixtures/auth/index.html' @@ -462,7 +462,7 @@ describe('errors', () => { it('establishes foobar spec bridge', () => { cy.visit('/fixtures/auth/index.html') // Establishes primary origin cy.get('[data-cy="login-foobar"]').click() // Takes you to idp.com - cy.origin('http://foobar.com:3500', () => { + cy.origin('http://www.foobar.com:3500', () => { cy.get('[data-cy="username"]').type('BJohnson') cy.get('[data-cy="login"]').click() }) @@ -478,7 +478,7 @@ describe('errors', () => { it('times out in cy.origin with foobar spec bridge defined', { defaultCommandTimeout: 50 }, (done) => { cy.on('fail', (err) => { expect(err.message).to.include(`Timed out retrying after 50ms:`) - expect(err.message).to.include(`The command was expected to run against origin \`http://localhost:3500\` but the application is at origin \`http://foobar.com:3500\`.`) + expect(err.message).to.include(`The command was expected to run against origin \`http://localhost:3500\` but the application is at origin \`http://www.foobar.com:3500\`.`) // make sure that the secondary origin failures do NOT show up as spec failures or AUT failures expect(err.message).not.to.include(`The following error originated from your test code, not from Cypress`) expect(err.message).not.to.include(`The following error originated from your application code, not from Cypress`) @@ -487,7 +487,7 @@ describe('errors', () => { 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.window().then((win) => { win.location.href = 'http://www.foobar.com:3500/fixtures/auth/index.html' diff --git a/packages/driver/src/cross-origin/communicator.ts b/packages/driver/src/cross-origin/communicator.ts index 9a71c3dd8760..a249711cb043 100644 --- a/packages/driver/src/cross-origin/communicator.ts +++ b/packages/driver/src/cross-origin/communicator.ts @@ -88,7 +88,7 @@ export class PrimaryOriginCommunicator extends EventEmitter { // where we need to set the crossOriginDriverWindows to source to // communicate back to the iframe if (messageName === 'bridge:ready' && source) { - this.crossOriginDriverWindows[data.superDomainOriginPolicy] = source as Window + this.crossOriginDriverWindows[data.originPolicy] = source as Window } // reify any logs coming back from the cross-origin spec bridges to serialize snapshot/consoleProp DOM elements as well as select functions. @@ -105,7 +105,7 @@ export class PrimaryOriginCommunicator extends EventEmitter { data.data.err = reifySerializedError(data.data.err, this.userInvocationStack as string) } - this.emit(messageName, data.data, data.superDomainOriginPolicy, source) + this.emit(messageName, data.data, data.originPolicy, source) return } @@ -137,8 +137,8 @@ export class PrimaryOriginCommunicator extends EventEmitter { }) } - toSpecBridge (superDomainOriginPolicy: string, event: string, data?: any) { - debug('=> to spec bridge', superDomainOriginPolicy, event, data) + toSpecBridge (originPolicy: string, event: string, data?: any) { + debug('=> to spec bridge', originPolicy, event, data) const preprocessedData = preprocessForSerialization(data) @@ -148,7 +148,7 @@ export class PrimaryOriginCommunicator extends EventEmitter { } // If there is no crossOriginDriverWindows, there is no need to send the message. - this.crossOriginDriverWindows[superDomainOriginPolicy]?.postMessage({ + this.crossOriginDriverWindows[originPolicy]?.postMessage({ event, data: preprocessedData, }, '*') @@ -161,18 +161,18 @@ export class PrimaryOriginCommunicator extends EventEmitter { * @param options - contains boolean to sync globals * @returns the response from primary of the event with the same name. */ - toSpecBridgePromise (superDomainOriginPolicy: string, event: string, data?: any) { + toSpecBridgePromise (originPolicy: string, event: string, data?: any) { return new Promise((resolve, reject) => { const dataToSend = sharedPromiseSetup({ resolve, reject, data, event, - specBridgeName: superDomainOriginPolicy, + specBridgeName: originPolicy, communicator: this, }) - this.toSpecBridge(superDomainOriginPolicy, event, dataToSend) + this.toSpecBridge(originPolicy, event, dataToSend) }) } } @@ -251,7 +251,7 @@ export class SpecBridgeCommunicator extends EventEmitter { * @param {Cypress.ObjectLike} data - any meta data to be sent with the event. */ toPrimary (event: string, data?: Cypress.ObjectLike, options: { syncGlobals: boolean } = { syncGlobals: false }) { - const { superDomainOriginPolicy } = $Location.create(window.location.href) + const { originPolicy } = $Location.create(window.location.href) const eventName = `${CROSS_ORIGIN_PREFIX}${event}` // Preprocess logs before sending through postMessage() to attempt to serialize some DOM nodes and functions. @@ -265,14 +265,14 @@ export class SpecBridgeCommunicator extends EventEmitter { data = preprocessSnapshotForSerialization(data as any) } - debug('<= to Primary ', event, data, superDomainOriginPolicy) + debug('<= to Primary ', event, data, originPolicy) if (options.syncGlobals) this.syncGlobalsToPrimary() this.handleSubjectAndErr(data, (data: Cypress.ObjectLike) => { window.top?.postMessage({ event: eventName, data, - superDomainOriginPolicy, + originPolicy, }, '*') }) } diff --git a/packages/driver/src/cross-origin/cypress.ts b/packages/driver/src/cross-origin/cypress.ts index 9e76d9fdc194..5823003180f5 100644 --- a/packages/driver/src/cross-origin/cypress.ts +++ b/packages/driver/src/cross-origin/cypress.ts @@ -44,7 +44,7 @@ const createCypress = () => { try { // the AUT would be the frame with a matching origin, but not the same exact href. - if (window.location.origin === cors.getSuperDomainOriginPolicy(frame.location.origin) + if (window.location.origin === cors.getOriginPolicy(frame.location.origin) && window.location.href !== frame.location.href) { return frame } @@ -67,10 +67,10 @@ const createCypress = () => { }) Cypress.specBridgeCommunicator.on('generate:final:snapshot', (snapshotUrl: string) => { - const currentAutSuperDomainOriginPolicy = cy.state('autLocation').superDomainOriginPolicy + const currentAutOriginPolicy = cy.state('autLocation').originPolicy const requestedSnapshotUrlLocation = $Location.create(snapshotUrl) - if (requestedSnapshotUrlLocation.superDomainOriginPolicy === currentAutSuperDomainOriginPolicy) { + if (requestedSnapshotUrlLocation.originPolicy === currentAutOriginPolicy) { // if true, this is the correct spec bridge to take the snapshot and send it back const finalSnapshot = cy.createSnapshot(FINAL_SNAPSHOT_NAME) diff --git a/packages/driver/src/cross-origin/events/misc.ts b/packages/driver/src/cross-origin/events/misc.ts index 91a6edb5fe2c..529969470c5d 100644 --- a/packages/driver/src/cross-origin/events/misc.ts +++ b/packages/driver/src/cross-origin/events/misc.ts @@ -24,7 +24,7 @@ export const handleMiscEvents = (Cypress: Cypress.Cypress, cy: $Cy) => { // Listen for any unload events in other origins, if any have unloaded we should also become unstable. Cypress.specBridgeCommunicator.on('before:unload', (origin) => { // If the unload event originated from this spec bridge, isStable is already being handled. - if (window.location.origin !== cors.getSuperDomainOriginPolicy(origin)) { + if (window.location.origin !== cors.getOriginPolicy(origin)) { cy.state('isStable', false) } }) diff --git a/packages/driver/src/cy/commands/navigation.ts b/packages/driver/src/cy/commands/navigation.ts index 45f2fbe97f19..a20dab7bea2c 100644 --- a/packages/driver/src/cy/commands/navigation.ts +++ b/packages/driver/src/cy/commands/navigation.ts @@ -312,7 +312,7 @@ const stabilityChanged = async (Cypress, state, config, stable) => { const onPageLoadErr = (err) => { state('onPageLoadErr', null) - const { superDomainOriginPolicy } = $Location.create(window.location.href) + const { originPolicy } = $Location.create(window.location.href) try { $errUtils.throwErrByPath('navigation.cross_origin', { @@ -320,7 +320,7 @@ const stabilityChanged = async (Cypress, state, config, stable) => { args: { configFile: Cypress.config('configFile'), message: err.message, - superDomainOriginPolicy, + originPolicy, }, }) } catch (error) { @@ -1084,11 +1084,16 @@ export default (Commands, Cypress, cy, state, config) => { remote = $Location.create(url) - // if the super origin currently matches - // or if we have previously visited a location or are a spec bridge - // then go ahead and change the iframe's src - // we use the superDomainOriginPolicy policy as we can interact with subdomains based document.domain set to the superdomain - if (remote.superDomainOriginPolicy === existing.superDomainOriginPolicy + /** + * If the experimentalSessionAndOrigin is enabled, reload the AUT if the origin policy is a mismatch (which includes subdomain) + * Otherwise, check the superDomainOriginPolicy which is consistent with current behavior + * or if we have previously visited a location or are a spec bridge + * then go ahead and change the iframe's src + */ + // TODO: If we decide to reload when sub domain changes, we can get rid of superDomainOriginPolicy completely + const doesOriginPolicyMatch = Cypress.config('experimentalSessionAndOrigin') ? remote.originPolicy === existing.originPolicy : remote.superDomainOriginPolicy === existing.superDomainOriginPolicy + + if (doesOriginPolicyMatch || ((previouslyVisitedLocation || Cypress.isCrossOriginSpecBridge) && Cypress.config('experimentalSessionAndOrigin')) ) { if (!previouslyVisitedLocation) { diff --git a/packages/driver/src/cy/commands/origin/index.ts b/packages/driver/src/cy/commands/origin/index.ts index 6b2a31ccf397..30e90dd08d87 100644 --- a/packages/driver/src/cy/commands/origin/index.ts +++ b/packages/driver/src/cy/commands/origin/index.ts @@ -85,12 +85,12 @@ export default (Commands, Cypress: Cypress.Cypress, cy: Cypress.cy, state: State validator.validateLocation(location, urlOrDomain) - const superDomainOriginPolicy = location.superDomainOriginPolicy + const originPolicy = location.originPolicy // This is intentionally not reset after leaving the cy.origin command. - cy.state('latestActiveOriginPolicy', superDomainOriginPolicy) + cy.state('latestActiveOriginPolicy', originPolicy) // This is set while IN the cy.origin command. - cy.state('currentActiveOriginPolicy', superDomainOriginPolicy) + cy.state('currentActiveOriginPolicy', originPolicy) return new Bluebird((resolve, reject, onCancel) => { const cleanup = ({ readyForOriginFailed }: {readyForOriginFailed?: boolean} = {}): void => { @@ -171,20 +171,20 @@ export default (Commands, Cypress: Cypress.Cypress, cy: Cypress.cy, state: State // fired once the spec bridge is set up and ready to receive messages communicator.once('bridge:ready', async (_data, specBridgeOriginPolicy) => { - if (specBridgeOriginPolicy === superDomainOriginPolicy) { + if (specBridgeOriginPolicy === originPolicy) { // now that the spec bridge is ready, instantiate Cypress with the current app config and environment variables for initial sync when creating the instance - communicator.toSpecBridge(superDomainOriginPolicy, 'initialize:cypress', { + communicator.toSpecBridge(originPolicy, 'initialize:cypress', { config: preprocessConfig(Cypress.config()), env: preprocessEnv(Cypress.env()), }) // Attach the spec bridge to the window to be tested. - communicator.toSpecBridge(superDomainOriginPolicy, 'attach:to:window') + communicator.toSpecBridge(originPolicy, 'attach:to:window') // once the secondary origin page loads, send along the // user-specified callback to run in that origin try { - communicator.toSpecBridge(superDomainOriginPolicy, 'run:origin:fn', { + communicator.toSpecBridge(originPolicy, 'run:origin:fn', { args: options?.args || undefined, fn: callbackFn.toString(), // let the spec bridge version of Cypress know if config read-only values can be overwritten since window.top cannot be accessed in cross-origin iframes diff --git a/packages/driver/src/cy/commands/waiting.ts b/packages/driver/src/cy/commands/waiting.ts index b06d7fe8072d..1c0a4873b2f8 100644 --- a/packages/driver/src/cy/commands/waiting.ts +++ b/packages/driver/src/cy/commands/waiting.ts @@ -282,14 +282,14 @@ export default (Commands, Cypress, cy, state) => { }) } - Cypress.primaryOriginCommunicator.on('wait:for:xhr', ({ args: [str, options] }, superDomainOriginPolicy) => { + Cypress.primaryOriginCommunicator.on('wait:for:xhr', ({ args: [str, options] }, originPolicy) => { options.isCrossOriginSpecBridge = true waitString(null, str, options).then((responses) => { - Cypress.primaryOriginCommunicator.toSpecBridge(superDomainOriginPolicy, 'wait:for:xhr:end', responses) + Cypress.primaryOriginCommunicator.toSpecBridge(originPolicy, 'wait:for:xhr:end', responses) }).catch((err) => { options._log?.error(err) err.hasSpecBridgeError = true - Cypress.primaryOriginCommunicator.toSpecBridge(superDomainOriginPolicy, 'wait:for:xhr:end', err) + Cypress.primaryOriginCommunicator.toSpecBridge(originPolicy, 'wait:for:xhr:end', err) }) }) diff --git a/packages/driver/src/cy/ensures.ts b/packages/driver/src/cy/ensures.ts index d6bc5a0e8608..4c59bc2ad209 100644 --- a/packages/driver/src/cy/ensures.ts +++ b/packages/driver/src/cy/ensures.ts @@ -395,7 +395,7 @@ export const create = (state: StateFunc, expect: $Cy['expect']) => { if (!isRunnerAbleToCommunicateWithAut()) { const crossOriginCommandError = $errUtils.errByPath('miscellaneous.cross_origin_command', { commandOrigin: window.location.origin, - autOrigin: state('autLocation').superDomainOriginPolicy, + autOrigin: state('autLocation').originPolicy, }) if (err) { diff --git a/packages/driver/src/cypress/error_messages.ts b/packages/driver/src/cypress/error_messages.ts index d64c4e895be0..fda03d580ead 100644 --- a/packages/driver/src/cypress/error_messages.ts +++ b/packages/driver/src/cypress/error_messages.ts @@ -980,7 +980,7 @@ export default { }, navigation: { - cross_origin ({ message, superDomainOriginPolicy, configFile, projectRoot }) { + cross_origin ({ message, originPolicy, configFile, projectRoot }) { return { message: stripIndent`\ Cypress detected a cross origin error happened on page load: @@ -989,7 +989,7 @@ export default { Before the page load, you were bound to the origin policy: - > ${superDomainOriginPolicy} + > ${originPolicy} A cross origin error happens when your application navigates to a new URL which does not match the origin policy above. @@ -1253,7 +1253,7 @@ export default { \`\` - \`cy.origin('${args.previousUrl.superDomainOriginPolicy}', () => {\` + \`cy.origin('${args.previousUrl.originPolicy}', () => {\` \` \` \`})\` @@ -1269,7 +1269,7 @@ export default { This error was thrown by a cross origin page. If you wish to suppress this error you will have to use the cy.origin command to handle the error prior to visiting the page. - \`cy.origin('${autLocation.superDomainOriginPolicy}', () => {\` + \`cy.origin('${autLocation.originPolicy}', () => {\` \` cy.on('uncaught:exception', (e) => {\` \` if (e.message.includes('Things went bad')) {\` \` // we expected this error, so let's ignore it\` @@ -2154,7 +2154,7 @@ export default { message: stripIndent`${cmd('visit')} was called to visit a cross origin site with an \`onLoad\` callback. \`onLoad\` callbacks can only be used with same origin sites. If you wish to specify an \`onLoad\` callback please use the \`cy.origin\` command to setup a \`window:load\` event prior to visiting the cross origin site. - \`cy.origin('${args.autLocation.superDomainOriginPolicy}', () => {\` + \`cy.origin('${args.autLocation.originPolicy}', () => {\` \` cy.on('window:load', () => {\` \` \` \` })\` @@ -2169,7 +2169,7 @@ export default { message: stripIndent`${cmd('visit')} was called to visit a cross origin site with an \`onBeforeLoad\` callback. \`onBeforeLoad\` callbacks can only be used with same origin sites. If you wish to specify an \`onBeforeLoad\` callback please use the \`cy.origin\` command to setup a \`window:before:load\` event prior to visiting the cross origin site. - \`cy.origin('${args.autLocation.superDomainOriginPolicy}', () => {\` + \`cy.origin('${args.autLocation.originPolicy}', () => {\` \` cy.on('window:before:load', () => {\` \` \` \` })\` @@ -2194,7 +2194,7 @@ export default { ${args.experimentalSessionAndOrigin ? `You likely forgot to use ${cmd('origin')}:` : `In order to visit a different origin, you can enable the \`experimentalSessionAndOrigin\` flag and use ${cmd('origin')}:` } ${args.isCrossOriginSpecBridge ? - `\`cy.origin('${args.previousUrl.superDomainOriginPolicy}', () => {\` + `\`cy.origin('${args.previousUrl.originPolicy}', () => {\` \` cy.visit('${args.previousUrl}')\` \` \` \`})\`` : @@ -2202,7 +2202,7 @@ export default { \`\`` } - \`cy.origin('${args.attemptedUrl.superDomainOriginPolicy}', () => {\` + \`cy.origin('${args.attemptedUrl.originPolicy}', () => {\` \` cy.visit('${args.originalUrl}')\` \` \` \`})\` diff --git a/packages/driver/src/cypress/log.ts b/packages/driver/src/cypress/log.ts index 942bc57a6ad3..63b9de52ace7 100644 --- a/packages/driver/src/cypress/log.ts +++ b/packages/driver/src/cypress/log.ts @@ -376,7 +376,7 @@ export class Log { if (this.config('experimentalSessionAndOrigin') && !Cypress.isCrossOriginSpecBridge) { const activeSpecBridgeOriginPolicyIfApplicable = this.state('currentActiveOriginPolicy') || undefined // @ts-ignore - const { superDomainOriginPolicy: originPolicyThatIsSoonToBeOrIsActive } = Cypress.Location.create(this.state('anticipatingCrossOriginResponse')?.href || this.state('url')) + const { originPolicy: originPolicyThatIsSoonToBeOrIsActive } = Cypress.Location.create(this.state('anticipatingCrossOriginResponse')?.href || this.state('url')) if (activeSpecBridgeOriginPolicyIfApplicable && activeSpecBridgeOriginPolicyIfApplicable === originPolicyThatIsSoonToBeOrIsActive) { Cypress.emit('request:snapshot:from:spec:bridge', { diff --git a/packages/network/lib/cors.ts b/packages/network/lib/cors.ts index a788363fd01f..b55e7a3b1452 100644 --- a/packages/network/lib/cors.ts +++ b/packages/network/lib/cors.ts @@ -74,10 +74,6 @@ export function getDomainNameFromParsedHost (parsedHost: ParsedHost) { return _.compact([parsedHost.domain, parsedHost.tld]).join('.') } -export function urlMatchesSuperDomainOriginPolicyProps (urlStr, props) { - return urlMatchesSameSitePolicyProps(urlStr, props, true) -} - export function urlMatchesOriginPolicyProps (urlStr, props) { if (!props) { return false @@ -124,10 +120,6 @@ export function urlOriginsMatch (url1: string, url2: string) { return urlMatchesOriginPolicyProps(url1, parseUrlIntoHostProtocolDomainTldPort(url2)) } -export function urlsSuperDomainOriginPolicyMatch (url1: string, url2: string) { - return urlSameSiteMatch(url1, url2, true) -} - /** * Whether or not a url's scheme, domain, and top-level domain match to determine whether or not * a cookie is considered first-party. See https://developer.mozilla.org/en-US/docs/Web/HTTP/Cookies#third-party_cookies diff --git a/packages/proxy/lib/http/response-middleware.ts b/packages/proxy/lib/http/response-middleware.ts index cc101ee8c97e..bfa2ffc684a8 100644 --- a/packages/proxy/lib/http/response-middleware.ts +++ b/packages/proxy/lib/http/response-middleware.ts @@ -53,9 +53,9 @@ function getNodeCharsetFromResponse (headers: IncomingHttpHeaders, body: Buffer, return 'latin1' } -function reqMatchesSuperOriginOriginPolicy (req: CypressIncomingRequest, remoteState) { +function reqMatchesOriginPolicy (req: CypressIncomingRequest, remoteState) { if (remoteState.strategy === 'http') { - return cors.urlMatchesSuperDomainOriginPolicyProps(req.proxiedUrl, remoteState.props) + return cors.urlMatchesOriginPolicyProps(req.proxiedUrl, remoteState.props) } if (remoteState.strategy === 'file') { @@ -248,7 +248,7 @@ const SetInjectionLevel: ResponseMiddleware = function () { this.debug('determine injection') - const isReqMatchOriginPolicy = reqMatchesSuperOriginOriginPolicy(this.req, this.remoteStates.current()) + const isReqMatchOriginPolicy = reqMatchesOriginPolicy(this.req, this.remoteStates.current()) const getInjectionLevel = () => { if (this.incomingRes.headers['x-cypress-file-server-error'] && !this.res.isInitial) { this.debug('- partial injection (x-cypress-file-server-error)') @@ -256,7 +256,7 @@ const SetInjectionLevel: ResponseMiddleware = function () { return 'partial' } - const isCrossOrigin = !reqMatchesSuperOriginOriginPolicy(this.req, this.remoteStates.getPrimary()) + const isCrossOrigin = !reqMatchesOriginPolicy(this.req, this.remoteStates.getPrimary()) const isAUTFrame = this.req.isAUTFrame if (this.config.experimentalSessionAndOrigin && isCrossOrigin && isAUTFrame && (isHTML || isRenderedHTML)) { diff --git a/packages/server/lib/remote_states.ts b/packages/server/lib/remote_states.ts index 4dae69c47290..4bc9c9e15c90 100644 --- a/packages/server/lib/remote_states.ts +++ b/packages/server/lib/remote_states.ts @@ -53,7 +53,7 @@ export class RemoteStates { } get (url: string) { - const state = this.remoteStates.get(cors.getSuperDomainOriginPolicy(url)) + const state = this.remoteStates.get(cors.getOriginPolicy(url)) debug('getting remote state: %o for: %s', state, url) @@ -69,7 +69,7 @@ export class RemoteStates { } isPrimaryOrigin (url: string): boolean { - return this.primaryOriginKey === cors.getSuperDomainOriginPolicy(url) + return this.primaryOriginKey === cors.getOriginPolicy(url) } reset () { @@ -91,7 +91,7 @@ export class RemoteStates { if (_.isString(urlOrState)) { const remoteOrigin = uri.origin(urlOrState) - const { subdomain: _unused, ...remoteProps } = cors.parseUrlIntoHostProtocolDomainTldPort(remoteOrigin) + const remoteProps = cors.parseUrlIntoHostProtocolDomainTldPort(remoteOrigin) if ((urlOrState === '') || !fullyQualifiedRe.test(urlOrState)) { state = { @@ -116,7 +116,7 @@ export class RemoteStates { state = urlOrState } - const remoteOriginPolicy = cors.getSuperDomainOriginPolicy(state.origin) + const remoteOriginPolicy = cors.getOriginPolicy(state.origin) this.currentOriginKey = remoteOriginPolicy diff --git a/packages/server/lib/server-e2e.ts b/packages/server/lib/server-e2e.ts index 7952f6a5520a..a50c2af2b66b 100644 --- a/packages/server/lib/server-e2e.ts +++ b/packages/server/lib/server-e2e.ts @@ -307,7 +307,7 @@ export class ServerE2E extends ServerBase { // TODO: think about moving this logic back into the frontend so that the driver can be in control // of when to buffer and set the remote state if (isOk && details.isHtml) { - const isCrossOrigin = options.hasAlreadyVisitedUrl && !cors.urlsSuperDomainOriginPolicyMatch(primaryRemoteState.origin, newUrl || '') || options.isFromSpecBridge + const isCrossOrigin = options.hasAlreadyVisitedUrl && !cors.urlOriginsMatch(primaryRemoteState.origin, newUrl || '') || options.isFromSpecBridge if (!handlingLocalFile) { this._remoteStates.set(newUrl as string, options, !isCrossOrigin)