Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

PluginEvents do not support multiple handlers #22428

Open
jeremygiberson opened this issue Jun 21, 2022 · 10 comments
Open

PluginEvents do not support multiple handlers #22428

jeremygiberson opened this issue Jun 21, 2022 · 10 comments
Labels
E2E Issue related to end-to-end testing topic: plugins ⚙️ Triaged Issue has been routed to backlog. This is not a commitment to have it prioritized by the team. type: bug

Comments

@jeremygiberson
Copy link

jeremygiberson commented Jun 21, 2022

Current behavior

Seemingly, as of cypress 10, if you have multiple plugins that register handlers for before:run, after:run, before:spec, or after:spec, only the last registered handler is dispatched.

Desired behavior

All event handlers should be dispatched.

Test code to reproduce

I've added a test spec for the scenario in the fork/branch: https://github.com/jeremygiberson/cypress/tree/run-events-multiple-bug. See pull request #22429

const { defineConfig } = require('cypress')

module.exports = defineConfig({
  // setupNodeEvents can be defined in either
  // the e2e or component configuration
  e2e: {
    setupNodeEvents(on, config) {
      on('before:run', ()=>{ console.log('before:run first handler') });
      on('before:run', ()=>{ console.log('before:run second handler') });
    }
  }
})

On execution of cypress test, you will only see the presence of "before:run second handler" in the output.

Cypress Version

^10.0.0

Other

Based on cursory investigation it seems like this is due to the EventRegistrar implementation. It seems like this is the class that handles plugin event registration.

But the implementation is such that there can only be a single callback for an event.

export class EventRegistrar {
  private _registeredEvents: Record<string, Function> = {}
}

Presumably, the implementation should be such that multiple callbacks can be registered per event.

export class EventRegistrar {
  private _registeredEvents: Record<string, Array<Function>> = {}
}

I'm not familiar with the cypress internals, so take with a grain of salt.

@cypress-bot cypress-bot bot added the stage: investigating Someone from Cypress is looking into this label Jun 22, 2022
@tbiethman
Copy link
Contributor

@jeremygiberson thank you very much for the report and the PR reproducing the issue. It is very much appreciated! I gave your branch a pull and verified your findings.

I will leave your PR open until this issue is prioritized so that we can ensure the work you did for us gets included. I am going to mark it as a draft, though, so it doesn't get merged prematurely.

@BuckyMaler
Copy link

Is there a chance this'll be patched for v10?

@BuckyMaler
Copy link

@nagash77 any update on this?

@alanfitzpatrick
Copy link

Would love an update on this

@matys84pl
Copy link

Any news on this?

@nagash77
Copy link
Contributor

@matys84pl This is not currently slated for development in the near future. We of course always welcome contributions from the community if anyone were so inclined.

@elaichenkov
Copy link

Hi all,
I've faced the same issue. So, I decided to create a library that can fix the problem. You just need to install the library with the following command:

npm i -D cypress-plugin-init 

And then, you need to import the initPlugins function and use it in your cypress.config.ts file:

// import the function
import { initPlugins } from 'cypress-plugin-init';

// For example you have two plugins:
const plugin1 = (on: Cypress.PluginEvents) => {
  on('before:run', (_) => console.log('[Plugin #1] Running before:run'));
};

const plugin2 = (on: Cypress.PluginEvents) => {
  on('before:run', (_) => console.log('[Plugin #2] Running before:run'));
};


export default defineConfig({
  e2e: {
   // ...
    setupNodeEvents(on, config) {
      // invoke the function with all plugins that you need instead of the 'plugin1' and 'plugin2'
      initPlugins(on, [plugin1, plugin2]);
    },
   // ...
  },
});

It will print the following output:

(Run Starting)
...
[Plugin #1] Running before:run
[Plugin #2] Running before:run
...
(Run Finished)

@bahmutov
Copy link
Contributor

bahmutov commented Apr 3, 2023

I too created a plugin to proxy events to multiple listeners cypress-on-fix

const { defineConfig } = require('cypress')

module.exports = defineConfig({
  e2e: {
    // baseUrl, etc
    supportFile: false,
    fixturesFolder: false,
    setupNodeEvents(cypressOn, config) {
      const on = require('cypress-on-fix')(cypressOn)
      // use "on" to register plugins, for example
      // https://github.com/bahmutov/cypress-split
      require('cypress-split')(on, config)
      // https://github.com/bahmutov/cypress-watch-and-reload
      require('cypress-watch-and-reload/plugins')(on, config)
      // https://github.com/bahmutov/cypress-code-coverage
      require('@bahmutov/cypress-code-coverage/plugin')(on, config)
    },
  },
})

@Deop
Copy link

Deop commented Apr 3, 2023

Hi @bahmutov I was trying to set this up but couldn't get it working. I'm still using plugin/index.js file which I then import into config file as setupNodeEvents, could you please give an example for this scenario?

@bahmutov
Copy link
Contributor

bahmutov commented Apr 3, 2023

@Deop can you open an issue in the https://github.com/kouzoh/test-framework-cypress/pull/2784 repo with a reproducible / code example?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
E2E Issue related to end-to-end testing topic: plugins ⚙️ Triaged Issue has been routed to backlog. This is not a commitment to have it prioritized by the team. type: bug
Projects
None yet
Development

No branches or pull requests