From 0bebd345ddabae0042ea339850b2f08f00d1fa37 Mon Sep 17 00:00:00 2001 From: Chris Breiding Date: Tue, 27 Apr 2021 09:36:46 -0400 Subject: [PATCH 1/4] add multidomain bundle --- packages/driver/src/cypress.js | 2 + packages/driver/src/cypress/commands.js | 10 +++-- packages/runner/multidomain/.eslintrc.json | 5 +++ packages/runner/multidomain/index.js | 47 ++++++++++++++++++++++ packages/runner/webpack.config.ts | 15 ++++++- packages/web-config/webpack.config.base.ts | 35 ++++++++++++---- 6 files changed, 101 insertions(+), 13 deletions(-) create mode 100644 packages/runner/multidomain/.eslintrc.json create mode 100644 packages/runner/multidomain/index.js diff --git a/packages/driver/src/cypress.js b/packages/driver/src/cypress.js index 7b90a927d109..37999280bc52 100644 --- a/packages/driver/src/cypress.js +++ b/packages/driver/src/cypress.js @@ -211,6 +211,8 @@ class $Cypress { // wire up command create to cy this.Commands = $Commands.create(this, this.cy, this.state, this.config) + this.Commands.addBuiltins() + this.events.proxyTo(this.cy) $FirefoxForcedGc.install(this) diff --git a/packages/driver/src/cypress/commands.js b/packages/driver/src/cypress/commands.js index 89d6c737bbd8..fa6c6059a291 100644 --- a/packages/driver/src/cypress/commands.js +++ b/packages/driver/src/cypress/commands.js @@ -188,11 +188,13 @@ const create = (Cypress, cy, state, config) => { overwrite (name, fn) { return storeOverride(name, fn) }, - } - // perf loop - for (let cmd of builtInCommands) { - cmd(Commands, Cypress, cy, state, config) + addBuiltins () { + // perf loop + for (let cmd of builtInCommands) { + cmd(Commands, Cypress, cy, state, config) + } + }, } return Commands diff --git a/packages/runner/multidomain/.eslintrc.json b/packages/runner/multidomain/.eslintrc.json new file mode 100644 index 000000000000..0d7b491c8f62 --- /dev/null +++ b/packages/runner/multidomain/.eslintrc.json @@ -0,0 +1,5 @@ +{ + "globals": { + "window": true + } +} diff --git a/packages/runner/multidomain/index.js b/packages/runner/multidomain/index.js new file mode 100644 index 000000000000..f4d79db2d0dc --- /dev/null +++ b/packages/runner/multidomain/index.js @@ -0,0 +1,47 @@ +import $Commands from '@packages/driver/src/cypress/commands' +import addLocalStorageCommands from '@packages/driver/src/cy/commands/local_storage' + +const autWindow = window.parent.frames[0] + +const Cypress = { + prependListener () {}, + log () {}, +} +const cy = { + addCommand ({ name, fn }) { + cy[name] = fn + }, +} +const state = (key) => { + if (key === 'window') { + return autWindow + } +} +const Commands = $Commands.create(Cypress, cy, state) + +addLocalStorageCommands(Commands, Cypress, cy, state) + +autWindow.onReady = () => { + cy.clearLocalStorage() +} + +/* + +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 + +*/ diff --git a/packages/runner/webpack.config.ts b/packages/runner/webpack.config.ts index 6803ea617aca..89d061e89a3b 100644 --- a/packages/runner/webpack.config.ts +++ b/packages/runner/webpack.config.ts @@ -91,4 +91,17 @@ const injectionConfig: webpack.Configuration = { }, } -export default [mainConfig, injectionConfig] +// @ts-ignore +const multiDomainConfig: webpack.Configuration = { + mode: 'development', + ...getSimpleConfig(), + entry: { + cypress_multidomain_runner: [path.resolve(__dirname, 'multidomain/index.js')], + }, + output: { + path: path.resolve(__dirname, 'dist'), + filename: '[name].js', + }, +} + +export default [mainConfig, injectionConfig, multiDomainConfig] diff --git a/packages/web-config/webpack.config.base.ts b/packages/web-config/webpack.config.base.ts index 51486df217f6..cdebc14dcb62 100644 --- a/packages/web-config/webpack.config.base.ts +++ b/packages/web-config/webpack.config.base.ts @@ -97,6 +97,12 @@ function makeSassLoaders ({ modules }): RuleSetRule { } } +// the chrome version should be synced with +// npm/webpack-batteries-included-preprocessor/index.js and +// packages/server/lib/browsers/chrome.ts +const babelPresetEnvConfig = [require.resolve('@babel/preset-env'), { targets: { 'chrome': '64' } }] +const babelPresetTypeScriptConfig = [require.resolve('@babel/preset-typescript'), { allowNamespaces: true }] + export const getCommonConfig = () => { const commonConfig: Configuration = { mode: 'none', @@ -128,12 +134,9 @@ export const getCommonConfig = () => { [require.resolve('@babel/plugin-proposal-class-properties'), { loose: true }], ], presets: [ - // the chrome version should be synced with - // npm/webpack-batteries-included-preprocessor/index.js and - // packages/server/lib/browsers/chrome.ts - [require.resolve('@babel/preset-env'), { targets: { 'chrome': '64' } }], + babelPresetEnvConfig, require.resolve('@babel/preset-react'), - [require.resolve('@babel/preset-typescript'), { allowNamespaces: true }], + babelPresetTypeScriptConfig, ], babelrc: false, }, @@ -217,7 +220,7 @@ export const getCommonConfig = () => { // eslint-disable-next-line @cypress/dev/arrow-body-multiline-braces export const getSimpleConfig = () => ({ resolve: { - extensions: ['.js'], + extensions: ['.js', '.ts'], }, stats, @@ -228,18 +231,34 @@ export const getSimpleConfig = () => ({ module: { rules: [ { - test: /\.(js)$/, + test: /\.(js|ts)$/, exclude: /node_modules/, use: { loader: require.resolve('babel-loader'), options: { presets: [ - [require.resolve('@babel/preset-env'), { targets: { 'chrome': 63 } }], + babelPresetEnvConfig, + babelPresetTypeScriptConfig, ], babelrc: false, }, }, }, + // FIXME: we don't actually want or need wasm support in the + // multidomain bundle that uses this config, but we need to refactor + // the driver so that it doesn't load the wasm code in + // packages/driver/src/cypress/source_map_utils.js when creating + // the multidomain bundle. for now, this is necessary so the build + // doesn't fail + { + test: /\.wasm$/, + type: 'javascript/auto', + use: [ + { + loader: require.resolve('arraybuffer-loader'), + }, + ], + }, ], }, From 79edbd9344772a632174d65f0566448f83faaf41 Mon Sep 17 00:00:00 2001 From: Chris Breiding Date: Tue, 27 Apr 2021 09:37:20 -0400 Subject: [PATCH 2/4] add a spec for manually testing and experimenting with multidomain bundle --- .../cypress/fixtures/multidomain-aut.html | 19 +++++++++++++++++++ .../cypress/fixtures/multidomain-sibling.html | 8 ++++++++ .../driver/cypress/fixtures/multidomain.html | 9 +++++++++ .../integration/e2e/multidomain_spec.ts | 5 +++++ packages/driver/cypress/plugins/server.js | 8 ++++++++ 5 files changed, 49 insertions(+) create mode 100644 packages/driver/cypress/fixtures/multidomain-aut.html create mode 100644 packages/driver/cypress/fixtures/multidomain-sibling.html create mode 100644 packages/driver/cypress/fixtures/multidomain.html create mode 100644 packages/driver/cypress/integration/e2e/multidomain_spec.ts diff --git a/packages/driver/cypress/fixtures/multidomain-aut.html b/packages/driver/cypress/fixtures/multidomain-aut.html new file mode 100644 index 000000000000..d41e8af04ec8 --- /dev/null +++ b/packages/driver/cypress/fixtures/multidomain-aut.html @@ -0,0 +1,19 @@ + + + + + + +

Multidomain AUT

+ + diff --git a/packages/driver/cypress/fixtures/multidomain-sibling.html b/packages/driver/cypress/fixtures/multidomain-sibling.html new file mode 100644 index 000000000000..d10ec54b3eb0 --- /dev/null +++ b/packages/driver/cypress/fixtures/multidomain-sibling.html @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/packages/driver/cypress/fixtures/multidomain.html b/packages/driver/cypress/fixtures/multidomain.html new file mode 100644 index 000000000000..f5a1107a98b0 --- /dev/null +++ b/packages/driver/cypress/fixtures/multidomain.html @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/packages/driver/cypress/integration/e2e/multidomain_spec.ts b/packages/driver/cypress/integration/e2e/multidomain_spec.ts new file mode 100644 index 000000000000..f1fac55697fe --- /dev/null +++ b/packages/driver/cypress/integration/e2e/multidomain_spec.ts @@ -0,0 +1,5 @@ +// NOTE: this test only exists for manual verification as the +// multidomain bundle is a very incomplete work-in-progress +it.skip('loads multidomain playground', () => { + cy.visit('/fixtures/multidomain.html') +}) diff --git a/packages/driver/cypress/plugins/server.js b/packages/driver/cypress/plugins/server.js index 2ee7884b5b21..d51b09c72092 100644 --- a/packages/driver/cypress/plugins/server.js +++ b/packages/driver/cypress/plugins/server.js @@ -8,6 +8,7 @@ const path = require('path') const Promise = require('bluebird') const PATH_TO_SERVER_PKG = path.dirname(require.resolve('@packages/server')) +const PATH_TO_RUNNER_PKG = path.dirname(require.resolve('@packages/runner')) const httpPorts = [3500, 3501] const httpsPort = 3502 @@ -151,6 +152,13 @@ const createApp = (port) => { .send('server error') }) + app.get('/cypress_multidomain_runner.js', (req, res) => { + res.type('application/javascript') + res.sendFile(path.join('dist', 'cypress_multidomain_runner.js'), { + root: path.join(PATH_TO_RUNNER_PKG, '..'), + }) + }) + let _var = '' app.get('/set-var', (req, res) => { From d7ced239bf12da4739f893867b3a681e800d6be5 Mon Sep 17 00:00:00 2001 From: Chris Breiding Date: Fri, 21 May 2021 10:16:40 -0400 Subject: [PATCH 3/4] get cy.now('get') functioning --- .../cypress/fixtures/multidomain-aut.html | 13 ++--- .../integration/e2e/multidomain_spec.ts | 2 +- packages/driver/src/cypress.js | 2 - packages/driver/src/cypress/commands.js | 10 ++-- packages/driver/src/cypress/cy.js | 8 +++ packages/runner/multidomain/index.js | 54 +++++++++++++------ packages/web-config/webpack.config.base.ts | 12 ++++- 7 files changed, 67 insertions(+), 34 deletions(-) diff --git a/packages/driver/cypress/fixtures/multidomain-aut.html b/packages/driver/cypress/fixtures/multidomain-aut.html index d41e8af04ec8..4a0c7d8838ce 100644 --- a/packages/driver/cypress/fixtures/multidomain-aut.html +++ b/packages/driver/cypress/fixtures/multidomain-aut.html @@ -1,19 +1,14 @@ + + +

Multidomain AUT

+

Some text in the cross-domain AUT

- - -

Multidomain AUT

diff --git a/packages/driver/cypress/integration/e2e/multidomain_spec.ts b/packages/driver/cypress/integration/e2e/multidomain_spec.ts index f1fac55697fe..81c4d8b4aaba 100644 --- a/packages/driver/cypress/integration/e2e/multidomain_spec.ts +++ b/packages/driver/cypress/integration/e2e/multidomain_spec.ts @@ -1,5 +1,5 @@ // NOTE: this test only exists for manual verification as the // multidomain bundle is a very incomplete work-in-progress -it.skip('loads multidomain playground', () => { +it('loads multidomain playground', () => { cy.visit('/fixtures/multidomain.html') }) diff --git a/packages/driver/src/cypress.js b/packages/driver/src/cypress.js index fb6e454e4614..d29cd9f27d16 100644 --- a/packages/driver/src/cypress.js +++ b/packages/driver/src/cypress.js @@ -211,8 +211,6 @@ class $Cypress { // wire up command create to cy this.Commands = $Commands.create(this, this.cy, this.state, this.config) - this.Commands.addBuiltins() - this.events.proxyTo(this.cy) $FirefoxForcedGc.install(this) diff --git a/packages/driver/src/cypress/commands.js b/packages/driver/src/cypress/commands.js index fa6c6059a291..89d6c737bbd8 100644 --- a/packages/driver/src/cypress/commands.js +++ b/packages/driver/src/cypress/commands.js @@ -188,13 +188,11 @@ const create = (Cypress, cy, state, config) => { overwrite (name, fn) { return storeOverride(name, fn) }, + } - addBuiltins () { - // perf loop - for (let cmd of builtInCommands) { - cmd(Commands, Cypress, cy, state, config) - } - }, + // perf loop + for (let cmd of builtInCommands) { + cmd(Commands, Cypress, cy, state, config) } return Commands diff --git a/packages/driver/src/cypress/cy.js b/packages/driver/src/cypress/cy.js index 939fac2b1597..cd9924054565 100644 --- a/packages/driver/src/cypress/cy.js +++ b/packages/driver/src/cypress/cy.js @@ -75,6 +75,14 @@ const setTopOnError = function (Cypress, cy) { curCy = cy + try { + // this will throw if AUT is cross-domain and we don't need to worry + // about top's error handler in that case anyway + top.__alreadySetErrorHandlers__ + } catch (err) { + return + } + // prevent overriding top.onerror twice when loading more than one // instance of test runner. if (top.__alreadySetErrorHandlers__) { diff --git a/packages/runner/multidomain/index.js b/packages/runner/multidomain/index.js index f4d79db2d0dc..fff07e25e5e5 100644 --- a/packages/runner/multidomain/index.js +++ b/packages/runner/multidomain/index.js @@ -1,28 +1,52 @@ +import $Cypress from '@packages/driver/src/cypress' +import $Cy from '@packages/driver/src/cypress/cy' import $Commands from '@packages/driver/src/cypress/commands' -import addLocalStorageCommands from '@packages/driver/src/cy/commands/local_storage' +import $Log from '@packages/driver/src/cypress/log' const autWindow = window.parent.frames[0] - -const Cypress = { - prependListener () {}, - log () {}, +const specWindow = { + Error, } -const cy = { - addCommand ({ name, fn }) { - cy[name] = fn +const Cypress = $Cypress.create({ + browser: { + channel: 'stable', + displayName: 'Chrome', + family: 'chromium', + isChosen: true, + isHeaded: true, + isHeadless: false, + majorVersion: 90, + name: 'chrome', + path: '/Applications/Google Chrome.app/Contents/MacOS/Google Chrome', + version: '90.0.4430.212', }, +}) +const log = (...args) => { + return Cypress.log.apply(this, args) } -const state = (key) => { - if (key === 'window') { - return autWindow - } +const cy = $Cy.create(specWindow, Cypress, Cypress.Cookies, Cypress.state, Cypress.config, log) + +Cypress.log = $Log.create(Cypress, cy, Cypress.state, Cypress.config) +Cypress.runner = { + addLog () {}, } -const Commands = $Commands.create(Cypress, cy, state) -addLocalStorageCommands(Commands, Cypress, cy, state) +Cypress.state('window', autWindow) +Cypress.state('document', autWindow.document) +Cypress.state('runnable', { + ctx: {}, + clearTimeout () {}, + resetTimeout () {}, + timeout () {}, +}) + +$Commands.create(Cypress, cy, Cypress.state) autWindow.onReady = () => { - cy.clearLocalStorage() + cy.now('get', 'p').then(($el) => { + // eslint-disable-next-line no-console + console.log('got the paragaph with text:', $el.text()) + }) } /* diff --git a/packages/web-config/webpack.config.base.ts b/packages/web-config/webpack.config.base.ts index cdebc14dcb62..746e8a9fa85a 100644 --- a/packages/web-config/webpack.config.base.ts +++ b/packages/web-config/webpack.config.base.ts @@ -219,8 +219,15 @@ export const getCommonConfig = () => { // eslint-disable-next-line @cypress/dev/arrow-body-multiline-braces export const getSimpleConfig = () => ({ + node: { + fs: 'empty', + child_process: 'empty', + net: 'empty', + tls: 'empty', + module: 'empty', + }, resolve: { - extensions: ['.js', '.ts'], + extensions: ['.js', '.ts', '.json'], }, stats, @@ -236,6 +243,9 @@ export const getSimpleConfig = () => ({ use: { loader: require.resolve('babel-loader'), options: { + plugins: [ + [require.resolve('@babel/plugin-proposal-class-properties'), { loose: true }], + ], presets: [ babelPresetEnvConfig, babelPresetTypeScriptConfig, From 2aafbb91d3c0d06ff3b7e046620347a5e7abaaa5 Mon Sep 17 00:00:00 2001 From: Chris Breiding Date: Fri, 21 May 2021 10:25:13 -0400 Subject: [PATCH 4/4] move majority of multidomain entry point into driver --- packages/driver/src/multidomain/index.js | 48 ++++++++++++++++++++++++ packages/runner/multidomain/index.js | 42 +-------------------- 2 files changed, 50 insertions(+), 40 deletions(-) create mode 100644 packages/driver/src/multidomain/index.js diff --git a/packages/driver/src/multidomain/index.js b/packages/driver/src/multidomain/index.js new file mode 100644 index 000000000000..5737213f923c --- /dev/null +++ b/packages/driver/src/multidomain/index.js @@ -0,0 +1,48 @@ +import $Cypress from '../cypress' +import $Cy from '../cypress/cy' +import $Commands from '../cypress/commands' +import $Log from '../cypress/log' + +export const initialize = (autWindow) => { + const specWindow = { + Error, + } + const Cypress = $Cypress.create({ + browser: { + channel: 'stable', + displayName: 'Chrome', + family: 'chromium', + isChosen: true, + isHeaded: true, + isHeadless: false, + majorVersion: 90, + name: 'chrome', + path: '/Applications/Google Chrome.app/Contents/MacOS/Google Chrome', + version: '90.0.4430.212', + }, + }) + const log = (...args) => { + return Cypress.log.apply(Cypress, args) + } + const cy = $Cy.create(specWindow, Cypress, Cypress.Cookies, Cypress.state, Cypress.config, log) + + Cypress.log = $Log.create(Cypress, cy, Cypress.state, Cypress.config) + Cypress.runner = { + addLog () {}, + } + + Cypress.state('window', autWindow) + Cypress.state('document', autWindow.document) + Cypress.state('runnable', { + ctx: {}, + clearTimeout () {}, + resetTimeout () {}, + timeout () {}, + }) + + $Commands.create(Cypress, cy, Cypress.state) + + return { + cy, + } +} diff --git a/packages/runner/multidomain/index.js b/packages/runner/multidomain/index.js index fff07e25e5e5..e72284fc337e 100644 --- a/packages/runner/multidomain/index.js +++ b/packages/runner/multidomain/index.js @@ -1,46 +1,8 @@ -import $Cypress from '@packages/driver/src/cypress' -import $Cy from '@packages/driver/src/cypress/cy' -import $Commands from '@packages/driver/src/cypress/commands' -import $Log from '@packages/driver/src/cypress/log' +import { initialize } from '@packages/driver/src/multidomain' const autWindow = window.parent.frames[0] -const specWindow = { - Error, -} -const Cypress = $Cypress.create({ - browser: { - channel: 'stable', - displayName: 'Chrome', - family: 'chromium', - isChosen: true, - isHeaded: true, - isHeadless: false, - majorVersion: 90, - name: 'chrome', - path: '/Applications/Google Chrome.app/Contents/MacOS/Google Chrome', - version: '90.0.4430.212', - }, -}) -const log = (...args) => { - return Cypress.log.apply(this, args) -} -const cy = $Cy.create(specWindow, Cypress, Cypress.Cookies, Cypress.state, Cypress.config, log) - -Cypress.log = $Log.create(Cypress, cy, Cypress.state, Cypress.config) -Cypress.runner = { - addLog () {}, -} - -Cypress.state('window', autWindow) -Cypress.state('document', autWindow.document) -Cypress.state('runnable', { - ctx: {}, - clearTimeout () {}, - resetTimeout () {}, - timeout () {}, -}) -$Commands.create(Cypress, cy, Cypress.state) +const { cy } = initialize(autWindow) autWindow.onReady = () => { cy.now('get', 'p').then(($el) => {