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: Improve simulated top cookie handling #23872

Merged
merged 15 commits into from
Oct 3, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
15 commits
Select commit Hold shift + click to select a range
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
9 changes: 5 additions & 4 deletions packages/app/src/runner/aut-iframe.ts
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,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
*/
doesAUTMatchTopOriginPolicy = () => {
doesAUTMatchTopSuperDomainOrigin = () => {
const Cypress = this.eventManager.getCypress()

if (!Cypress) return true
Expand All @@ -107,7 +107,7 @@ export class AutIframe {
const locationTop = Cypress.Location.create(window.location.href)
const locationAUT = Cypress.Location.create(currentHref)

return locationTop.originPolicy === locationAUT.originPolicy || locationAUT.originPolicy === 'about://blank'
return locationTop.superDomainOrigin === locationAUT.superDomainOrigin || locationAUT.superDomainOrigin === 'about://blank'
} catch (err) {
if (err.name === 'SecurityError') {
return false
Expand Down Expand Up @@ -151,7 +151,7 @@ export class AutIframe {
}

restoreDom = (snapshot) => {
if (!this.doesAUTMatchTopOriginPolicy()) {
if (!this.doesAUTMatchTopSuperDomainOrigin()) {
/**
* 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).
Expand All @@ -162,7 +162,8 @@ export class AutIframe {
this.restoreDom(snapshot)
})

// The iframe is in a cross origin state. Remove the src attribute to adhere to same origin policy. NOTE: This should only be done ONCE.
// 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.
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 }, originPolicy) => {
Cypress.primaryOriginCommunicator.toSpecBridge(originPolicy, specBridgeResponseEvent, cy.state('duringUserTestExecution'))
Cypress.primaryOriginCommunicator.on('sync:during:user:test:execution', ({ specBridgeResponseEvent }, superDomainOrigin) => {
Cypress.primaryOriginCommunicator.toSpecBridge(superDomainOrigin, 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', (originPolicy) => {
this.localBus.emit('expect:origin', originPolicy)
Cypress.primaryOriginCommunicator.on('expect:origin', (superDomainOrigin) => {
this.localBus.emit('expect:origin', superDomainOrigin)
})

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

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

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

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

notifyCrossOriginBridgeReady (originPolicy) {
notifyCrossOriginBridgeReady (superDomainOrigin) {
// 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, originPolicy)
Cypress.primaryOriginCommunicator.emit('bridge:ready', undefined, superDomainOrigin)
}

snapshotUnpinned () {
Expand Down
8 changes: 4 additions & 4 deletions packages/app/src/runner/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,7 @@ function createIframeModel () {
autIframe.detachDom,
autIframe.restoreDom,
autIframe.highlightEl,
autIframe.doesAUTMatchTopOriginPolicy,
autIframe.doesAUTMatchTopSuperDomainOrigin,
getEventManager(),
{
selectorPlaygroundModel: getEventManager().selectorPlaygroundModel,
Expand Down 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.originPolicy}`
const id = `Spec Bridge: ${location.superDomainOrigin}`

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

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.originPolicy}/${getRunnerConfigFromWindow().namespace}/spec-bridge-iframes`,
src: `${location.superDomainOrigin}/${getRunnerConfigFromWindow().namespace}/spec-bridge-iframes`,
})
}

Expand Down
4 changes: 2 additions & 2 deletions packages/driver/cypress/e2e/commands/location.cy.js
Original file line number Diff line number Diff line change
Expand Up @@ -326,7 +326,7 @@ describe('src/cy/commands/location', () => {
context('#location', () => {
it('returns the location object', () => {
cy.location().then((loc) => {
expect(loc).to.have.keys(['auth', 'authObj', 'hash', 'href', 'host', 'hostname', 'origin', 'pathname', 'port', 'protocol', 'search', 'originPolicy', 'superDomain', 'toString'])
expect(loc).to.have.keys(['auth', 'authObj', 'hash', 'href', 'host', 'hostname', 'pathname', 'port', 'protocol', 'search', 'origin', 'superDomainOrigin', 'superDomain', 'toString'])
})
})

Expand Down Expand Up @@ -529,7 +529,7 @@ describe('src/cy/commands/location', () => {

expect(_.keys(consoleProps)).to.deep.eq(['Command', 'Yielded'])
expect(consoleProps.Command).to.eq('location')
expect(_.keys(consoleProps.Yielded)).to.deep.eq(['auth', 'authObj', 'hash', 'href', 'host', 'hostname', 'origin', 'pathname', 'port', 'protocol', 'search', 'originPolicy', 'superDomain', 'toString'])
expect(_.keys(consoleProps.Yielded)).to.deep.eq(['auth', 'authObj', 'hash', 'href', 'host', 'hostname', 'origin', 'pathname', 'port', 'protocol', 'search', 'superDomainOrigin', 'superDomain', 'toString'])
})
})
})
Expand Down
4 changes: 2 additions & 2 deletions packages/driver/cypress/e2e/commands/navigation.cy.js
Original file line number Diff line number Diff line change
Expand Up @@ -610,7 +610,7 @@ describe('src/cy/commands/navigation', () => {
})
}

it('can visit pages on the same originPolicy', () => {
it('can visit pages on the same origin', () => {
cy
.visit('http://localhost:3500/fixtures/jquery.html')
.visit('http://localhost:3500/fixtures/generic.html')
Expand Down Expand Up @@ -690,7 +690,7 @@ describe('src/cy/commands/navigation', () => {
})
})

it('can visit relative pages on the same originPolicy', () => {
it('can visit relative pages on the same origin', () => {
// as long as we are already on the localhost:3500
// domain this will work
cy
Expand Down
70 changes: 60 additions & 10 deletions packages/driver/cypress/e2e/cypress/location.cy.js
Original file line number Diff line number Diff line change
Expand Up @@ -203,51 +203,101 @@ describe('src/cypress/location', () => {
})
})

context('#getOriginPolicy', () => {
context('#getOrigin', () => {
it('handles ip addresses', function () {
const str = this.setup('local').getOrigin()

expect(str).to.eq('http://127.0.0.1:8080')
})

it('handles 1 part localhost', function () {
const str = this.setup('users').getOrigin()

expect(str).to.eq('http://localhost:2020')
})

it('handles 2 parts stack', function () {
const str = this.setup('stack').getOrigin()

expect(str).to.eq('https://stackoverflow.com')
})

it('handles subdomains google', function () {
const str = this.setup('google').getOrigin()

expect(str).to.eq('https://www.google.com')
})

it('issue: #255 two domains in the url', function () {
const str = this.setup('email').getOrigin()

expect(str).to.eq('http://localhost:3500')
})

it('handles private tlds in the public suffix', function () {
const str = this.setup('heroku').getOrigin()

expect(str).to.eq('https://example.herokuapp.com')
})

it('handles subdomains of private tlds in the public suffix', function () {
const str = this.setup('herokuSub').getOrigin()

expect(str).to.eq('https://foo.example.herokuapp.com')
})

it('falls back to dumb check when invalid tld', function () {
const str = this.setup('unknown').getOrigin()

expect(str).to.eq('http://what.is.so.unknown')
})
})

context('#getSuperDomainOrigin', () => {
it('handles ip addresses', function () {
const str = this.setup('local').getOriginPolicy()
const str = this.setup('local').getSuperDomainOrigin()

expect(str).to.eq('http://127.0.0.1:8080')
})

it('handles 1 part localhost', function () {
const str = this.setup('users').getOriginPolicy()
const str = this.setup('users').getSuperDomainOrigin()

expect(str).to.eq('http://localhost:2020')
})

it('handles 2 parts stack', function () {
const str = this.setup('stack').getOriginPolicy()
const str = this.setup('stack').getSuperDomainOrigin()

expect(str).to.eq('https://stackoverflow.com')
})

it('handles subdomains google', function () {
const str = this.setup('google').getOriginPolicy()
const str = this.setup('google').getSuperDomainOrigin()

expect(str).to.eq('https://google.com')
})

it('issue: #255 two domains in the url', function () {
const str = this.setup('email').getOriginPolicy()
const str = this.setup('email').getSuperDomainOrigin()

expect(str).to.eq('http://localhost:3500')
})

it('handles private tlds in the public suffix', function () {
const str = this.setup('heroku').getOriginPolicy()
const str = this.setup('heroku').getSuperDomainOrigin()

expect(str).to.eq('https://example.herokuapp.com')
})

it('handles subdomains of private tlds in the public suffix', function () {
const str = this.setup('herokuSub').getOriginPolicy()
const str = this.setup('herokuSub').getSuperDomainOrigin()

expect(str).to.eq('https://example.herokuapp.com')
})

it('falls back to dumb check when invalid tld', function () {
const str = this.setup('unknown').getOriginPolicy()
const str = this.setup('unknown').getSuperDomainOrigin()

expect(str).to.eq('http://so.unknown')
})
Expand All @@ -256,7 +306,7 @@ describe('src/cypress/location', () => {
context('.create', () => {
it('returns an object literal', () => {
const obj = Location.create(urls.cypress, urls.signin)
const keys = ['auth', 'authObj', 'hash', 'href', 'host', 'hostname', 'origin', 'pathname', 'port', 'protocol', 'search', 'toString', 'originPolicy', 'superDomain']
const keys = ['auth', 'authObj', 'hash', 'href', 'host', 'hostname', 'pathname', 'port', 'protocol', 'search', 'toString', 'origin', 'superDomainOrigin', 'superDomain']

expect(obj).to.have.keys(keys)
})
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ context('cy.origin location', () => {
expect(consoleProps.Yielded).to.have.property('hostname').that.is.a('string')
expect(consoleProps.Yielded).to.have.property('href').that.is.a('string')
expect(consoleProps.Yielded).to.have.property('origin').that.is.a('string')
expect(consoleProps.Yielded).to.have.property('originPolicy').that.is.a('string')
expect(consoleProps.Yielded).to.have.property('superDomainOrigin').that.is.a('string')
expect(consoleProps.Yielded).to.have.property('pathname').that.is.a('string')
expect(consoleProps.Yielded).to.have.property('port').that.is.a('string')
expect(consoleProps.Yielded).to.have.property('protocol').that.is.a('string')
Expand Down
Loading