Overcoming Cypress limitations with cypress-plugin-init library
Introduction
The Cypress plugin system is a powerful way to extend Cypress functionality, but it has some limitations. One of the biggest limitations is that you can only have one listener for a specific event. This means that if you want to use multiple plugins or reporters that listen to the same event, you can’t do it. This is where the cypress-plugin-init
library comes in. This open-source library simplifies the process of setting up multiple Cypress plugins or reporters in your project, making it easier to use multiple plugins or reporters that listen to the same event.
Background
Before we get started, I want to say a few words about the Cypress plugin system. It is a great way to extend the functionality of Cypress by adding custom code to your tests. Plugins can modify Cypress behavior, add commands, or listen to events. However, the plugin system is limited in some ways. One of the biggest limitations is that you can only have one listener for a specific event. This means that if you have multiple plugins or reporters that listen to the same event, only one of them will be fired. This limitation has been reported on the Cypress GitHub repository in issues #22428 and #5240.
Getting Started
To use the cypress-plugin-init
library, you'll need to install it in your Cypress project. You can do this using npm:
npm i-D cypress-plugin-init
Once you’ve installed the library, you can use it to initialize multiple plugins that listen to the same event. Here’s an example of how to use the library to initialize two plugins that listen to the before:run
event.
In the example below, we’re using the initPlugins
function provided by the cypress-plugin-init
library. This function takes three arguments:
on
— requiredplugins[]
— requiredconfig
— optional
import { defineConfig } from 'cypress';
import { initPlugins } from 'cypress-plugin-init';
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) {
initPlugins(on, [plugin1, plugin2]);
},
},
});
And then, when you run this code you will notice the result in your terminal:
(Run Starting)
...
[Plugin #1] Running before:run
[Plugin #2] Running before:run
...
(Run Finished)
However, if you run the same code without the initPlugins
function, the output will be:
(Run Starting)
...
[Plugin #2] Running before:run
...
(Run Finished)
Real-world working example
You want to have two reporters. The first one is registerAIOTestsPlugin for Jira and the second one is cypress-mochawesome-reporter HTML for your CI. So, in your case, it is not possible to have both of them at the same time without cypress-plugin-init
library. Hence, here is an example of how to include these two reporters in your Cypress config:
import { initPlugins } from 'cypress-plugin-init';
import { registerAIOTestsPlugin } from 'cypress-aiotests-reporter/src';
import cypressMochawesomeReporter from 'cypress-mochawesome-reporter/plugin';
export default defineConfig({
e2e: {
// ...
setupNodeEvents(on, config) {
initPlugins(on, [registerAIOTestsPlugin, cypressMochawesomeReporter], config);
},
// ...
},
});
Conclusion
The cypress-plugin-init
library is a powerful tool that simplifies the process of setting up multiple Cypress plugins in your project. With this library, you can use multiple plugins that listen to the same event, allowing you to extend Cypress functionality in new and creative ways. I hope this article has shown you how to use the cypress-plugin-init
library and provided examples of how it can be useful in your Cypress projects. For more information on the library, you can read its documentation on GitHub.