Writing a Plugin
The Plugins API allows you to hook into and extend Cypress behavior.
Note: This document assumes you have read the Plugins Guide.
Plugins API
To get started, open up this file:
cypress/plugins/index.js
The plugins file must export a function with the following signature:
// cypress/plugins/index.js
// export a function
module.exports = (on, config) => {
// configure plugins here
}
⚠️ This code is part of the
plugins file
and thus executes in the Node environment. You cannot call Cypress
or cy
commands in this file, but you do have the direct access to the file system and
the rest of the operating system.
The exported function is called whenever a project is opened either with cypress open or cypress run.
Your function will receive 2 arguments: on
and config
.
You can return a synchronous function, or you can also return a Promise, and it will be awaited until it resolves. This enables you to perform asynchronous actions in your exported function such as reading files in from the filesystem.
If you return or resolve with an object, Cypress will then merge this object
into the config
which enables you to overwrite configuration or environment
variables.
on
on
is a function that you will use to register listeners on various events
that Cypress exposes.
Registering to listen on an event looks like this:
module.exports = (on, config) => {
on('<event>', (arg1, arg2) => {
// plugin stuff here
})
}
Each event documents its own argument signature. To understand how to use them, please refer to the docs for each one.
config
config
is the resolved
Cypress configuration of the opened project.
This configuration contains all of the values that get passed into the browser for your project.
For a comprehensive list of all configuration values look here.
Some plugins may utilize or require these values, so they can take certain actions based on the configuration.
You can programmatically modify these values and Cypress will then respect these changes. This enables you to swap out configuration based on things like the environment you're running in.
The config
object also includes the following extra values that are not part
of the standard configuration. These values are read only and cannot be
modified from the plugins file.
configFile
: The absolute path to the config file. By default, this is<projectRoot>/cypress.json
, but may be a custom path orfalse
if using the--config-file
flag.projectRoot
: The absolute path to the root of the project (e.g./Users/me/dev/my-project
)version
: The version number of Cypress. This can be used to handle breaking changes.
Please check out our API docs for modifying configuration here.
List of events
The following events are available:
Event | Description |
---|---|
after:run | Occurs after the run is finished. |
after:screenshot | Occurs after a screenshot is taken. |
after:spec | Occurs after a spec is finished running. |
before:browser:launch | Occurs immediately before launching a browser. |
before:run | Occurs before the run starts. |
before:spec | Occurs when a spec is about to be run. |
file:preprocessor | Occurs when a spec or spec-related file needs to be transpiled for the browser. |
task | Occurs in conjunction with the cy.task command. |
Execution context
Your pluginsFile
is invoked when Cypress opens a project.
Cypress does this by spawning an independent child_process
which then
requires
in your pluginsFile
. This is similar to the way Visual Studio Code
or Atom works.
The code in this file will be executed using the the Node version that launched Cypress.
npm modules
When Cypress executes your pluginsFile
it will execute with process.cwd()
set to your project's path. Additionally - you will be able to require
any
node module you have installed.
You can also require
local files relative to your project.
For example, if your package.json
looked like this:
{
"name": "My Project",
"dependencies": {
"debug": "x.x.x"
},
"devDependencies": {
"lodash": "x.x.x"
}
}
Then you could do any of the following in your pluginsFile
:
// cypress/plugins/index.js
const _ = require('lodash') // yup, dev dependencies
const path = require('path') // yup, built in node modules
const debug = require('debug') // yup, dependencies
const User = require('../../lib/models/user') // yup, relative local modules
console.log(__dirname) // /Users/janelane/Dev/my-project/cypress/plugins/index.js
console.log(process.cwd()) // /Users/janelane/Dev/my-project
Error handling
Cypress spawns your pluginsFile
in its own child process so it is isolated
away from the context that Cypress itself runs in. That means you cannot
accidentally modify or change Cypress's own execution in any way.
If your pluginsFile
has an uncaught exception, an unhandled rejection from a
promise, or a syntax error - we will automatically catch those and display them
to you inside of the console and even in the Test Runner itself.
Errors from your plugins will not crash Cypress.
File changes
Normally when writing code in Node, you typically have to restart the process after changing any files.
With Cypress, we automatically watch your pluginsFile
and any changes made
will take effect immediately. We will read the file in and execute the exported
function again.
This enables you to iterate on plugin code even with Cypress already running.