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: support ct/e2e specific overrides in cypress.json #15444

Merged
merged 10 commits into from
Mar 13, 2021
563 changes: 288 additions & 275 deletions cli/schema/cypress.schema.json

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion cli/types/cypress.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ declare namespace Cypress {
type RequestBody = string | object
type ViewportOrientation = 'portrait' | 'landscape'
type PrevSubject = 'optional' | 'element' | 'document' | 'window'
type PluginConfig = (on: PluginEvents, config: PluginConfigOptions) => void | ConfigOptions | Promise<ConfigOptions>
type PluginConfig = (on: PluginEvents, config: PluginConfigOptions, mode: 'e2e' | 'component') => void | ConfigOptions | Promise<ConfigOptions>

interface CommandOptions {
prevSubject: boolean | PrevSubject | PrevSubject[]
Expand Down
6 changes: 5 additions & 1 deletion npm/react/cypress/plugins/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,11 @@ const webpackConfig = {
/**
* @type Cypress.PluginConfig
*/
module.exports = (on, config) => {
module.exports = (on, config, mode) => {
if (mode !== 'component') {
throw Error('This is an component project. mode should be `component`.')
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 good way to test that mode is passed correctly. We expect this project to be only used with runner-ct.

}

on('dev-server:start', (options) => {
return startDevServer({ options, webpackConfig, disableLazyCompilation: false })
})
Expand Down
6 changes: 5 additions & 1 deletion npm/vue/cypress/plugins/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,11 @@ const webpackConfig = require('../../webpack.config')
/**
* @type Cypress.PluginConfig
*/
module.exports = (on, config) => {
module.exports = (on, config, mode) => {
if (mode !== 'component') {
throw Error('This is a component testing project. mode should be `component`.')
JessicaSachs marked this conversation as resolved.
Show resolved Hide resolved
}

require('@cypress/code-coverage/task')(on, config)
on('dev-server:start', (options) => startDevServer({ options, webpackConfig }))

Expand Down
3 changes: 2 additions & 1 deletion packages/server-ct/src/project-ct.ts
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ export class ProjectCt extends ProjectBase<ServerCt> {
this.server.socket.changeToUrl(targetUrl)
}

open (options) {
open (options: Record<string, unknown>) {
JessicaSachs marked this conversation as resolved.
Show resolved Hide resolved
this._server = new ServerCt()

return super.open(options, {
Expand Down Expand Up @@ -85,6 +85,7 @@ export class ProjectCt extends ProjectBase<ServerCt> {
return plugins.init(allowedCfg, {
projectRoot: this.projectRoot,
configFile: settings.pathToConfigFile(this.projectRoot, options),
mode: options.mode,
})
.then((modifiedCfg) => {
debug('plugin config yielded: %o', modifiedCfg)
Expand Down
2 changes: 1 addition & 1 deletion packages/server/lib/open_project.js
Original file line number Diff line number Diff line change
Expand Up @@ -328,7 +328,7 @@ const moduleFactory = () => {
debug('opening project %s', path)
debug('and options %o', options)

return openProject.open(options)
return openProject.open({ ...options, mode: args.testingType })
.return(this)
},
}
Expand Down
14 changes: 10 additions & 4 deletions packages/server/lib/plugins/child/run_plugins.js
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,13 @@ const getDefaultPreprocessor = function (config) {

let plugins

const load = (ipc, config, pluginsFile) => {
/**
* @param {EventEmitter} ipc
* @param {object} config
* @param {string} pluginsFile
* @param {'component' | 'e2e'} string
*/
const load = (ipc, config, pluginsFile, mode) => {
debug('run plugins function')

let eventIdCount = 0
Expand Down Expand Up @@ -87,7 +93,7 @@ const load = (ipc, config, pluginsFile) => {
.try(() => {
debug('run plugins function')

return plugins(register, config)
return plugins(register, config, mode)
})
.tap(() => {
if (!registeredEventsByName['file:preprocessor']) {
Expand Down Expand Up @@ -192,10 +198,10 @@ const runPlugins = (ipc, pluginsFile, projectRoot) => {
return
}

ipc.on('load', (config) => {
ipc.on('load', (config, mode) => {
debug('plugins load file "%s"', pluginsFile)
debug('passing config %o', config)
load(ipc, config, pluginsFile)
load(ipc, config, pluginsFile, mode)
})

ipc.on('execute', (event, ids, args) => {
Expand Down
2 changes: 1 addition & 1 deletion packages/server/lib/plugins/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -113,7 +113,7 @@ const init = (config, options) => {
version: pkg.version,
})

ipc.send('load', config)
ipc.send('load', config, options.mode)

ipc.on('loaded', (newCfg, registrations) => {
_.omit(config, 'projectRoot', 'configFile')
Expand Down
3 changes: 2 additions & 1 deletion packages/server/lib/project-e2e.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ export class ProjectE2E extends ProjectBase<ServerE2E> {
return 'e2e'
}

open (options) {
open (options: Record<string, unknown>) {
this._server = new ServerE2E()

return super.open(options, {
Expand Down Expand Up @@ -59,6 +59,7 @@ export class ProjectE2E extends ProjectBase<ServerE2E> {
return plugins.init(cfg, {
projectRoot: this.projectRoot,
configFile: settings.pathToConfigFile(this.projectRoot, options),
mode: options.mode,
onError (err) {
debug('got plugins error', err.stack)

Expand Down
14 changes: 14 additions & 0 deletions packages/server/lib/util/settings.js
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,10 @@ module.exports = {
}, _.cloneDeep(obj))
},

isComponentTesting (options = {}) {
return options.experimentalComponentTesting || options.componentTesting || options.testingType === 'component'
},
Copy link
Contributor Author

Choose a reason for hiding this comment

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

We have a lot of flags for CT, apparently... we should reduce these to just one or two eventually.

Copy link
Contributor

Choose a reason for hiding this comment

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

Oy vey. Yeah we need to do this like ASAP.


configFile (options = {}) {
return options.configFile === false ? false : (options.configFile || 'cypress.json')
},
Expand Down Expand Up @@ -151,6 +155,16 @@ module.exports = {
.catch({ code: 'ENOENT' }, () => {
return this._write(file, {})
}).then((json = {}) => {
if (this.isComponentTesting(options) && 'component' in json) {
json = { ...json, ...json.component }
delete json.component
}

if (!this.isComponentTesting(options) && 'e2e' in json) {
json = { ...json, ...json.e2e }
delete json.e2e
}

const changed = this._applyRewriteRules(json)

// if our object is unchanged
Expand Down
1 change: 1 addition & 0 deletions packages/server/test/integration/plugins_spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ describe('lib/plugins', () => {

const options = {
onWarning,
mode: 'e2e',
}

return plugins.init(projectConfig, options)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,11 @@ const { expect } = require('chai')
const fse = require('fs-extra')
const path = require('path')

module.exports = (on, config) => {
module.exports = (on, config, mode) => {
if (mode !== 'e2e') {
throw Error('This is an e2e project. mode should be `e2e`.')
}

const parentPid = process.ppid
let { PATH_TO_CHROME_PROFILE } = config.env

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,11 @@ const webpackConfig = {
/**
* @type Cypress.PluginConfig
*/
module.exports = (on, config) => {
module.exports = (on, config, mode) => {
if (mode !== 'e2e') {
throw Error('This is an e2e project. mode should be `e2e`.')
}

require('@cypress/code-coverage/task')(on, config)
on('dev-server:start', (options) => startDevServer({ options, webpackConfig }))

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,11 @@ const { useFixedFirefoxResolution } = require('../../../utils')
/**
* @type {Cypress.PluginConfig}
*/
module.exports = (on, config) => {
module.exports = (on, config, mode) => {
if (mode !== 'e2e') {
throw Error('This is an e2e project. mode should be `e2e`.')
}

let performance = {
track: () => Promise.resolve(),
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,11 @@ let timings = []
let rss = []
let intervalId

module.exports = (on, config) => {
module.exports = (on, config, mode) => {
if (mode !== 'e2e') {
throw Error('This is an e2e project. mode should be `e2e`.')
}

on('task', {
'console' (...args) {
console.log(...args)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -109,7 +109,11 @@ const getHandlersByType = (type) => {
}
}

module.exports = (on, config) => {
module.exports = (on, config, mode) => {
if (mode !== 'e2e') {
throw Error('This is an e2e project. mode should be `e2e`.')
}

const beforeBrowserLaunchHandler = config.env.BEFORE_BROWSER_LAUNCH_HANDLER

if (!beforeBrowserLaunchHandler) {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
const semver = require('semver')

module.exports = (on, config) => {
module.exports = (on, config, mode) => {
if (mode !== 'e2e') {
throw Error('This is an e2e project. mode should be `e2e`.')
}

if (!semver.valid(config.version)) {
throw new Error('config.version is invalid')
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,8 @@
module.exports = (on, config) => {
module.exports = (on, config, mode) => {
if (mode !== 'e2e') {
throw Error('This is an e2e project. mode should be `e2e`.')
}

return new Promise((resolve) => {
setTimeout(resolve, 100)
})
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,8 @@
module.exports = (on, config) => {
module.exports = (on, config, mode) => {
if (mode !== 'e2e') {
throw Error('This is an e2e project. mode should be `e2e`.')
}

if (config.env.NO_MUTATE_RETURN) {
on('before:browser:launch', (browser, options) => {
// this will emit a warning
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,11 @@
const fs = require('fs')
const { expect } = require('chai')

module.exports = (on, config) => {
module.exports = (on, config, mode) => {
if (mode !== 'e2e') {
throw Error('This is an e2e project. mode should be `e2e`.')
}

expect(process.geteuid()).to.not.eq(0)
console.log('✅ not running as root')

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,11 @@ const { useFixedFirefoxResolution } = require('../../../utils')
/**
* @type {Cypress.PluginConfig}
*/
module.exports = (on, config) => {
module.exports = (on, config, mode) => {
if (mode !== 'e2e') {
throw Error('This is an e2e project. mode should be `e2e`.')
}

on('before:browser:launch', (browser, options) => {
useFixedFirefoxResolution(browser, options, config)

Expand Down
36 changes: 36 additions & 0 deletions packages/server/test/unit/settings_spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,42 @@ describe('lib/settings', () => {
})
})

it('promises cypress.json and merges CT specific properties for via testingType: component', function () {
return this.setup({ a: 'b', component: { a: 'c' } })
.then(() => {
return settings.read(projectRoot, { testingType: 'component' })
}).then((obj) => {
expect(obj).to.deep.eq({ a: 'c' })
})
})

it('promises cypress.json and merges CT specific properties for via componentTesting: true', function () {
return this.setup({ a: 'b', component: { a: 'c' } })
.then(() => {
return settings.read(projectRoot, { componentTesting: true })
}).then((obj) => {
expect(obj).to.deep.eq({ a: 'c' })
})
})

it('promises cypress.json and merges CT specific properties for via experimentalComponentTesting: true', function () {
return this.setup({ a: 'b', component: { a: 'c' } })
.then(() => {
return settings.read(projectRoot, { experimentalComponentTesting: true })
}).then((obj) => {
expect(obj).to.deep.eq({ a: 'c' })
})
})

it('promises cypress.json and merges e2e specific properties', function () {
return this.setup({ a: 'b', e2e: { a: 'c' } })
.then(() => {
return settings.read(projectRoot)
}).then((obj) => {
expect(obj).to.deep.eq({ a: 'c' })
})
})

it('renames commandTimeout -> defaultCommandTimeout', function () {
return this.setup({ commandTimeout: 30000, foo: 'bar' })
.then(() => {
Expand Down