From ced36a8f54c20248b311ea3737c5ec062b2a7315 Mon Sep 17 00:00:00 2001 From: "David A. Ramos" Date: Thu, 21 Sep 2023 22:36:54 -0700 Subject: [PATCH] [cypress] Avoid clobbering conflicting event handlers This works around https://github.com/cypress-io/cypress/issues/22428. --- packages/cypress-plugin/cypress-on-fix.d.ts | 8 ++++++++ packages/cypress-plugin/package.json | 1 + packages/cypress-plugin/src/index.ts | 8 +++++++- packages/cypress-plugin/src/tsconfig.json | 2 +- .../test/integration-input-manual/cypress-config.mjs | 11 +++++++---- .../test/integration-input-manual/cypress.config.js | 11 +++++++---- .../test/integration-input-manual/package.json | 1 + packages/cypress-plugin/tsconfig.json | 2 +- yarn.lock | 9 +++++++++ 9 files changed, 42 insertions(+), 11 deletions(-) create mode 100644 packages/cypress-plugin/cypress-on-fix.d.ts diff --git a/packages/cypress-plugin/cypress-on-fix.d.ts b/packages/cypress-plugin/cypress-on-fix.d.ts new file mode 100644 index 0000000..abce4b3 --- /dev/null +++ b/packages/cypress-plugin/cypress-on-fix.d.ts @@ -0,0 +1,8 @@ +// Copyright (c) 2023 Developer Innovations, LLC + +declare module "cypress-on-fix" { + import * as Cypress from "cypress"; + export default function onProxy( + on: Cypress.PluginEvents + ): Cypress.PluginEvents; +} diff --git a/packages/cypress-plugin/package.json b/packages/cypress-plugin/package.json index 604db86..0cd0dc7 100644 --- a/packages/cypress-plugin/package.json +++ b/packages/cypress-plugin/package.json @@ -52,6 +52,7 @@ "cli-table3": "0.5.1", "cosmiconfig": "^7.0.1", "cypress-multi-reporters": "^1.6.3", + "cypress-on-fix": "^1.0.2", "dayjs": "^1.10.4", "debug": "^4.3.3", "deep-equal": "^2.0.5", diff --git a/packages/cypress-plugin/src/index.ts b/packages/cypress-plugin/src/index.ts index 90b54e5..fb65ae9 100644 --- a/packages/cypress-plugin/src/index.ts +++ b/packages/cypress-plugin/src/index.ts @@ -19,6 +19,7 @@ import { ENV_VAR_AUTO_SUPPORT, ENV_VAR_UNFLAKABLE_RESOLVED_CONFIG_JSON, } from "./config-env-vars"; +import cypressOnFix from "cypress-on-fix"; export { PluginOptions }; @@ -100,9 +101,14 @@ const wrapSetupNodeEvents = | undefined ) => async ( - on: Cypress.PluginEvents, + baseOn: Cypress.PluginEvents, config: Cypress.PluginConfigOptions ): Promise => { + // Due to https://github.com/cypress-io/cypress/issues/22428, only the last event handler + // registered for each event type will be called. This means we'll clobber any event handlers + // the user registers. To avoid this, we use cypress-on-fix. + const on = cypressOnFix(baseOn); + const userModifiedConfig = userSetupNodeEvents !== undefined ? await userSetupNodeEvents(on, config) diff --git a/packages/cypress-plugin/src/tsconfig.json b/packages/cypress-plugin/src/tsconfig.json index 44badea..80d8585 100644 --- a/packages/cypress-plugin/src/tsconfig.json +++ b/packages/cypress-plugin/src/tsconfig.json @@ -1,4 +1,4 @@ { "extends": "../tsconfig.json", - "include": ["../mocha.d.ts", ".", ".eslintrc.js"] + "include": ["../cypress-on-fix.d.ts", "../mocha.d.ts", ".", ".eslintrc.js"] } diff --git a/packages/cypress-plugin/test/integration-input-manual/cypress-config.mjs b/packages/cypress-plugin/test/integration-input-manual/cypress-config.mjs index 952022a..d5d5a61 100644 --- a/packages/cypress-plugin/test/integration-input-manual/cypress-config.mjs +++ b/packages/cypress-plugin/test/integration-input-manual/cypress-config.mjs @@ -8,6 +8,7 @@ import { registerCosmiconfigMock } from "unflakable-test-common/dist/config.js"; import { registerUnflakable } from "@unflakable/cypress-plugin"; import semverGte from "semver/functions/gte.js"; import path from "path"; +import cypressOnFix from "cypress-on-fix"; /** * @type {Cypress.ConfigOptions} @@ -15,11 +16,12 @@ import path from "path"; export default { component: { /** - * @param {Cypress.PluginEvents} on + * @param {Cypress.PluginEvents} baseOn * @param {Cypress.PluginConfigOptions} config * @returns {Promise | Cypress.PluginConfigOptions | void} */ - setupNodeEvents(on, config) { + setupNodeEvents(baseOn, config) { + const on = cypressOnFix(baseOn); registerCosmiconfigMock(); registerSimpleGitMock(); tasks.registerTasks(on); @@ -35,11 +37,12 @@ export default { }, e2e: { /** - * @param {Cypress.PluginEvents} on + * @param {Cypress.PluginEvents} baseOn * @param {Cypress.PluginConfigOptions} config * @returns {Promise | Cypress.PluginConfigOptions | void} */ - setupNodeEvents(on, config) { + setupNodeEvents(baseOn, config) { + const on = cypressOnFix(baseOn); registerCosmiconfigMock(); registerSimpleGitMock(); tasks.registerTasks(on); diff --git a/packages/cypress-plugin/test/integration-input-manual/cypress.config.js b/packages/cypress-plugin/test/integration-input-manual/cypress.config.js index 9e0a4e8..376bd1f 100644 --- a/packages/cypress-plugin/test/integration-input-manual/cypress.config.js +++ b/packages/cypress-plugin/test/integration-input-manual/cypress.config.js @@ -11,6 +11,7 @@ const semverGte = require("semver/functions/gte"); const { registerUnflakable } = require("@unflakable/cypress-plugin"); const path = require("path"); +const cypressOnFix = require("cypress-on-fix"); module.exports = { /** @@ -18,11 +19,12 @@ module.exports = { */ component: { /** - * @param {Cypress.PluginEvents} on + * @param {Cypress.PluginEvents} baseOn * @param {Cypress.PluginConfigOptions} config * @returns {Promise | Cypress.PluginConfigOptions | void} */ - setupNodeEvents(on, config) { + setupNodeEvents(baseOn, config) { + const on = cypressOnFix(baseOn); registerCosmiconfigMock(); registerSimpleGitMock(); registerTasks(on); @@ -38,11 +40,12 @@ module.exports = { }, e2e: { /** - * @param {Cypress.PluginEvents} on + * @param {Cypress.PluginEvents} baseOn * @param {Cypress.PluginConfigOptions} config * @returns {Promise | Cypress.PluginConfigOptions | void} */ - setupNodeEvents(on, config) { + setupNodeEvents(baseOn, config) { + const on = cypressOnFix(baseOn); registerCosmiconfigMock(); registerSimpleGitMock(); registerTasks(on); diff --git a/packages/cypress-plugin/test/integration-input-manual/package.json b/packages/cypress-plugin/test/integration-input-manual/package.json index 49515a8..c67d68d 100644 --- a/packages/cypress-plugin/test/integration-input-manual/package.json +++ b/packages/cypress-plugin/test/integration-input-manual/package.json @@ -11,6 +11,7 @@ "@unflakable/cypress-plugin": "workspace:^", "cypress": "11.2 - 13", "cypress-multi-reporters": "^1.6.3", + "cypress-on-fix": "^1.0.2", "mocha": "=7.0.1", "mocha-junit-reporter": "^2.2.0", "process": "^0.11.10", diff --git a/packages/cypress-plugin/tsconfig.json b/packages/cypress-plugin/tsconfig.json index 9e9a7c8..786cbe3 100644 --- a/packages/cypress-plugin/tsconfig.json +++ b/packages/cypress-plugin/tsconfig.json @@ -15,5 +15,5 @@ // Avoids conflicting global definitions from, e.g., jest. "types": ["node"] }, - "include": ["mocha.d.ts", "rollup.config.mjs"] + "include": ["cypress-on-fix.d.ts", "mocha.d.ts", "rollup.config.mjs"] } diff --git a/yarn.lock b/yarn.lock index 7398f4c..5eb8cd1 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3218,6 +3218,7 @@ __metadata: cross-env: ^7.0.3 cypress: 11.2 - 13 cypress-multi-reporters: ^1.6.3 + cypress-on-fix: ^1.0.2 dayjs: ^1.10.4 debug: ^4.3.3 deep-equal: ^2.0.5 @@ -4789,6 +4790,7 @@ __metadata: "@unflakable/cypress-plugin": "workspace:^" cypress: 11.2 - 13 cypress-multi-reporters: ^1.6.3 + cypress-on-fix: ^1.0.2 mocha: =7.0.1 mocha-junit-reporter: ^2.2.0 process: ^0.11.10 @@ -4856,6 +4858,13 @@ __metadata: languageName: node linkType: hard +"cypress-on-fix@npm:^1.0.2": + version: 1.0.2 + resolution: "cypress-on-fix@npm:1.0.2" + checksum: b35e0d49e4270237e7cbe95c21d458772d3df6bbb4423346c70f9417e61fdf061ad1d83aca76a854a378d001a68f50c17b8dd312fbe9c50b5d12e61fc317a785 + languageName: node + linkType: hard + "cypress@npm:11.2 - 13": version: 12.14.0 resolution: "cypress@npm:12.14.0"