From ff4a8246b3edbcb7c2fadd012500ad8a50c4c3ca Mon Sep 17 00:00:00 2001 From: Chris Breiding Date: Mon, 15 Mar 2021 14:50:58 -0400 Subject: [PATCH 1/3] Revert "feat: support ct/e2e specific overrides in cypress.json (#15444)" This reverts commit a94c9d5ef0da8559f20391fc14396d71fdca7a2f. --- cli/schema/cypress.schema.json | 563 +++++++++--------- cli/types/cypress.d.ts | 2 +- npm/react/cypress/plugins/index.js | 6 +- npm/vue/cypress/plugins/index.js | 6 +- packages/server-ct/src/project-ct.ts | 3 +- packages/server/lib/open_project.js | 2 +- .../server/lib/plugins/child/run_plugins.js | 14 +- packages/server/lib/plugins/index.js | 2 +- packages/server/lib/project-e2e.ts | 3 +- packages/server/lib/util/settings.js | 14 - .../server/test/integration/plugins_spec.js | 1 - .../cypress/plugins/index.js | 6 +- .../component-tests/cypress/plugins/index.js | 6 +- .../projects/e2e/cypress/plugins/index.js | 6 +- .../firefox-memory/cypress/plugins/index.js | 6 +- .../cypress/plugins/index.js | 6 +- .../cypress/plugins/index.js | 6 +- .../plugin-config/cypress/plugins/index.js | 6 +- .../cypress/plugins/index.js | 6 +- .../cypress/plugins/index.js | 6 +- .../retries-2/cypress/plugins/index.js | 6 +- packages/server/test/unit/settings_spec.js | 36 -- 22 files changed, 296 insertions(+), 416 deletions(-) diff --git a/cli/schema/cypress.schema.json b/cli/schema/cypress.schema.json index 9312ee3095a5..7099b4b626b0 100644 --- a/cli/schema/cypress.schema.json +++ b/cli/schema/cypress.schema.json @@ -1,294 +1,281 @@ { "title": "JSON schema for the https://cypress.io Test Runner's configuration file. Details at https://on.cypress.io/configuration", "$schema": "http://json-schema.org/draft-04/schema#", - "definitions": { - "cypressConfig": { + "type": "object", + "properties": { + "baseUrl": { + "type": "string", + "description": "Url used as prefix for cy.visit() or cy.request() command’s url. Example http://localhost:3030 or https://test.my-domain.com" + }, + "env": { "type": "object", - "properties": { - "baseUrl": { - "type": "string", - "description": "Url used as prefix for cy.visit() or cy.request() command’s url. Example http://localhost:3030 or https://test.my-domain.com" - }, - "env": { - "type": "object", - "description": "Any values to be set as environment variables. See https://on.cypress.io/environment-variables", - "body": {} - }, - "ignoreTestFiles": { - "type": [ - "string", - "array" - ], - "items": { - "type": "string" - }, - "description": "A String or Array of glob patterns used to ignore test files that would otherwise be shown in your list of tests. Cypress uses minimatch with the options: {dot: true, matchBase: true}. We suggest using http://globtester.com to test what files would match." - }, - "numTestsKeptInMemory": { - "type": "number", - "default": 50, - "description": "The number of tests for which snapshots and command data are kept in memory. Reduce this number if you are experiencing high memory consumption in your browser during a test run." - }, - "port": { - "type": "number", - "default": null, - "description": "Port used to host Cypress. Normally this is a randomly generated port" - }, - "reporter": { - "type": "string", - "default": "spec", - "description": "The reporter used when running headlessly or in CI. See https://on.cypress.io/reporters" - }, - "reporterOptions": { - "type": "object", - "default": null, - "description": "The reporter options used. Supported options depend on the reporter. See https://on.cypress.io/reporters#Reporter-Options" - }, - "testFiles": { - "type": [ - "string", - "array" - ], - "default": "**/*.*", - "description": "A String or Array of string glob patterns of the test files to load. See https://on.cypress.io/configuration#Global" - }, - "watchForFileChanges": { - "type": "boolean", - "default": true, - "description": "Whether Cypress will watch and restart tests on test file changes" - }, - "defaultCommandTimeout": { - "type": "number", - "default": 4000, - "description": "Time, in milliseconds, to wait until most DOM based commands are considered timed out" - }, - "execTimeout": { - "type": "number", - "default": 60000, - "description": "Time, in milliseconds, to wait for a system command to finish executing during a cy.exec() command" - }, - "taskTimeout": { - "type": "number", - "default": 60000, - "description": "Time, in milliseconds, to wait for a task to finish executing during a cy.task() command" - }, - "pageLoadTimeout": { - "type": "number", - "default": 60000, - "description": "Time, in milliseconds, to wait for page transition events or cy.visit(), cy.go(), cy.reload() commands to fire their page load events. Network requests are limited by the underlying operating system, and may still time out if this value is increased." - }, - "requestTimeout": { - "type": "number", - "default": 5000, - "description": "Time, in milliseconds, to wait for an XHR request to go out in a cy.wait() command" - }, - "responseTimeout": { - "type": "number", - "default": 30000, - "description": "Time, in milliseconds, to wait until a response in a cy.request(), cy.wait(), cy.fixture(), cy.getCookie(), cy.getCookies(), cy.setCookie(), cy.clearCookie(), cy.clearCookies(), and cy.screenshot() commands" - }, - "fileServerFolder": { - "type": "string", - "default": "root project folder", - "description": "Path to folder where application files will attempt to be served from" - }, - "fixturesFolder": { - "type": [ - "string", - "boolean" - ], - "default": "cypress/fixtures", - "description": "Path to folder containing fixture files (Pass false to disable)" - }, - "integrationFolder": { - "type": "string", - "default": "cypress/integration", - "description": "Path to folder containing integration test files" - }, - "downloadsFolder": { - "type": "string", - "default": "cypress/downloads", - "description": "Path to folder where files downloaded during a test are saved" - }, - "experimentalComponentTesting": { - "type": "boolean", - "default": false, - "description": "Enabled experimental component testing, see https://github.com/cypress-io/cypress/issues/5922" - }, - "componentFolder": { - "type": [ - "string", - "boolean" - ], - "default": false, - "description": "Path to folder containing component test files (Pass false to disable)" - }, - "pluginsFile": { - "type": [ - "string", - "boolean" - ], - "default": "cypress/plugins/index.js", - "description": "Path to plugins file. (Pass false to disable)" - }, - "screenshotOnRunFailure": { - "type": "boolean", - "default": true, - "description": "Whether Cypress will take a screenshot when a test fails during cypress run" - }, - "screenshotsFolder": { - "type": "string", - "default": "cypress/screenshots", - "description": "Path to folder where screenshots will be saved from cy.screenshot() command or after a test fails during cypress run" - }, - "supportFile": { - "type": [ - "string", - "boolean" - ], - "default": "cypress/support/index.js", - "description": "Path to file to load before test files load. This file is compiled and bundled. (Pass false to disable)" - }, - "videosFolder": { - "type": "string", - "default": "cypress/videos", - "description": "Path to folder where videos will be saved during cypress run" - }, - "trashAssetsBeforeRuns": { - "type": "boolean", - "default": true, - "description": "Whether Cypress will trash assets within the screenshotsFolder and videosFolder before tests run with cypress run" - }, - "videoCompression": { - "type": [ - "number", - "boolean" - ], - "default": 32, - "description": "The quality setting for the video compression, in Constant Rate Factor (CRF). The value can be false to disable compression or a value between 0 and 51, where a lower value results in better quality (at the expense of a higher file size)." - }, - "video": { - "type": "boolean", - "default": true, - "description": "Whether Cypress will capture a video of the tests run with cypress run" - }, - "videoUploadOnPasses": { - "type": "boolean", - "default": true, - "description": "Whether Cypress will process, compress, and upload videos to the Dashboard even when all tests in a spec file are passing. This only applies when recording your runs to the Dashboard. Turn this off if you’d like to only upload the spec file’s video when there are failing tests." - }, - "chromeWebSecurity": { - "type": "boolean", - "default": true, - "description": "Whether Chrome Web Security for same-origin policy and insecure mixed content is enabled. Read more about this at https://on.cypress.io/web-security" - }, - "userAgent": { - "type": "string", - "default": null, - "description": "Enables you to override the default user agent the browser sends in all request headers. User agent values are typically used by servers to help identify the operating system, browser, and browser version. See User-Agent MDN Documentation for example user agent values here: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/User-Agent" - }, - "blockHosts": { - "type": [ - "string", - "array" - ], - "items": { - "type": "string" - }, - "default": null, - "description": "A String or Array of hosts that you wish to block traffic for. Please read the notes for examples on using this https://on.cypress.io/configuration#blockHosts" - }, - "modifyObstructiveCode": { - "type": "boolean", - "default": true, - "description": "Whether Cypress will search for and replace obstructive JS code found in .js or .html files that prevent Cypress from working. Please read the notes for more information on this setting. https://on.cypress.io/configuration#modifyObstructiveCode" - }, - "viewportHeight": { - "type": "number", - "default": 660, - "description": "Default height in pixels for the application under tests’ viewport (Override with cy.viewport() command)" - }, - "viewportWidth": { - "type": "number", - "default": 1000, - "description": "Default width in pixels for the application under tests’ viewport. (Override with cy.viewport() command)" - }, - "animationDistanceThreshold": { - "type": "number", - "default": 5, - "description": "The distance in pixels an element must exceed over time to be considered animating" - }, - "waitForAnimations": { - "type": "boolean", - "default": true, - "description": "Whether to wait for elements to finish animating before executing commands" - }, - "scrollBehavior": { - "enum": [ - false, - "center", - "top", - "bottom", - "nearest" - ], - "default": "top", - "description": "Viewport position to which an element should be scrolled prior to action commands. Setting `false` disables scrolling." - }, - "projectId": { - "type": "string", - "default": null, - "description": "A 6 character string use to identify this project in the Cypress Dashboard. See https://on.cypress.io/dashboard-service#Identification" - }, - "nodeVersion": { - "enum": [ - "system", - "bundled" - ], - "default": "bundled", - "description": "If set to 'system', Cypress will try to find a Node.js executable on your path to use when executing your plugins. Otherwise, Cypress will use the Node version bundled with Cypress." - }, - "experimentalSourceRewriting": { - "type": "boolean", - "default": false, - "description": "Enables AST-based JS/HTML rewriting. This may fix issues caused by the existing regex-based JS/HTML replacement algorithm." - }, - "experimentalFetchPolyfill": { - "type": "boolean", - "default": false, - "description": "Polyfills `window.fetch` to enable Network spying and stubbing" - }, - "experimentalStudio": { - "type": "boolean", - "default": false, - "description": "Generate and save commands directly to your test suite by interacting with your app as an end user would." - }, - "retries": { - "type": [ - "object", - "number", - "null" - ], - "default": { - "runMode": 0, - "openMode": 0 - }, - "description": "The number of times to retry a failing. Can be configured to apply only in runMode or openMode" - }, - "includeShadowDom": { - "type": "boolean", - "default": false, - "description": "Enables including elements within the shadow DOM when using querying commands (e.g. cy.get(), cy.find()). Can be set globally in cypress.json, per-suite or per-test in the test configuration object, or programmatically with Cypress.config()" - }, - "component": { - "description": "Any component runner specific overrides", - "$ref": "#/definitions/cypressConfig" - }, - "e2e": { - "description": "Any e2e runner specific overrides", - "$ref": "#/definitions/cypressConfig" - } - } + "description": "Any values to be set as environment variables. See https://on.cypress.io/environment-variables", + "body": {} + }, + "ignoreTestFiles": { + "type": [ + "string", + "array" + ], + "items": { + "type": "string" + }, + "description": "A String or Array of glob patterns used to ignore test files that would otherwise be shown in your list of tests. Cypress uses minimatch with the options: {dot: true, matchBase: true}. We suggest using http://globtester.com to test what files would match." + }, + "numTestsKeptInMemory": { + "type": "number", + "default": 50, + "description": "The number of tests for which snapshots and command data are kept in memory. Reduce this number if you are experiencing high memory consumption in your browser during a test run." + }, + "port": { + "type": "number", + "default": null, + "description": "Port used to host Cypress. Normally this is a randomly generated port" + }, + "reporter": { + "type": "string", + "default": "spec", + "description": "The reporter used when running headlessly or in CI. See https://on.cypress.io/reporters" + }, + "reporterOptions": { + "type": "object", + "default": null, + "description": "The reporter options used. Supported options depend on the reporter. See https://on.cypress.io/reporters#Reporter-Options" + }, + "testFiles": { + "type": [ + "string", + "array" + ], + "default": "**/*.*", + "description": "A String or Array of string glob patterns of the test files to load. See https://on.cypress.io/configuration#Global" + }, + "watchForFileChanges": { + "type": "boolean", + "default": true, + "description": "Whether Cypress will watch and restart tests on test file changes" + }, + "defaultCommandTimeout": { + "type": "number", + "default": 4000, + "description": "Time, in milliseconds, to wait until most DOM based commands are considered timed out" + }, + "execTimeout": { + "type": "number", + "default": 60000, + "description": "Time, in milliseconds, to wait for a system command to finish executing during a cy.exec() command" + }, + "taskTimeout": { + "type": "number", + "default": 60000, + "description": "Time, in milliseconds, to wait for a task to finish executing during a cy.task() command" + }, + "pageLoadTimeout": { + "type": "number", + "default": 60000, + "description": "Time, in milliseconds, to wait for page transition events or cy.visit(), cy.go(), cy.reload() commands to fire their page load events. Network requests are limited by the underlying operating system, and may still time out if this value is increased." + }, + "requestTimeout": { + "type": "number", + "default": 5000, + "description": "Time, in milliseconds, to wait for an XHR request to go out in a cy.wait() command" + }, + "responseTimeout": { + "type": "number", + "default": 30000, + "description": "Time, in milliseconds, to wait until a response in a cy.request(), cy.wait(), cy.fixture(), cy.getCookie(), cy.getCookies(), cy.setCookie(), cy.clearCookie(), cy.clearCookies(), and cy.screenshot() commands" + }, + "fileServerFolder": { + "type": "string", + "default": "root project folder", + "description": "Path to folder where application files will attempt to be served from" + }, + "fixturesFolder": { + "type": [ + "string", + "boolean" + ], + "default": "cypress/fixtures", + "description": "Path to folder containing fixture files (Pass false to disable)" + }, + "integrationFolder": { + "type": "string", + "default": "cypress/integration", + "description": "Path to folder containing integration test files" + }, + "downloadsFolder": { + "type": "string", + "default": "cypress/downloads", + "description": "Path to folder where files downloaded during a test are saved" + }, + "experimentalComponentTesting": { + "type": "boolean", + "default": false, + "description": "Enabled experimental component testing, see https://github.com/cypress-io/cypress/issues/5922" + }, + "componentFolder": { + "type": [ + "string", + "boolean" + ], + "default": false, + "description": "Path to folder containing component test files (Pass false to disable)" + }, + "pluginsFile": { + "type": [ + "string", + "boolean" + ], + "default": "cypress/plugins/index.js", + "description": "Path to plugins file. (Pass false to disable)" + }, + "screenshotOnRunFailure": { + "type": "boolean", + "default": true, + "description": "Whether Cypress will take a screenshot when a test fails during cypress run" + }, + "screenshotsFolder": { + "type": "string", + "default": "cypress/screenshots", + "description": "Path to folder where screenshots will be saved from cy.screenshot() command or after a test fails during cypress run" + }, + "supportFile": { + "type": [ + "string", + "boolean" + ], + "default": "cypress/support/index.js", + "description": "Path to file to load before test files load. This file is compiled and bundled. (Pass false to disable)" + }, + "videosFolder": { + "type": "string", + "default": "cypress/videos", + "description": "Path to folder where videos will be saved during cypress run" + }, + "trashAssetsBeforeRuns": { + "type": "boolean", + "default": true, + "description": "Whether Cypress will trash assets within the screenshotsFolder and videosFolder before tests run with cypress run" + }, + "videoCompression": { + "type": [ + "number", + "boolean" + ], + "default": 32, + "description": "The quality setting for the video compression, in Constant Rate Factor (CRF). The value can be false to disable compression or a value between 0 and 51, where a lower value results in better quality (at the expense of a higher file size)." + }, + "video": { + "type": "boolean", + "default": true, + "description": "Whether Cypress will capture a video of the tests run with cypress run" + }, + "videoUploadOnPasses": { + "type": "boolean", + "default": true, + "description": "Whether Cypress will process, compress, and upload videos to the Dashboard even when all tests in a spec file are passing. This only applies when recording your runs to the Dashboard. Turn this off if you’d like to only upload the spec file’s video when there are failing tests." + }, + "chromeWebSecurity": { + "type": "boolean", + "default": true, + "description": "Whether Chrome Web Security for same-origin policy and insecure mixed content is enabled. Read more about this at https://on.cypress.io/web-security" + }, + "userAgent": { + "type": "string", + "default": null, + "description": "Enables you to override the default user agent the browser sends in all request headers. User agent values are typically used by servers to help identify the operating system, browser, and browser version. See User-Agent MDN Documentation for example user agent values here: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/User-Agent" + }, + "blockHosts": { + "type": [ + "string", + "array" + ], + "items": { + "type": "string" + }, + "default": null, + "description": "A String or Array of hosts that you wish to block traffic for. Please read the notes for examples on using this https://on.cypress.io/configuration#blockHosts" + }, + "modifyObstructiveCode": { + "type": "boolean", + "default": true, + "description": "Whether Cypress will search for and replace obstructive JS code found in .js or .html files that prevent Cypress from working. Please read the notes for more information on this setting. https://on.cypress.io/configuration#modifyObstructiveCode" + }, + "viewportHeight": { + "type": "number", + "default": 660, + "description": "Default height in pixels for the application under tests’ viewport (Override with cy.viewport() command)" + }, + "viewportWidth": { + "type": "number", + "default": 1000, + "description": "Default width in pixels for the application under tests’ viewport. (Override with cy.viewport() command)" + }, + "animationDistanceThreshold": { + "type": "number", + "default": 5, + "description": "The distance in pixels an element must exceed over time to be considered animating" + }, + "waitForAnimations": { + "type": "boolean", + "default": true, + "description": "Whether to wait for elements to finish animating before executing commands" + }, + "scrollBehavior": { + "enum": [ + false, + "center", + "top", + "bottom", + "nearest" + ], + "default": "top", + "description": "Viewport position to which an element should be scrolled prior to action commands. Setting `false` disables scrolling." + }, + "projectId": { + "type": "string", + "default": null, + "description": "A 6 character string use to identify this project in the Cypress Dashboard. See https://on.cypress.io/dashboard-service#Identification" + }, + "nodeVersion": { + "enum": [ + "system", + "bundled" + ], + "default": "bundled", + "description": "If set to 'system', Cypress will try to find a Node.js executable on your path to use when executing your plugins. Otherwise, Cypress will use the Node version bundled with Cypress." + }, + "experimentalSourceRewriting": { + "type": "boolean", + "default": false, + "description": "Enables AST-based JS/HTML rewriting. This may fix issues caused by the existing regex-based JS/HTML replacement algorithm." + }, + "experimentalFetchPolyfill": { + "type": "boolean", + "default": false, + "description": "Polyfills `window.fetch` to enable Network spying and stubbing" + }, + "experimentalStudio": { + "type": "boolean", + "default": false, + "description": "Generate and save commands directly to your test suite by interacting with your app as an end user would." + }, + "retries": { + "type": [ + "object", + "number", + "null" + ], + "default": { + "runMode": 0, + "openMode": 0 + }, + "description": "The number of times to retry a failing. Can be configured to apply only in runMode or openMode" + }, + "includeShadowDom": { + "type": "boolean", + "default": false, + "description": "Enables including elements within the shadow DOM when using querying commands (e.g. cy.get(), cy.find()). Can be set globally in cypress.json, per-suite or per-test in the test configuration object, or programmatically with Cypress.config()" } - }, - "$ref": "#/definitions/cypressConfig" + } } diff --git a/cli/types/cypress.d.ts b/cli/types/cypress.d.ts index 06c72d9043cc..c52de05772ef 100644 --- a/cli/types/cypress.d.ts +++ b/cli/types/cypress.d.ts @@ -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, mode: 'e2e' | 'component') => void | ConfigOptions | Promise + type PluginConfig = (on: PluginEvents, config: PluginConfigOptions) => void | ConfigOptions | Promise interface CommandOptions { prevSubject: boolean | PrevSubject | PrevSubject[] diff --git a/npm/react/cypress/plugins/index.js b/npm/react/cypress/plugins/index.js index b560c50f0bea..9aa6e0a55c27 100644 --- a/npm/react/cypress/plugins/index.js +++ b/npm/react/cypress/plugins/index.js @@ -60,11 +60,7 @@ const webpackConfig = { /** * @type Cypress.PluginConfig */ -module.exports = (on, config, mode) => { - if (mode !== 'component') { - throw Error('This is an component project. mode should be `component`.') - } - +module.exports = (on, config) => { on('dev-server:start', (options) => { return startDevServer({ options, webpackConfig, disableLazyCompilation: false }) }) diff --git a/npm/vue/cypress/plugins/index.js b/npm/vue/cypress/plugins/index.js index 4a575785d41a..1e01c246d085 100644 --- a/npm/vue/cypress/plugins/index.js +++ b/npm/vue/cypress/plugins/index.js @@ -5,11 +5,7 @@ const webpackConfig = require('../../webpack.config') /** * @type Cypress.PluginConfig */ -module.exports = (on, config, mode) => { - if (mode !== 'component') { - throw Error('This is a component testing project. mode should be `component`.') - } - +module.exports = (on, config) => { require('@cypress/code-coverage/task')(on, config) on('dev-server:start', (options) => startDevServer({ options, webpackConfig })) diff --git a/packages/server-ct/src/project-ct.ts b/packages/server-ct/src/project-ct.ts index 3396eda70dd9..7e827091f393 100644 --- a/packages/server-ct/src/project-ct.ts +++ b/packages/server-ct/src/project-ct.ts @@ -47,7 +47,7 @@ export class ProjectCt extends ProjectBase { this.server.socket.changeToUrl(targetUrl) } - open (options: Record) { + open (options) { this._server = new ServerCt() return super.open(options, { @@ -85,7 +85,6 @@ export class ProjectCt extends ProjectBase { return plugins.init(allowedCfg, { projectRoot: this.projectRoot, configFile: settings.pathToConfigFile(this.projectRoot, options), - mode: options.mode, }) .then((modifiedCfg) => { debug('plugin config yielded: %o', modifiedCfg) diff --git a/packages/server/lib/open_project.js b/packages/server/lib/open_project.js index 2cb93227f3b6..508c75c19296 100644 --- a/packages/server/lib/open_project.js +++ b/packages/server/lib/open_project.js @@ -328,7 +328,7 @@ const moduleFactory = () => { debug('opening project %s', path) debug('and options %o', options) - return openProject.open({ ...options, mode: args.testingType }) + return openProject.open(options) .return(this) }, } diff --git a/packages/server/lib/plugins/child/run_plugins.js b/packages/server/lib/plugins/child/run_plugins.js index d82d29014fe0..63a977fbdc17 100644 --- a/packages/server/lib/plugins/child/run_plugins.js +++ b/packages/server/lib/plugins/child/run_plugins.js @@ -37,13 +37,7 @@ const getDefaultPreprocessor = function (config) { let plugins -/** - * @param {EventEmitter} ipc - * @param {object} config - * @param {string} pluginsFile - * @param {'component' | 'e2e'} string - */ -const load = (ipc, config, pluginsFile, mode) => { +const load = (ipc, config, pluginsFile) => { debug('run plugins function') let eventIdCount = 0 @@ -93,7 +87,7 @@ const load = (ipc, config, pluginsFile, mode) => { .try(() => { debug('run plugins function') - return plugins(register, config, mode) + return plugins(register, config) }) .tap(() => { if (!registeredEventsByName['file:preprocessor']) { @@ -198,10 +192,10 @@ const runPlugins = (ipc, pluginsFile, projectRoot) => { return } - ipc.on('load', (config, mode) => { + ipc.on('load', (config) => { debug('plugins load file "%s"', pluginsFile) debug('passing config %o', config) - load(ipc, config, pluginsFile, mode) + load(ipc, config, pluginsFile) }) ipc.on('execute', (event, ids, args) => { diff --git a/packages/server/lib/plugins/index.js b/packages/server/lib/plugins/index.js index 95d763f7d4de..6b425367fa86 100644 --- a/packages/server/lib/plugins/index.js +++ b/packages/server/lib/plugins/index.js @@ -113,7 +113,7 @@ const init = (config, options) => { version: pkg.version, }) - ipc.send('load', config, options.mode) + ipc.send('load', config) ipc.on('loaded', (newCfg, registrations) => { _.omit(config, 'projectRoot', 'configFile') diff --git a/packages/server/lib/project-e2e.ts b/packages/server/lib/project-e2e.ts index 9611927b1f3a..49fcf355d6d8 100644 --- a/packages/server/lib/project-e2e.ts +++ b/packages/server/lib/project-e2e.ts @@ -14,7 +14,7 @@ export class ProjectE2E extends ProjectBase { return 'e2e' } - open (options: Record) { + open (options) { this._server = new ServerE2E() return super.open(options, { @@ -59,7 +59,6 @@ export class ProjectE2E extends ProjectBase { return plugins.init(cfg, { projectRoot: this.projectRoot, configFile: settings.pathToConfigFile(this.projectRoot, options), - mode: options.mode, onError (err) { debug('got plugins error', err.stack) diff --git a/packages/server/lib/util/settings.js b/packages/server/lib/util/settings.js index c03ddd9f997a..e2e17f673917 100644 --- a/packages/server/lib/util/settings.js +++ b/packages/server/lib/util/settings.js @@ -93,10 +93,6 @@ module.exports = { }, _.cloneDeep(obj)) }, - isComponentTesting (options = {}) { - return options.experimentalComponentTesting || options.componentTesting || options.testingType === 'component' - }, - configFile (options = {}) { return options.configFile === false ? false : (options.configFile || 'cypress.json') }, @@ -155,16 +151,6 @@ 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 diff --git a/packages/server/test/integration/plugins_spec.js b/packages/server/test/integration/plugins_spec.js index 460280ed711c..6303b2318a71 100644 --- a/packages/server/test/integration/plugins_spec.js +++ b/packages/server/test/integration/plugins_spec.js @@ -26,7 +26,6 @@ describe('lib/plugins', () => { const options = { onWarning, - mode: 'e2e', } return plugins.init(projectConfig, options) diff --git a/packages/server/test/support/fixtures/projects/chrome-browser-preferences/cypress/plugins/index.js b/packages/server/test/support/fixtures/projects/chrome-browser-preferences/cypress/plugins/index.js index e64705d6a20b..8ae57533e229 100644 --- a/packages/server/test/support/fixtures/projects/chrome-browser-preferences/cypress/plugins/index.js +++ b/packages/server/test/support/fixtures/projects/chrome-browser-preferences/cypress/plugins/index.js @@ -3,11 +3,7 @@ const { expect } = require('chai') const fse = require('fs-extra') const path = require('path') -module.exports = (on, config, mode) => { - if (mode !== 'e2e') { - throw Error('This is an e2e project. mode should be `e2e`.') - } - +module.exports = (on, config) => { const parentPid = process.ppid let { PATH_TO_CHROME_PROFILE } = config.env diff --git a/packages/server/test/support/fixtures/projects/component-tests/cypress/plugins/index.js b/packages/server/test/support/fixtures/projects/component-tests/cypress/plugins/index.js index 902cb2f334a9..22333b91e4da 100644 --- a/packages/server/test/support/fixtures/projects/component-tests/cypress/plugins/index.js +++ b/packages/server/test/support/fixtures/projects/component-tests/cypress/plugins/index.js @@ -13,11 +13,7 @@ const webpackConfig = { /** * @type Cypress.PluginConfig */ -module.exports = (on, config, mode) => { - if (mode !== 'e2e') { - throw Error('This is an e2e project. mode should be `e2e`.') - } - +module.exports = (on, config) => { require('@cypress/code-coverage/task')(on, config) on('dev-server:start', (options) => startDevServer({ options, webpackConfig })) diff --git a/packages/server/test/support/fixtures/projects/e2e/cypress/plugins/index.js b/packages/server/test/support/fixtures/projects/e2e/cypress/plugins/index.js index f1df5879287b..e6746f685a1b 100644 --- a/packages/server/test/support/fixtures/projects/e2e/cypress/plugins/index.js +++ b/packages/server/test/support/fixtures/projects/e2e/cypress/plugins/index.js @@ -11,11 +11,7 @@ const { useFixedFirefoxResolution } = require('../../../utils') /** * @type {Cypress.PluginConfig} */ -module.exports = (on, config, mode) => { - if (mode !== 'e2e') { - throw Error('This is an e2e project. mode should be `e2e`.') - } - +module.exports = (on, config) => { let performance = { track: () => Promise.resolve(), } diff --git a/packages/server/test/support/fixtures/projects/firefox-memory/cypress/plugins/index.js b/packages/server/test/support/fixtures/projects/firefox-memory/cypress/plugins/index.js index 76f5e71ddf3c..9b16edf98c32 100644 --- a/packages/server/test/support/fixtures/projects/firefox-memory/cypress/plugins/index.js +++ b/packages/server/test/support/fixtures/projects/firefox-memory/cypress/plugins/index.js @@ -20,11 +20,7 @@ let timings = [] let rss = [] let intervalId -module.exports = (on, config, mode) => { - if (mode !== 'e2e') { - throw Error('This is an e2e project. mode should be `e2e`.') - } - +module.exports = (on, config) => { on('task', { 'console' (...args) { console.log(...args) diff --git a/packages/server/test/support/fixtures/projects/plugin-before-browser-launch-deprecation/cypress/plugins/index.js b/packages/server/test/support/fixtures/projects/plugin-before-browser-launch-deprecation/cypress/plugins/index.js index 011a4220a3fe..a52576c6c3b8 100644 --- a/packages/server/test/support/fixtures/projects/plugin-before-browser-launch-deprecation/cypress/plugins/index.js +++ b/packages/server/test/support/fixtures/projects/plugin-before-browser-launch-deprecation/cypress/plugins/index.js @@ -109,11 +109,7 @@ const getHandlersByType = (type) => { } } -module.exports = (on, config, mode) => { - if (mode !== 'e2e') { - throw Error('This is an e2e project. mode should be `e2e`.') - } - +module.exports = (on, config) => { const beforeBrowserLaunchHandler = config.env.BEFORE_BROWSER_LAUNCH_HANDLER if (!beforeBrowserLaunchHandler) { diff --git a/packages/server/test/support/fixtures/projects/plugin-config-version/cypress/plugins/index.js b/packages/server/test/support/fixtures/projects/plugin-config-version/cypress/plugins/index.js index 0cb870daf284..6e74e114bfca 100644 --- a/packages/server/test/support/fixtures/projects/plugin-config-version/cypress/plugins/index.js +++ b/packages/server/test/support/fixtures/projects/plugin-config-version/cypress/plugins/index.js @@ -1,10 +1,6 @@ const semver = require('semver') -module.exports = (on, config, mode) => { - if (mode !== 'e2e') { - throw Error('This is an e2e project. mode should be `e2e`.') - } - +module.exports = (on, config) => { if (!semver.valid(config.version)) { throw new Error('config.version is invalid') } diff --git a/packages/server/test/support/fixtures/projects/plugin-config/cypress/plugins/index.js b/packages/server/test/support/fixtures/projects/plugin-config/cypress/plugins/index.js index 2fc5b99992ab..95461bde6d6e 100644 --- a/packages/server/test/support/fixtures/projects/plugin-config/cypress/plugins/index.js +++ b/packages/server/test/support/fixtures/projects/plugin-config/cypress/plugins/index.js @@ -1,8 +1,4 @@ -module.exports = (on, config, mode) => { - if (mode !== 'e2e') { - throw Error('This is an e2e project. mode should be `e2e`.') - } - +module.exports = (on, config) => { return new Promise((resolve) => { setTimeout(resolve, 100) }) diff --git a/packages/server/test/support/fixtures/projects/plugin-event-deprecated/cypress/plugins/index.js b/packages/server/test/support/fixtures/projects/plugin-event-deprecated/cypress/plugins/index.js index 082db2ab71dd..fd699f94b7a0 100644 --- a/packages/server/test/support/fixtures/projects/plugin-event-deprecated/cypress/plugins/index.js +++ b/packages/server/test/support/fixtures/projects/plugin-event-deprecated/cypress/plugins/index.js @@ -1,8 +1,4 @@ -module.exports = (on, config, mode) => { - if (mode !== 'e2e') { - throw Error('This is an e2e project. mode should be `e2e`.') - } - +module.exports = (on, config) => { if (config.env.NO_MUTATE_RETURN) { on('before:browser:launch', (browser, options) => { // this will emit a warning diff --git a/packages/server/test/support/fixtures/projects/read-only-project-root/cypress/plugins/index.js b/packages/server/test/support/fixtures/projects/read-only-project-root/cypress/plugins/index.js index 12642cc76846..1655288a0f41 100644 --- a/packages/server/test/support/fixtures/projects/read-only-project-root/cypress/plugins/index.js +++ b/packages/server/test/support/fixtures/projects/read-only-project-root/cypress/plugins/index.js @@ -1,11 +1,7 @@ const fs = require('fs') const { expect } = require('chai') -module.exports = (on, config, mode) => { - if (mode !== 'e2e') { - throw Error('This is an e2e project. mode should be `e2e`.') - } - +module.exports = (on, config) => { expect(process.geteuid()).to.not.eq(0) console.log('✅ not running as root') diff --git a/packages/server/test/support/fixtures/projects/retries-2/cypress/plugins/index.js b/packages/server/test/support/fixtures/projects/retries-2/cypress/plugins/index.js index a5e55997cdd6..27a4eac6e871 100644 --- a/packages/server/test/support/fixtures/projects/retries-2/cypress/plugins/index.js +++ b/packages/server/test/support/fixtures/projects/retries-2/cypress/plugins/index.js @@ -5,11 +5,7 @@ const { useFixedFirefoxResolution } = require('../../../utils') /** * @type {Cypress.PluginConfig} */ -module.exports = (on, config, mode) => { - if (mode !== 'e2e') { - throw Error('This is an e2e project. mode should be `e2e`.') - } - +module.exports = (on, config) => { on('before:browser:launch', (browser, options) => { useFixedFirefoxResolution(browser, options, config) diff --git a/packages/server/test/unit/settings_spec.js b/packages/server/test/unit/settings_spec.js index ee68e5fd89b1..499704e57443 100644 --- a/packages/server/test/unit/settings_spec.js +++ b/packages/server/test/unit/settings_spec.js @@ -111,42 +111,6 @@ 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(() => { From fe1046e8fa4cef3a8408b8bffedb21fcc66ee882 Mon Sep 17 00:00:00 2001 From: Chris Breiding Date: Mon, 15 Mar 2021 14:57:53 -0400 Subject: [PATCH 2/3] Revert "feat: use require to support config via cypress.js (#15263)" This reverts commit 24e07f6d32fa8235459380134a486b6f0d36926d. --- packages/server/lib/util/settings.js | 9 +---- packages/server/test/e2e/6_visit_spec.js | 5 --- .../server/test/e2e/6_web_security_spec.js | 5 --- packages/server/test/e2e/7_record_spec.js | 21 ++++++------ .../server/test/integration/cypress_spec.js | 33 +++++++------------ packages/server/test/specUtils.ts | 8 ----- packages/server/test/unit/settings_spec.js | 5 --- 7 files changed, 22 insertions(+), 64 deletions(-) diff --git a/packages/server/lib/util/settings.js b/packages/server/lib/util/settings.js index e2e17f673917..699023887c39 100644 --- a/packages/server/lib/util/settings.js +++ b/packages/server/lib/util/settings.js @@ -140,14 +140,7 @@ module.exports = { const file = this.pathToConfigFile(projectRoot, options) - const requireAsync = (file) => { - return Promise.try(() => require(file)) - } - - return requireAsync(file) - .catch({ code: 'MODULE_NOT_FOUND' }, () => { - return this._write(file, {}) - }) + return fs.readJsonAsync(file) .catch({ code: 'ENOENT' }, () => { return this._write(file, {}) }).then((json = {}) => { diff --git a/packages/server/test/e2e/6_visit_spec.js b/packages/server/test/e2e/6_visit_spec.js index 484dd9c098ab..b5e743af5c6f 100644 --- a/packages/server/test/e2e/6_visit_spec.js +++ b/packages/server/test/e2e/6_visit_spec.js @@ -5,7 +5,6 @@ const https = require('https') const useragent = require('express-useragent') const { allowDestroy } = require('@packages/network') const e2e = require('../support/helpers/e2e').default -const { clearCypressJsonCache } = require('../specUtils') // create an HTTPS server that forces TLSv1 const startTlsV1Server = (port) => { @@ -117,10 +116,6 @@ foo\ } describe('e2e visit', () => { - beforeEach(() => { - clearCypressJsonCache() - }) - context('low response timeout', () => { e2e.setup({ settings: { diff --git a/packages/server/test/e2e/6_web_security_spec.js b/packages/server/test/e2e/6_web_security_spec.js index f86c5ae7f782..dc0da65cf9f1 100644 --- a/packages/server/test/e2e/6_web_security_spec.js +++ b/packages/server/test/e2e/6_web_security_spec.js @@ -1,5 +1,4 @@ const e2e = require('../support/helpers/e2e').default -const { clearCypressJsonCache } = require('../specUtils') const onServer = function (app) { app.get('/link', (req, res) => { @@ -52,10 +51,6 @@ const onServer = function (app) { } describe('e2e web security', () => { - beforeEach(() => { - clearCypressJsonCache() - }) - e2e.setup({ servers: [{ port: 4466, diff --git a/packages/server/test/e2e/7_record_spec.js b/packages/server/test/e2e/7_record_spec.js index 5cb8afd68eb3..16649aabc735 100644 --- a/packages/server/test/e2e/7_record_spec.js +++ b/packages/server/test/e2e/7_record_spec.js @@ -16,7 +16,9 @@ const { postInstanceTestsResponse, } = require('../support/helpers/serverStub') const { expectRunsToHaveCorrectTimings } = require('../support/helpers/resultsUtils') -const { clearCypressJsonCache } = require('../specUtils') +const postRunResponseWithWarnings = jsonSchemas.getExample('postRunResponse')('2.2.0') +const postRunResponse = _.assign({}, postRunResponseWithWarnings, { warnings: [] }) +const postRunInstanceResponse = jsonSchemas.getExample('postRunInstanceResponse')('2.1.0') const e2ePath = Fixtures.projectPath('e2e') const outputPath = path.join(e2ePath, 'output.json') @@ -689,17 +691,14 @@ describe('e2e record', () => { }) describe('create run 500', () => { - beforeEach(() => { - clearCypressJsonCache() - }) - - const routes = createRoutes({ - postRun: { - res (req, res) { - return res.sendStatus(500) - }, + const routes = [{ + method: 'post', + url: '/runs', + req: 'postRunRequest@2.2.0', + res (req, res) { + return res.sendStatus(500) }, - }) + }] setupStubbedServer(routes) diff --git a/packages/server/test/integration/cypress_spec.js b/packages/server/test/integration/cypress_spec.js index 70d92e50acb3..ef3ed30e1d1d 100644 --- a/packages/server/test/integration/cypress_spec.js +++ b/packages/server/test/integration/cypress_spec.js @@ -47,7 +47,6 @@ const system = require(`${root}lib/util/system`) const appData = require(`${root}lib/util/app_data`) const electronApp = require('../../lib/util/electron-app') const savedState = require(`${root}lib/saved_state`) -const { clearCypressJsonCache } = require('../specUtils') const TYPICAL_BROWSERS = [ { @@ -428,7 +427,6 @@ describe('lib/cypress', () => { sinon.stub(runMode, 'listenForProjectEnd').resolves({ stats: { failures: 0 } }) sinon.stub(browsers, 'open') sinon.stub(commitInfo, 'getRemoteOrigin').resolves('remoteOrigin') - clearCypressJsonCache() }) it('runs project headlessly and exits with exit code 0', function () { @@ -1228,8 +1226,6 @@ describe('lib/cypress', () => { describe('--port', () => { beforeEach(() => { - clearCypressJsonCache() - return runMode.listenForProjectEnd.resolves({ stats: { failures: 0 } }) }) @@ -1264,7 +1260,6 @@ describe('lib/cypress', () => { describe('--env', () => { beforeEach(() => { process.env = _.omit(process.env, 'CYPRESS_DEBUG') - clearCypressJsonCache() return runMode.listenForProjectEnd.resolves({ stats: { failures: 0 } }) }) @@ -1307,10 +1302,6 @@ describe('lib/cypress', () => { }) describe('--config-file', () => { - beforeEach(() => { - clearCypressJsonCache() - }) - it('false does not require cypress.json to run', function () { return fs.statAsync(path.join(this.pristinePath, 'cypress.json')) .then(() => { @@ -1930,21 +1921,21 @@ describe('lib/cypress', () => { describe('--config-file', () => { beforeEach(function () { - clearCypressJsonCache() + this.filename = 'foo.bar.baz.asdf.quux.json' this.open = sinon.stub(ServerE2E.prototype, 'open').resolves([]) }) it('reads config from a custom config file', function () { - const filename = 'foo.bar.baz.asdf.quux.json' + sinon.stub(fs, 'readJsonAsync') + fs.readJsonAsync.withArgs(path.join(this.pristinePath, this.filename)).resolves({ + env: { foo: 'bar' }, + port: 2020, + }) - fs.writeFileAsync( - path.join(this.pristinePath, filename), - JSON.stringify({ env: { foo: 'bar' }, port: 2020 }), - 'utf8', - ) + fs.readJsonAsync.callThrough() return cypress.start([ - `--config-file=${filename}`, + `--config-file=${this.filename}`, ]) .then(() => { const options = Events.start.firstCall.args[0] @@ -1962,13 +1953,11 @@ describe('lib/cypress', () => { }) it('creates custom config file if it does not exist', function () { - const filename = 'foo.quux.test.json' - return cypress.start([ - `--config-file=${filename}`, + `--config-file=${this.filename}`, ]) .then(() => { - debug('cypress started with config %s', filename) + debug('cypress started with config %s', this.filename) const options = Events.start.firstCall.args[0] debug('first call arguments %o', Events.start.firstCall.args) @@ -1977,7 +1966,7 @@ describe('lib/cypress', () => { }).then(() => { expect(this.open, 'open was called').to.be.called - return fs.readJsonAsync(path.join(this.pristinePath, filename)) + return fs.readJsonAsync(path.join(this.pristinePath, this.filename)) .then((json) => { expect(json, 'json file is empty').to.deep.equal({}) }) diff --git a/packages/server/test/specUtils.ts b/packages/server/test/specUtils.ts index b699389ab80f..eae319679fd5 100644 --- a/packages/server/test/specUtils.ts +++ b/packages/server/test/specUtils.ts @@ -46,11 +46,3 @@ export const getFs = () => { return recurse({ root: mockfs.getMockRoot() }, -1).root } - -export const clearCypressJsonCache = () => { - Object.keys(require.cache).forEach((key) => { - if (key.includes('cypress.json')) { - delete require.cache[key] - } - }) -} diff --git a/packages/server/test/unit/settings_spec.js b/packages/server/test/unit/settings_spec.js index 499704e57443..d512f601ba0e 100644 --- a/packages/server/test/unit/settings_spec.js +++ b/packages/server/test/unit/settings_spec.js @@ -3,15 +3,10 @@ require('../spec_helper') const path = require('path') const { fs } = require(`${root}lib/util/fs`) const settings = require(`${root}lib/util/settings`) -const { clearCypressJsonCache } = require('../specUtils') const projectRoot = process.cwd() describe('lib/settings', () => { - beforeEach(function () { - clearCypressJsonCache() - }) - context('with no configFile option', () => { beforeEach(function () { this.setup = (obj = {}) => { From 496e458818e7dee3c014114992257490f26b6c8c Mon Sep 17 00:00:00 2001 From: Chris Breiding Date: Mon, 15 Mar 2021 16:29:01 -0400 Subject: [PATCH 3/3] clone settings so they can't be mutated, add test --- packages/server/lib/config.js | 4 ++-- packages/server/test/e2e/7_record_spec.js | 16 ++++++---------- packages/server/test/unit/config_spec.js | 16 ++++++++++++++-- 3 files changed, 22 insertions(+), 14 deletions(-) diff --git a/packages/server/lib/config.js b/packages/server/lib/config.js index a95efe5bb286..e996da02d0b4 100644 --- a/packages/server/lib/config.js +++ b/packages/server/lib/config.js @@ -209,8 +209,8 @@ module.exports = { return this.set({ projectName: this.getNameFromRoot(projectRoot), projectRoot, - config: settings, - envFile, + config: _.cloneDeep(settings), + envFile: _.cloneDeep(envFile), options, }) }) diff --git a/packages/server/test/e2e/7_record_spec.js b/packages/server/test/e2e/7_record_spec.js index 16649aabc735..d5f3cff96ce9 100644 --- a/packages/server/test/e2e/7_record_spec.js +++ b/packages/server/test/e2e/7_record_spec.js @@ -16,9 +16,6 @@ const { postInstanceTestsResponse, } = require('../support/helpers/serverStub') const { expectRunsToHaveCorrectTimings } = require('../support/helpers/resultsUtils') -const postRunResponseWithWarnings = jsonSchemas.getExample('postRunResponse')('2.2.0') -const postRunResponse = _.assign({}, postRunResponseWithWarnings, { warnings: [] }) -const postRunInstanceResponse = jsonSchemas.getExample('postRunInstanceResponse')('2.1.0') const e2ePath = Fixtures.projectPath('e2e') const outputPath = path.join(e2ePath, 'output.json') @@ -691,14 +688,13 @@ describe('e2e record', () => { }) describe('create run 500', () => { - const routes = [{ - method: 'post', - url: '/runs', - req: 'postRunRequest@2.2.0', - res (req, res) { - return res.sendStatus(500) + const routes = createRoutes({ + postRun: { + res (req, res) { + return res.sendStatus(500) + }, }, - }] + }) setupStubbedServer(routes) diff --git a/packages/server/test/unit/config_spec.js b/packages/server/test/unit/config_spec.js index df53b331c706..418d6a5bbc04 100644 --- a/packages/server/test/unit/config_spec.js +++ b/packages/server/test/unit/config_spec.js @@ -56,8 +56,7 @@ describe('lib/config', () => { this.setup = (cypressJson = {}, cypressEnvJson = {}) => { sinon.stub(settings, 'read').withArgs(this.projectRoot).resolves(cypressJson) - - return sinon.stub(settings, 'readEnv').withArgs(this.projectRoot).resolves(cypressEnvJson) + sinon.stub(settings, 'readEnv').withArgs(this.projectRoot).resolves(cypressEnvJson) } }) @@ -81,6 +80,19 @@ describe('lib/config', () => { }) }) + it('clones settings and env settings, so they are not mutated', function () { + const settings = { foo: 'bar' } + const envSettings = { baz: 'qux' } + + this.setup(settings, envSettings) + + return config.get(this.projectRoot) + .then(() => { + expect(settings).to.deep.equal({ foo: 'bar' }) + expect(envSettings).to.deep.equal({ baz: 'qux' }) + }) + }) + context('port', () => { beforeEach(function () { return this.setup({}, { foo: 'bar' })