From 778321786f7a19d63ddabc74806b7c2852bbfe69 Mon Sep 17 00:00:00 2001 From: Chris Breiding Date: Fri, 28 Feb 2020 14:13:36 -0500 Subject: [PATCH] Pass projectRoot and configFile to plugins file through config (#6317) * decaffeinate: Rename index.coffee from .coffee to .js * decaffeinate: Convert index.coffee to JS * decaffeinate: Run post-processing cleanups on index.coffee * refactor decaffeinated plugins/index.js * decaffeinate: Rename 3_plugins_spec.coffee from .coffee to .js * decaffeinate: Convert 3_plugins_spec.coffee to JS * decaffeinate: Run post-processing cleanups on 3_plugins_spec.coffee * fix wrongly removed return * refactor e2e plugins spec, update snapshot * pass env argument to plugins file * decaffeinate: Rename index_spec.coffee from .coffee to .js * decaffeinate: Convert index_spec.coffee to JS * decaffeinate: Run post-processing cleanups on index_spec.coffee * update plugins tests * update scaffold snapshot * add back server test script and document running individual tests * add projectRoot and configFile directly to config * normalize browsers in snapshot * add types for configFile and projectRoot * fix linting issues * return return * Merge * remove file * remove unnecessary returns --- cli/types/index.d.ts | 13 +- cli/types/tests/plugins-config.ts | 4 +- .../__snapshots__/3_plugins_spec.coffee.js | 404 ------------------ .../server/__snapshots__/3_plugins_spec.js | 18 +- packages/server/lib/plugins/index.js | 17 +- packages/server/lib/project.js | 2 + packages/server/test/e2e/3_plugins_spec.js | 47 +- .../fixtures/projects/e2e/cypress-alt.json | 1 + .../integration/plugins_config_extras_spec.js | 13 + .../projects/e2e/cypress/plugins/index.js | 4 + packages/server/test/support/helpers/e2e.js | 4 + .../test/unit/browsers/browsers_spec.coffee | 5 +- .../server/test/unit/plugins/index_spec.js | 163 ++++--- 13 files changed, 200 insertions(+), 495 deletions(-) delete mode 100644 packages/server/__snapshots__/3_plugins_spec.coffee.js create mode 100644 packages/server/test/support/fixtures/projects/e2e/cypress-alt.json create mode 100644 packages/server/test/support/fixtures/projects/e2e/cypress/integration/plugins_config_extras_spec.js diff --git a/cli/types/index.d.ts b/cli/types/index.d.ts index a9efe1f070..7fef2f9c58 100644 --- a/cli/types/index.d.ts +++ b/cli/types/index.d.ts @@ -52,7 +52,7 @@ declare namespace Cypress { type RequestBody = string | object type ViewportOrientation = "portrait" | "landscape" type PrevSubject = "optional" | "element" | "document" | "window" - type PluginConfig = (on: PluginEvents, config: ConfigOptions) => void | Partial | Promise> + type PluginConfig = (on: PluginEvents, config: PluginConfigOptions) => void | Partial | Promise> interface CommandOptions { prevSubject: boolean | PrevSubject | PrevSubject[] @@ -2282,6 +2282,17 @@ declare namespace Cypress { firefoxGcInterval: Nullable, openMode: Nullable }> } + interface PluginConfigOptions extends ConfigOptions { + /** + * Absolute path to the config file (default: /cypress.json) or false + */ + configFile: string | false + /** + * Absolute path to the root of the project + */ + projectRoot: string + } + interface DebugOptions { verbose: boolean } diff --git a/cli/types/tests/plugins-config.ts b/cli/types/tests/plugins-config.ts index f081289040..1b72d6a6ad 100644 --- a/cli/types/tests/plugins-config.ts +++ b/cli/types/tests/plugins-config.ts @@ -5,8 +5,10 @@ const pluginConfig: Cypress.PluginConfig = (on, config) => {} // allows synchronous returns const pluginConfig2: Cypress.PluginConfig = (on, config) => { - config // $ExpectType ConfigOptions + config // $ExpectType PluginConfigOptions config.baseUrl // $ExpectType: string + config.configFile // $ExpectType: string | false + config.projectRoot // $ExpectType: string on('before:browser:launch', (browser, options) => { browser.displayName // $ExpectType string diff --git a/packages/server/__snapshots__/3_plugins_spec.coffee.js b/packages/server/__snapshots__/3_plugins_spec.coffee.js deleted file mode 100644 index 5e105bd8a3..0000000000 --- a/packages/server/__snapshots__/3_plugins_spec.coffee.js +++ /dev/null @@ -1,404 +0,0 @@ -exports['e2e plugins fails 1'] = ` - -==================================================================================================== - - (Run Starting) - - ┌────────────────────────────────────────────────────────────────────────────────────────────────┐ - │ Cypress: 1.2.3 │ - │ Browser: FooBrowser 88 │ - │ Specs: 1 found (app_spec.coffee) │ - │ Searched: cypress/integration/app_spec.coffee │ - └────────────────────────────────────────────────────────────────────────────────────────────────┘ - - -──────────────────────────────────────────────────────────────────────────────────────────────────── - - Running: app_spec.coffee (1 of 1) - -The following error was thrown by a plugin. We've stopped running your tests because a plugin crashed. - -Error: Async error from plugins file - [stack trace lines] - - - (Results) - - ┌────────────────────────────────────────────────────────────────────────────────────────────────┐ - │ Tests: 0 │ - │ Passing: 0 │ - │ Failing: 1 │ - │ Pending: 0 │ - │ Skipped: 0 │ - │ Screenshots: 0 │ - │ Video: true │ - │ Duration: X seconds │ - │ Spec Ran: app_spec.coffee │ - └────────────────────────────────────────────────────────────────────────────────────────────────┘ - - - (Video) - - - Started processing: Compressing to 32 CRF - - Finished processing: /XXX/XXX/XXX/cypress/videos/app_spec.coffee.mp4 (X second) - - -==================================================================================================== - - (Run Finished) - - - Spec Tests Passing Failing Pending Skipped - ┌────────────────────────────────────────────────────────────────────────────────────────────────┐ - │ ✖ app_spec.coffee XX:XX - - 1 - - │ - └────────────────────────────────────────────────────────────────────────────────────────────────┘ - ✖ 1 of 1 failed (100%) XX:XX - - 1 - - - - -` - -exports['e2e plugins passes 1'] = ` - -==================================================================================================== - - (Run Starting) - - ┌────────────────────────────────────────────────────────────────────────────────────────────────┐ - │ Cypress: 1.2.3 │ - │ Browser: FooBrowser 88 │ - │ Specs: 1 found (app_spec.coffee) │ - │ Searched: cypress/integration/app_spec.coffee │ - └────────────────────────────────────────────────────────────────────────────────────────────────┘ - - -──────────────────────────────────────────────────────────────────────────────────────────────────── - - Running: app_spec.coffee (1 of 1) - - - ✓ is another spec - ✓ is another spec - - 2 passing - - - (Results) - - ┌────────────────────────────────────────────────────────────────────────────────────────────────┐ - │ Tests: 2 │ - │ Passing: 2 │ - │ Failing: 0 │ - │ Pending: 0 │ - │ Skipped: 0 │ - │ Screenshots: 0 │ - │ Video: true │ - │ Duration: X seconds │ - │ Spec Ran: app_spec.coffee │ - └────────────────────────────────────────────────────────────────────────────────────────────────┘ - - - (Video) - - - Started processing: Compressing to 32 CRF - - Finished processing: /XXX/XXX/XXX/cypress/videos/app_spec.coffee.mp4 (X second) - - -==================================================================================================== - - (Run Finished) - - - Spec Tests Passing Failing Pending Skipped - ┌────────────────────────────────────────────────────────────────────────────────────────────────┐ - │ ✔ app_spec.coffee XX:XX 2 2 - - - │ - └────────────────────────────────────────────────────────────────────────────────────────────────┘ - ✔ All specs passed! XX:XX 2 2 - - - - - -` - -exports['e2e plugins can modify config from plugins 1'] = ` - -==================================================================================================== - - (Run Starting) - - ┌────────────────────────────────────────────────────────────────────────────────────────────────┐ - │ Cypress: 1.2.3 │ - │ Browser: FooBrowser 88 │ - │ Specs: 1 found (app_spec.coffee) │ - │ Searched: cypress/integration/app_spec.coffee │ - └────────────────────────────────────────────────────────────────────────────────────────────────┘ - - -──────────────────────────────────────────────────────────────────────────────────────────────────── - - Running: app_spec.coffee (1 of 1) - - - ✓ overrides config - ✓ overrides env - - 2 passing - - - (Results) - - ┌────────────────────────────────────────────────────────────────────────────────────────────────┐ - │ Tests: 2 │ - │ Passing: 2 │ - │ Failing: 0 │ - │ Pending: 0 │ - │ Skipped: 0 │ - │ Screenshots: 0 │ - │ Video: true │ - │ Duration: X seconds │ - │ Spec Ran: app_spec.coffee │ - └────────────────────────────────────────────────────────────────────────────────────────────────┘ - - - (Video) - - - Started processing: Compressing to 20 CRF - - Finished processing: /XXX/XXX/XXX/cypress/videos/app_spec.coffee.mp4 (X second) - - -==================================================================================================== - - (Run Finished) - - - Spec Tests Passing Failing Pending Skipped - ┌────────────────────────────────────────────────────────────────────────────────────────────────┐ - │ ✔ app_spec.coffee XX:XX 2 2 - - - │ - └────────────────────────────────────────────────────────────────────────────────────────────────┘ - ✔ All specs passed! XX:XX 2 2 - - - - - -` - -exports['e2e plugins / works with user extensions'] = ` - -==================================================================================================== - - (Run Starting) - - ┌────────────────────────────────────────────────────────────────────────────────────────────────┐ - │ Cypress: 1.2.3 │ - │ Browser: FooBrowser 88 │ - │ Specs: 1 found (app_spec.coffee) │ - │ Searched: cypress/integration/app_spec.coffee │ - └────────────────────────────────────────────────────────────────────────────────────────────────┘ - - -──────────────────────────────────────────────────────────────────────────────────────────────────── - - Running: app_spec.coffee (1 of 1) - - - ✓ can inject text from an extension - - 1 passing - - - (Results) - - ┌────────────────────────────────────────────────────────────────────────────────────────────────┐ - │ Tests: 1 │ - │ Passing: 1 │ - │ Failing: 0 │ - │ Pending: 0 │ - │ Skipped: 0 │ - │ Screenshots: 0 │ - │ Video: true │ - │ Duration: X seconds │ - │ Spec Ran: app_spec.coffee │ - └────────────────────────────────────────────────────────────────────────────────────────────────┘ - - - (Video) - - - Started processing: Compressing to 32 CRF - - Finished processing: /XXX/XXX/XXX/cypress/videos/app_spec.coffee.mp4 (X second) - - -==================================================================================================== - - (Run Finished) - - - Spec Tests Passing Failing Pending Skipped - ┌────────────────────────────────────────────────────────────────────────────────────────────────┐ - │ ✔ app_spec.coffee XX:XX 1 1 - - - │ - └────────────────────────────────────────────────────────────────────────────────────────────────┘ - ✔ All specs passed! XX:XX 1 1 - - - - - -` - -exports['e2e plugins handles absolute path to pluginsFile 1'] = ` - -==================================================================================================== - - (Run Starting) - - ┌────────────────────────────────────────────────────────────────────────────────────────────────┐ - │ Cypress: 1.2.3 │ - │ Browser: FooBrowser 88 │ - │ Specs: 1 found (absolute_spec.coffee) │ - │ Searched: cypress/integration/absolute_spec.coffee │ - └────────────────────────────────────────────────────────────────────────────────────────────────┘ - - -──────────────────────────────────────────────────────────────────────────────────────────────────── - - Running: absolute_spec.coffee (1 of 1) - - - ✓ uses the plugins file - - 1 passing - - - (Results) - - ┌────────────────────────────────────────────────────────────────────────────────────────────────┐ - │ Tests: 1 │ - │ Passing: 1 │ - │ Failing: 0 │ - │ Pending: 0 │ - │ Skipped: 0 │ - │ Screenshots: 0 │ - │ Video: true │ - │ Duration: X seconds │ - │ Spec Ran: absolute_spec.coffee │ - └────────────────────────────────────────────────────────────────────────────────────────────────┘ - - - (Video) - - - Started processing: Compressing to 32 CRF - - Finished processing: /XXX/XXX/XXX/cypress/videos/absolute_spec.coffee.mp4 (X second) - - -==================================================================================================== - - (Run Finished) - - - Spec Tests Passing Failing Pending Skipped - ┌────────────────────────────────────────────────────────────────────────────────────────────────┐ - │ ✔ absolute_spec.coffee XX:XX 1 1 - - - │ - └────────────────────────────────────────────────────────────────────────────────────────────────┘ - ✔ All specs passed! XX:XX 1 1 - - - - - -` - -exports['e2e plugins calls after:screenshot for cy.screenshot() and failure screenshots 1'] = ` - -==================================================================================================== - - (Run Starting) - - ┌────────────────────────────────────────────────────────────────────────────────────────────────┐ - │ Cypress: 1.2.3 │ - │ Browser: FooBrowser 88 │ - │ Specs: 1 found (after_screenshot_spec.coffee) │ - │ Searched: cypress/integration/after_screenshot_spec.coffee │ - └────────────────────────────────────────────────────────────────────────────────────────────────┘ - - -──────────────────────────────────────────────────────────────────────────────────────────────────── - - Running: after_screenshot_spec.coffee (1 of 1) - - - ✓ cy.screenshot() - replacement - ✓ cy.screenshot() - ignored values - ✓ cy.screenshot() - invalid return - 1) failure screenshot - rename - - 3 passing - 1 failing - - 1) failure screenshot - rename: - Error: test error - [stack trace lines] - - - - - (Results) - - ┌────────────────────────────────────────────────────────────────────────────────────────────────┐ - │ Tests: 4 │ - │ Passing: 3 │ - │ Failing: 1 │ - │ Pending: 0 │ - │ Skipped: 0 │ - │ Screenshots: 4 │ - │ Video: true │ - │ Duration: X seconds │ - │ Spec Ran: after_screenshot_spec.coffee │ - └────────────────────────────────────────────────────────────────────────────────────────────────┘ - - - (Screenshots) - - - /XXX/XXX/XXX/screenshot-replacement.png (YxX) - - /XXX/XXX/XXX/cypress/screenshots/after_screenshot_spec.coffee/ignored-values.png (YxX) - - /XXX/XXX/XXX/cypress/screenshots/after_screenshot_spec.coffee/invalid-return.png (YxX) - - /XXX/XXX/XXX/screenshot-replacement.png (YxX) - - - (Video) - - - Started processing: Compressing to 32 CRF - - Finished processing: /XXX/XXX/XXX/cypress/videos/after_screenshot_spec.coffee.mp (X second) - 4 - - -==================================================================================================== - - (Run Finished) - - - Spec Tests Passing Failing Pending Skipped - ┌────────────────────────────────────────────────────────────────────────────────────────────────┐ - │ ✖ after_screenshot_spec.coffee XX:XX 4 3 1 - - │ - └────────────────────────────────────────────────────────────────────────────────────────────────┘ - ✖ 1 of 1 failed (100%) XX:XX 4 3 1 - - - - -` - -exports['e2e plugins can filter browsers from config 1'] = ` -Can't run because you've entered an invalid browser name. - -Browser: 'chrome' was not found on your system. - -Available browsers found are: electron - -` - -exports['e2e plugins catches invalid viewportWidth returned from plugins 1'] = ` -An invalid configuration value returned from the plugins file: \`cypress/plugins/index.coffee\` - -Expected \`viewportWidth\` to be a number. Instead the value was: \`"foo"\` - -` - -exports['e2e plugins catches invalid browsers list returned from plugins 1'] = ` -An invalid configuration value returned from the plugins file: \`cypress/plugins/index.coffee\` - -Expected at least one browser - -` - -exports['e2e plugins catches invalid browser returned from plugins 1'] = ` -An invalid configuration value returned from the plugins file: \`cypress/plugins/index.coffee\` - -Found an error while validating the \`browsers\` list. Expected \`displayName\` to be a non-empty string. Instead the value was: \`{"name":"browser name","family":"chromium"}\` - -` diff --git a/packages/server/__snapshots__/3_plugins_spec.js b/packages/server/__snapshots__/3_plugins_spec.js index 1c2c6a05f7..b8e4f9cd09 100644 --- a/packages/server/__snapshots__/3_plugins_spec.js +++ b/packages/server/__snapshots__/3_plugins_spec.js @@ -1,4 +1,4 @@ -exports['e2e plugins passes 1'] = ` +exports['e2e plugins passes with working preprocessor 1'] = ` ==================================================================================================== @@ -58,7 +58,7 @@ exports['e2e plugins passes 1'] = ` ` -exports['e2e plugins fails 1'] = ` +exports['e2e plugins fails with async error 1'] = ` ==================================================================================================== @@ -175,13 +175,6 @@ exports['e2e plugins can modify config from plugins 1'] = ` ✔ All specs passed! XX:XX 2 2 - - - -` - -exports['e2e plugins catches invalid viewportWidth returned from plugins 1'] = ` -An invalid configuration value returned from the plugins file: \`cypress/plugins/index.coffee\` - -Expected \`viewportWidth\` to be a number. Instead the value was: \`"foo"\` - ` exports['e2e plugins catches invalid browsers list returned from plugins 1'] = ` @@ -402,3 +395,10 @@ exports['e2e plugins calls after:screenshot for cy.screenshot() and failure scre ` + +exports['e2e plugins catches invalid viewportWidth returned from plugins 1'] = ` +An invalid configuration value returned from the plugins file: \`cypress/plugins/index.coffee\` + +Expected \`viewportWidth\` to be a number. Instead the value was: \`"foo"\` + +` diff --git a/packages/server/lib/plugins/index.js b/packages/server/lib/plugins/index.js index 15f3b7536a..d00011f717 100644 --- a/packages/server/lib/plugins/index.js +++ b/packages/server/lib/plugins/index.js @@ -68,9 +68,16 @@ const init = (config, options) => { handler(ipc) } + _.extend(config, { + projectRoot: options.projectRoot, + configFile: options.configFile, + }) + ipc.send('load', config) ipc.on('loaded', (newCfg, registrations) => { + _.omit(config, 'projectRoot', 'configFile') + _.each(registrations, (registration) => { debug('register plugins process event', registration.event, 'with id', registration.eventId) @@ -105,9 +112,7 @@ const init = (config, options) => { const handleError = (err) => { debug('plugins process error:', err.stack) - if (!pluginsProcess) { - return // prevent repeating this in case of multiple errors - } + if (!pluginsProcess) return // prevent repeating this in case of multiple errors killPluginsProcess() err = errors.get('PLUGINS_ERROR', err.annotated || err.stack || err.message) @@ -116,11 +121,9 @@ const init = (config, options) => { return options.onError(err) } - const handleWarning = function (warningErr) { + const handleWarning = (warningErr) => { debug('plugins process warning:', warningErr.stack) - if (!pluginsProcess) { - return // prevent repeating this in case of multiple warnings - } + if (!pluginsProcess) return // prevent repeating this in case of multiple warnings return options.onWarning(warningErr) } diff --git a/packages/server/lib/project.js b/packages/server/lib/project.js index cd1012ae39..d73f6be7fa 100644 --- a/packages/server/lib/project.js +++ b/packages/server/lib/project.js @@ -159,6 +159,8 @@ class Project extends EE { cfg = config.whitelist(cfg) return plugins.init(cfg, { + projectRoot: this.projectRoot, + configFile: settings.pathToConfigFile(this.projectRoot, options), onError (err) { debug('got plugins error', err.stack) diff --git a/packages/server/test/e2e/3_plugins_spec.js b/packages/server/test/e2e/3_plugins_spec.js index 4db26897a6..e7df92f6b2 100644 --- a/packages/server/test/e2e/3_plugins_spec.js +++ b/packages/server/test/e2e/3_plugins_spec.js @@ -3,6 +3,7 @@ const path = require('path') const e2e = require('../support/helpers/e2e') const Fixtures = require('../support/helpers/fixtures') +const e2eProject = Fixtures.projectPath('e2e') const pluginExtension = Fixtures.projectPath('plugin-extension') const pluginConfig = Fixtures.projectPath('plugin-config') const pluginFilterBrowsers = Fixtures.projectPath('plugin-filter-browsers') @@ -14,10 +15,10 @@ const pluginReturnsBadConfig = Fixtures.projectPath('plugin-returns-bad-config') const pluginReturnsEmptyBrowsersList = Fixtures.projectPath('plugin-returns-empty-browsers-list') const pluginReturnsInvalidBrowser = Fixtures.projectPath('plugin-returns-invalid-browser') -describe('e2e plugins', () => { +describe('e2e plugins', function () { e2e.setup() - it('passes', function () { + it('passes with working preprocessor', function () { return e2e.exec(this, { spec: 'app_spec.coffee', project: workingPreprocessor, @@ -26,7 +27,7 @@ describe('e2e plugins', () => { }) }) - it('fails', function () { + it('fails with async error', function () { return e2e.exec(this, { spec: 'app_spec.coffee', project: pluginsAsyncError, @@ -121,4 +122,44 @@ describe('e2e plugins', () => { expectedExitCode: 1, }) }) + + describe('projectRoot and configFile', function () { + it('passes projectRoot and default configFile to plugins function', function () { + return e2e.exec(this, { + spec: 'plugins_config_extras_spec.js', + config: { + env: { + projectRoot: e2eProject, + configFile: path.join(e2eProject, 'cypress.json'), + }, + }, + }) + }) + + it('passes custom configFile to plugins function', function () { + return e2e.exec(this, { + spec: 'plugins_config_extras_spec.js', + configFile: 'cypress-alt.json', + config: { + env: { + projectRoot: e2eProject, + configFile: path.join(e2eProject, 'cypress-alt.json'), + }, + }, + }) + }) + + it('passes false configFile to plugins function', function () { + return e2e.exec(this, { + spec: 'plugins_config_extras_spec.js', + configFile: 'false', + config: { + env: { + projectRoot: e2eProject, + configFile: false, + }, + }, + }) + }) + }) }) diff --git a/packages/server/test/support/fixtures/projects/e2e/cypress-alt.json b/packages/server/test/support/fixtures/projects/e2e/cypress-alt.json new file mode 100644 index 0000000000..0967ef424b --- /dev/null +++ b/packages/server/test/support/fixtures/projects/e2e/cypress-alt.json @@ -0,0 +1 @@ +{} diff --git a/packages/server/test/support/fixtures/projects/e2e/cypress/integration/plugins_config_extras_spec.js b/packages/server/test/support/fixtures/projects/e2e/cypress/integration/plugins_config_extras_spec.js new file mode 100644 index 0000000000..35cc21d434 --- /dev/null +++ b/packages/server/test/support/fixtures/projects/e2e/cypress/integration/plugins_config_extras_spec.js @@ -0,0 +1,13 @@ +describe('plugins config extras', () => { + it('has correct projectRoot', () => { + cy.task('get:config:value', 'projectRoot') + .should('not.be.undefined') + .and('equal', Cypress.env('projectRoot')) + }) + + it('has correct configFile', () => { + cy.task('get:config:value', 'configFile') + .should('not.be.undefined') + .and('equal', Cypress.env('configFile')) + }) +}) 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 74bd46ffd1..52d24a873e 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 @@ -151,5 +151,9 @@ module.exports = (on, config) => { 'get:browser:args' () { return browserArgs }, + + 'get:config:value' (key) { + return config[key] + }, }) } diff --git a/packages/server/test/support/helpers/e2e.js b/packages/server/test/support/helpers/e2e.js index b44c4c024d..ebbd8d3feb 100644 --- a/packages/server/test/support/helpers/e2e.js +++ b/packages/server/test/support/helpers/e2e.js @@ -573,6 +573,10 @@ const e2e = { args.push(`--tag=${options.tag}`) } + if (options.configFile) { + args.push(`--config-file=${options.configFile}`) + } + return args }, diff --git a/packages/server/test/unit/browsers/browsers_spec.coffee b/packages/server/test/unit/browsers/browsers_spec.coffee index 73f39882e6..44c86faf87 100644 --- a/packages/server/test/unit/browsers/browsers_spec.coffee +++ b/packages/server/test/unit/browsers/browsers_spec.coffee @@ -6,6 +6,9 @@ browsers = require("#{root}../lib/browsers") utils = require("#{root}../lib/browsers/utils") snapshot = require('snap-shot-it') +normalizeBrowsers = (message) -> + message.replace(/(found are: ).*/, "$1chrome, firefox, electron") + describe "lib/browsers/index", -> context ".getBrowserInstance", -> it "returns instance", -> @@ -40,7 +43,7 @@ describe "lib/browsers/index", -> expect(browsers.ensureAndGetByNameOrPath("browserNotGonnaBeFound")) .to.be.rejectedWith({ type: 'BROWSER_NOT_FOUND_BY_NAME' }) .then (err) -> - snapshot(err.message) + snapshot(normalizeBrowsers(err.message)) it "throws a special error when canary is passed", -> sinon.stub(utils, "getBrowsers").resolves([ diff --git a/packages/server/test/unit/plugins/index_spec.js b/packages/server/test/unit/plugins/index_spec.js index 4913a81195..961f1b9083 100644 --- a/packages/server/test/unit/plugins/index_spec.js +++ b/packages/server/test/unit/plugins/index_spec.js @@ -8,36 +8,53 @@ const plugins = require(`${root}../lib/plugins`) const PLUGIN_PID = 77777 describe('lib/plugins/index', () => { - beforeEach(function () { + let pluginsProcess + let ipc + let configExtras + let getOptions + + beforeEach(() => { plugins._reset() - this.pluginsProcess = { + configExtras = { + projectRoot: '/path/to/project/root', + configFile: '/path/to/project/root/cypress.json', + } + + getOptions = (overrides = {}) => { + return { + ...configExtras, + ...overrides, + } + } + + pluginsProcess = { send: sinon.spy(), on: sinon.stub(), kill: sinon.spy(), pid: PLUGIN_PID, } - sinon.stub(cp, 'fork').returns(this.pluginsProcess) + sinon.stub(cp, 'fork').returns(pluginsProcess) - this.ipc = { + ipc = { send: sinon.spy(), on: sinon.stub(), } - sinon.stub(util, 'wrapIpc').returns(this.ipc) + sinon.stub(util, 'wrapIpc').returns(ipc) }) context('#init', () => { it('is noop if no pluginsFile', () => { - return plugins.init({}) // doesn't reject or time out + return plugins.init({}, getOptions()) // doesn't reject or time out }) - it('forks child process', function () { - // have to fire 'loaded' message, otherwise plugins.init promise never resolves - this.ipc.on.withArgs('loaded').yields([]) + it('forks child process', () => { + // have to fire "loaded" message, otherwise plugins.init promise never resolves + ipc.on.withArgs('loaded').yields([]) - return plugins.init({ pluginsFile: 'cypress-plugin' }) + return plugins.init({ pluginsFile: 'cypress-plugin' }, getOptions()) .then(() => { expect(cp.fork).to.be.called expect(cp.fork.lastCall.args[0]).to.contain('plugins/child/index.js') @@ -46,8 +63,8 @@ describe('lib/plugins/index', () => { }) }) - it('uses system Node when available', function () { - this.ipc.on.withArgs('loaded').yields([]) + it('uses system Node when available', () => { + ipc.on.withArgs('loaded').yields([]) const systemNode = '/my/path/to/system/node' const config = { pluginsFile: 'cypress-plugin', @@ -56,7 +73,7 @@ describe('lib/plugins/index', () => { resolvedNodePath: systemNode, } - return plugins.init(config) + return plugins.init(config, getOptions()) .then(() => { const options = { stdio: 'inherit', @@ -67,15 +84,15 @@ describe('lib/plugins/index', () => { }) }) - it('uses bundled Node when cannot find system Node', function () { - this.ipc.on.withArgs('loaded').yields([]) + it('uses bundled Node when cannot find system Node', () => { + ipc.on.withArgs('loaded').yields([]) const config = { pluginsFile: 'cypress-plugin', nodeVersion: 'system', resolvedNodeVersion: 'v1.2.3', } - return plugins.init(config) + return plugins.init(config, getOptions()) .then(() => { const options = { stdio: 'inherit', @@ -85,13 +102,13 @@ describe('lib/plugins/index', () => { }) }) - it('calls any handlers registered with the wrapped ipc', function () { - this.ipc.on.withArgs('loaded').yields([]) + it('calls any handlers registered with the wrapped ipc', () => { + ipc.on.withArgs('loaded').yields([]) const handler = sinon.spy() plugins.registerHandler(handler) - return plugins.init({ pluginsFile: 'cypress-plugin' }) + return plugins.init({ pluginsFile: 'cypress-plugin' }, getOptions()) .then(() => { expect(handler).to.be.called expect(handler.lastCall.args[0].send).to.be.a('function') @@ -100,51 +117,56 @@ describe('lib/plugins/index', () => { }) }) - it('sends config via ipc', function () { - this.ipc.on.withArgs('loaded').yields([]) + it('sends \'load\' event with config via ipc', () => { + ipc.on.withArgs('loaded').yields([]) const config = { pluginsFile: 'cypress-plugin' } - return plugins.init(config).then(() => { - expect(this.ipc.send).to.be.calledWith('load', config) + return plugins.init(config, getOptions()).then(() => { + expect(ipc.send).to.be.calledWith('load', { + ...config, + ...configExtras, + }) }) }) - it('resolves once it receives \'loaded\' message', function () { - this.ipc.on.withArgs('loaded').yields([]) + it('resolves once it receives \'loaded\' message', () => { + ipc.on.withArgs('loaded').yields([]) // should resolve and not time out - return plugins.init({ pluginsFile: 'cypress-plugin' }) + return plugins.init({ pluginsFile: 'cypress-plugin' }, getOptions()) }) - it('kills child process if it already exists', function () { - this.ipc.on.withArgs('loaded').yields([]) + it('kills child process if it already exists', () => { + ipc.on.withArgs('loaded').yields([]) - return plugins.init({ pluginsFile: 'cypress-plugin' }) + return plugins.init({ pluginsFile: 'cypress-plugin' }, getOptions()) .then(() => { - return plugins.init({ pluginsFile: 'cypress-plugin' }) + return plugins.init({ pluginsFile: 'cypress-plugin' }, getOptions()) }).then(() => { - expect(this.pluginsProcess.kill).to.be.calledOnce + expect(pluginsProcess.kill).to.be.calledOnce }) }) describe('loaded message', () => { - beforeEach(function () { - this.config = {} + let config - this.ipc.on.withArgs('loaded').yields(this.config, [{ + beforeEach(() => { + config = {} + + ipc.on.withArgs('loaded').yields(config, [{ event: 'some:event', eventId: 0, }]) - return plugins.init({ pluginsFile: 'cypress-plugin' }) + return plugins.init({ pluginsFile: 'cypress-plugin' }, getOptions()) }) - it('sends \'execute\' message when event is executed, wrapped in promise', function () { + it('sends \'execute\' message when event is executed, wrapped in promise', () => { sinon.stub(util, 'wrapParentPromise').resolves('value').yields('00') return plugins.execute('some:event', 'foo', 'bar').then((value) => { expect(util.wrapParentPromise).to.be.called - expect(this.ipc.send).to.be.calledWith( + expect(ipc.send).to.be.calledWith( 'execute', 'some:event', { eventId: 0, invocationId: '00' }, @@ -158,12 +180,12 @@ describe('lib/plugins/index', () => { describe('load:error message', () => { context('PLUGINS_FILE_ERROR', () => { - beforeEach(function () { - this.ipc.on.withArgs('load:error').yields('PLUGINS_FILE_ERROR', 'path/to/pluginsFile.js', 'error message stack') + beforeEach(() => { + ipc.on.withArgs('load:error').yields('PLUGINS_FILE_ERROR', 'path/to/pluginsFile.js', 'error message stack') }) it('rejects plugins.init', () => { - return plugins.init({ pluginsFile: 'cypress-plugin' }) + return plugins.init({ pluginsFile: 'cypress-plugin' }, getOptions()) .catch((err) => { expect(err.message).to.contain('The plugins file is missing or invalid') expect(err.message).to.contain('path/to/pluginsFile.js') @@ -174,12 +196,12 @@ describe('lib/plugins/index', () => { }) context('PLUGINS_FUNCTION_ERROR', () => { - beforeEach(function () { - this.ipc.on.withArgs('load:error').yields('PLUGINS_FUNCTION_ERROR', 'path/to/pluginsFile.js', 'error message stack') + beforeEach(() => { + ipc.on.withArgs('load:error').yields('PLUGINS_FUNCTION_ERROR', 'path/to/pluginsFile.js', 'error message stack') }) it('rejects plugins.init', () => { - return plugins.init({ pluginsFile: 'cypress-plugin' }) + return plugins.init({ pluginsFile: 'cypress-plugin' }, getOptions()) .catch((err) => { expect(err.message).to.contain('The function exported by the plugins file threw an error.') expect(err.message).to.contain('path/to/pluginsFile.js') @@ -191,46 +213,49 @@ describe('lib/plugins/index', () => { }) describe('error message', () => { - beforeEach(function () { - this.err = { + let err + let onError + + beforeEach(() => { + err = { name: 'error name', message: 'error message', } - this.onError = sinon.spy() - this.ipc.on.withArgs('loaded').yields([]) + onError = sinon.spy() + ipc.on.withArgs('loaded').yields([]) - return plugins.init({ pluginsFile: 'cypress-plugin' }, { onError: this.onError }) + return plugins.init({ pluginsFile: 'cypress-plugin' }, getOptions({ onError })) }) - it('kills the plugins process when plugins process errors', function () { - this.pluginsProcess.on.withArgs('error').yield(this.err) + it('kills the plugins process when plugins process errors', () => { + pluginsProcess.on.withArgs('error').yield(err) - expect(this.pluginsProcess.kill).to.be.called + expect(pluginsProcess.kill).to.be.called }) - it('kills the plugins process when ipc sends error', function () { - this.ipc.on.withArgs('error').yield(this.err) + it('kills the plugins process when ipc sends error', () => { + ipc.on.withArgs('error').yield(err) - expect(this.pluginsProcess.kill).to.be.called + expect(pluginsProcess.kill).to.be.called }) - it('calls onError when plugins process errors', function () { - this.pluginsProcess.on.withArgs('error').yield(this.err) - expect(this.onError).to.be.called - expect(this.onError.lastCall.args[0].title).to.equal('Error running plugin') - expect(this.onError.lastCall.args[0].stack).to.include('The following error was thrown by a plugin') + it('calls onError when plugins process errors', () => { + pluginsProcess.on.withArgs('error').yield(err) + expect(onError).to.be.called + expect(onError.lastCall.args[0].title).to.equal('Error running plugin') + expect(onError.lastCall.args[0].stack).to.include('The following error was thrown by a plugin') - expect(this.onError.lastCall.args[0].details).to.include(this.err.message) + expect(onError.lastCall.args[0].details).to.include(err.message) }) - it('calls onError when ipc sends error', function () { - this.ipc.on.withArgs('error').yield(this.err) - expect(this.onError).to.be.called - expect(this.onError.lastCall.args[0].title).to.equal('Error running plugin') - expect(this.onError.lastCall.args[0].stack).to.include('The following error was thrown by a plugin') + it('calls onError when ipc sends error', () => { + ipc.on.withArgs('error').yield(err) + expect(onError).to.be.called + expect(onError.lastCall.args[0].title).to.equal('Error running plugin') + expect(onError.lastCall.args[0].stack).to.include('The following error was thrown by a plugin') - expect(this.onError.lastCall.args[0].details).to.include(this.err.message) + expect(onError.lastCall.args[0].details).to.include(err.message) }) }) }) @@ -286,10 +311,10 @@ describe('lib/plugins/index', () => { plugins._setPluginsProcess(null) }) - it('returns the pid if there is a plugins process', function () { - this.ipc.on.withArgs('loaded').yields([]) + it('returns the pid if there is a plugins process', () => { + ipc.on.withArgs('loaded').yields([]) - return plugins.init({ pluginsFile: 'cypress-plugin' }) + return plugins.init({ pluginsFile: 'cypress-plugin' }, getOptions()) .then(() => { expect(plugins.getPluginPid()).to.eq(PLUGIN_PID) })