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

chore: Initialize Cypress before secondary domain page loads #17262

Merged
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
14 changes: 14 additions & 0 deletions packages/driver/cypress/fixtures/multidomain-secondary.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
<!DOCTYPE html>
<html>
<head>
</head>
<body>
<p></p>

<script>
if (window.Cypress) {
document.querySelector('p').innerText = 'From a secondary domain with window.Cypress'
}
</script>
</body>
</html>
2 changes: 1 addition & 1 deletion packages/driver/cypress/fixtures/multidomain.html
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,6 @@
<head>
</head>
<body>
<a href="http://127.0.0.1:3501/fixtures/generic.html">Go to 127.0.0.1:3501</a>
<a href="http://127.0.0.1:3501/fixtures/multidomain-secondary.html">Go to 127.0.0.1:3501</a>
</body>
</html>
11 changes: 6 additions & 5 deletions packages/driver/cypress/integration/e2e/multidomain_spec.ts
Original file line number Diff line number Diff line change
@@ -1,22 +1,23 @@
// FIXME: Skip this for now since it's flaky
it.skip('verifies initial implementation of sibling iframe and switchToDomain', (done) => {
top.addEventListener('message', (event) => {
if (event.data && event.data.text) {
expect(event.data.text).to.equal('Foo')
if (event.data && event.data.textFromParagraph !== undefined) {
expect(event.data.host).to.equal('127.0.0.1:3501')
expect(event.data.textFromParagraph).to.equal('From a secondary domain with window.Cypress')
done()
}
}, false)

cy.state('anticipateMultidomain', true)
cy.viewport(900, 300)
cy.visit('/fixtures/multidomain.html')
// @ts-ignore
cy.anticipateMultidomain()
Copy link
Contributor Author

Choose a reason for hiding this comment

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

This is a temporary measure to enable setting up the cross-domain bridge iframe. Once we tackle #17252, we'll look ahead to the cy.switchToDomain command and this will no longer be required.

cy.get('a').click()
// @ts-ignore
cy.switchToDomain('127.0.0.1:3501', () => {
// @ts-ignore
cy.now('get', '.foo').then(($el) => {
top.postMessage({ host: location.host, text: $el.text() }, '*')
cy.now('get', 'p').then(($el) => {
top.postMessage({ host: location.host, textFromParagraph: $el.text() }, '*')
})
})
})
15 changes: 15 additions & 0 deletions packages/driver/src/cy/multidomain/index.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,20 @@
import Bluebird from 'bluebird'

export function addCommands (Commands, Cypress: Cypress.Cypress, cy: Cypress.cy, state: Cypress.State) {
Commands.addAll({
anticipateMultidomain () {
state('anticipateMultidomain', true)

return new Bluebird((resolve) => {
// @ts-ignore
Cypress.once('cross:domain:bridge:ready', () => {
resolve()
})

Cypress.action('cy:expect:domain', '127.0.0.1:3501')
})
},

switchToDomain (domain, fn) {
Cypress.log({
name: 'switchToDomain',
Expand Down
24 changes: 12 additions & 12 deletions packages/driver/src/cypress.js
Original file line number Diff line number Diff line change
Expand Up @@ -476,18 +476,6 @@ class $Cypress {
case 'cy:scrolled':
return this.emit('scrolled', ...args)

case 'app:cross:domain:window:load':
return this.emit('cross:domain:window:load', args[0])

case 'cy:switch:domain':
return this.emit('switch:domain', args[0])

case 'runner:cross:domain:driver:ready':
return this.emit('cross:domain:driver:ready')

case 'cy:cross:domain:message':
return this.emit('cross:domain:message', ...args)

case 'app:uncaught:exception':
return this.emitMap('uncaught:exception', ...args)

Expand Down Expand Up @@ -535,6 +523,18 @@ class $Cypress {
case 'spec:script:error':
return this.emit('script:error', ...args)

// multidomain messages
// TODO: consider moving these elsewhere if they grow too
// large in number
case 'cy:expect:domain':
return this.emit('expect:domain', args[0])

case 'runner:cross:domain:bridge:ready':
return this.emit('cross:domain:bridge:ready')

case 'cy:cross:domain:message':
return this.emit('cross:domain:message', ...args)

default:
return
}
Expand Down
10 changes: 1 addition & 9 deletions packages/driver/src/cypress/cy.js
Original file line number Diff line number Diff line change
Expand Up @@ -1054,15 +1054,7 @@ const create = function (specWindow, Cypress, Cookies, state, config, log) {
// temporary hack so that other tests expecting cross-origin
// failures still fail as expected
if (state('anticipateMultidomain')) {
Cypress.once('cross:domain:window:load', () => {
Cypress.once('cross:domain:driver:ready', () => {
stability.isStable(true, 'load')
})

Cypress.action('cy:switch:domain', '127.0.0.1:3501')
})

return
return stability.isStable(true, 'load')
}

let e = err
Expand Down
13 changes: 7 additions & 6 deletions packages/driver/src/multidomain/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import $Cy from '../cypress/cy'
import $Commands from '../cypress/commands'
import $Log from '../cypress/log'

export const initialize = (autWindow) => {
const onBeforeAppWindowLoad = (autWindow) => {
const specWindow = {
Error,
}
Expand Down Expand Up @@ -50,11 +50,12 @@ export const initialize = (autWindow) => {
}
}, false)

top.postMessage('cross:domain:driver:ready', '*')

autWindow.Cypress = Cypress
autWindow.cy = cy

return {
cy,
}
top.postMessage('cross:domain:window:before:load', '*')
}

window.__onBeforeAppWindowLoad = onBeforeAppWindowLoad

top.postMessage('cross:domain:bridge:ready', '*')
12 changes: 6 additions & 6 deletions packages/runner-shared/src/event-manager.js
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ const driverToReporterEvents = 'paused before:firefox:force:gc after:firefox:for
const driverToLocalAndReporterEvents = 'run:start run:end'.split(' ')
const driverToSocketEvents = 'backend:request automation:request mocha recorder:frame'.split(' ')
const driverTestEvents = 'test:before:run:async test:after:run'.split(' ')
const driverToLocalEvents = 'viewport:changed config stop url:changed page:loading visit:failed switch:domain'.split(' ')
const driverToLocalEvents = 'viewport:changed config stop url:changed page:loading visit:failed expect:domain'.split(' ')
const socketRerunEvents = 'runner:restart watched:file:changed'.split(' ')
const socketToDriverEvents = 'net:event script:error'.split(' ')
const localToReporterEvents = 'reporter:log:add reporter:log:state:changed reporter:log:remove'.split(' ')
Expand Down Expand Up @@ -303,15 +303,15 @@ export const eventManager = {

top.addEventListener('message', (event) => {
switch (event.data) {
case 'app:cross:domain:window:load':
return Cypress.action('app:cross:domain:window:load')
case 'cross:domain:driver:ready':
case 'cross:domain:window:before:load':
this.crossDomainDriverWindow = event.source

return Cypress.action('runner:cross:domain:driver:ready')
return
case 'cross:domain:bridge:ready':
return Cypress.action('runner:cross:domain:bridge:ready')
default:
// eslint-disable-next-line no-console
console.log('Unknown postMessage:', event.data)
console.log('Unexpected postMessage:', event.data)
}
}, false)
},
Expand Down
11 changes: 6 additions & 5 deletions packages/runner/injection/multidomain.js
Original file line number Diff line number Diff line change
Expand Up @@ -33,8 +33,9 @@

// timers.wrap()

// TODO: change this to be window:before:load once coordination with
// driver is fleshed out better
window.addEventListener('load', () => {
window.top.postMessage('app:cross:domain:window:load', '*')
})
// TODO: don't hard-code the index. need it to be predictable or need
// to search for the right one somehow. will need to be fixed when we
// test out visiting a 3rd domain
const cyBridgeFrame = window.parent.frames[2]

cyBridgeFrame.__onBeforeAppWindowLoad(window)
25 changes: 1 addition & 24 deletions packages/runner/multidomain/index.js
Original file line number Diff line number Diff line change
@@ -1,24 +1 @@
import { initialize } from '@packages/driver/src/multidomain'

initialize(window.parent.frames[0])

/*

Need:
- Cypress
- cy, with
- built-in commands
- user-defined commands

Commands need:
- state
- config
- events

Don't need:
- UI components
- spec runner
- mocha
- wasm / source map utils

*/
import '@packages/driver/src/multidomain'
2 changes: 1 addition & 1 deletion packages/runner/src/iframe/iframes.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,7 @@ export default class Iframes extends Component {

this.props.eventManager.on('print:selector:elements:to:console', this._printSelectorElementsToConsole)

this.props.eventManager.on('switch:domain', this._addCrossDomainIframe)
this.props.eventManager.on('expect:domain', this._addCrossDomainIframe)

this._disposers.push(autorun(() => {
this.autIframe.toggleSelectorPlayground(selectorPlaygroundModel.isEnabled)
Expand Down