{
  "doc": {
    "id": "api/node-events/overview",
    "title": "Overview of Node Events in Cypress",
    "description": "Node event hooks enable you to tap into, modify, or extend the internal behavior of Cypress.",
    "section": "api",
    "source_path": "/llm/markdown/api/node-events/overview.md",
    "version": "a8fd16711bdda4c7b5645b9717e588ae99ec2470",
    "updated_at": "2026-05-18T17:21:32.047Z",
    "headings": [
      {
        "id": "api/node-events/overview#node-events-overview",
        "text": "Node Events Overview",
        "level": 1
      },
      {
        "id": "api/node-events/overview#setupnodeevents",
        "text": "setupNodeEvents",
        "level": 2
      },
      {
        "id": "api/node-events/overview#on",
        "text": "on",
        "level": 3
      },
      {
        "id": "api/node-events/overview#list-of-events",
        "text": "List of events",
        "level": 4
      },
      {
        "id": "api/node-events/overview#config",
        "text": "config",
        "level": 3
      },
      {
        "id": "api/node-events/overview#use-cases",
        "text": "Use Cases",
        "level": 2
      },
      {
        "id": "api/node-events/overview#configuration",
        "text": "Configuration",
        "level": 3
      },
      {
        "id": "api/node-events/overview#preprocessors",
        "text": "Preprocessors",
        "level": 3
      },
      {
        "id": "api/node-events/overview#run-lifecycle",
        "text": "Run Lifecycle",
        "level": 3
      },
      {
        "id": "api/node-events/overview#spec-lifecycle",
        "text": "Spec Lifecycle",
        "level": 3
      },
      {
        "id": "api/node-events/overview#browser-launching",
        "text": "Browser Launching",
        "level": 3
      },
      {
        "id": "api/node-events/overview#screenshot-handling",
        "text": "Screenshot handling",
        "level": 3
      },
      {
        "id": "api/node-events/overview#cy-task",
        "text": "cy.task",
        "level": 3
      },
      {
        "id": "api/node-events/overview#execution-context",
        "text": "Execution context",
        "level": 2
      },
      {
        "id": "api/node-events/overview#npm-modules",
        "text": "npm modules",
        "level": 3
      },
      {
        "id": "api/node-events/overview#error-handling",
        "text": "Error handling",
        "level": 2
      },
      {
        "id": "api/node-events/overview#file-changes",
        "text": "File changes",
        "level": 2
      },
      {
        "id": "api/node-events/overview#real-world-example",
        "text": "Real World Example",
        "level": 2
      }
    ]
  },
  "chunks": [
    {
      "id": "api/node-events/overview#setupnodeevents",
      "doc_id": "api/node-events/overview",
      "heading": "setupNodeEvents",
      "heading_level": 2,
      "content_markdown": "## setupNodeEvents\n\nThe [`setupNodeEvents`](/llm/markdown/app/references/configuration.md#setupNodeEvents) function receives 2 arguments: [`on`](#on) and [`config`](#config). It can return a synchronous value or can also return a Promise, which will be awaited until it resolves. This enables you to perform asynchronous actions such as reading files in from the filesystem.\n\nIf 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.\n\n*   cypress.config.js\n*   cypress.config.ts\n\n```\nconst { defineConfig } = require('cypress')module.exports = defineConfig({  // setupNodeEvents can be defined in either  // the e2e or component configuration  e2e: {    setupNodeEvents(on, config) {      // configure plugins here    },  },})\n```\n\n```\nimport { defineConfig } from 'cypress'export default defineConfig({  // setupNodeEvents can be defined in either  // the e2e or component configuration  e2e: {    setupNodeEvents(on, config) {      // configure plugins here    },  },})\n```\n\n### on\n\n`on` is a function that you will use to register listeners on various **events** that Cypress exposes.\n\nRegistering to listen on an event looks like this:\n\n*   cypress.config.js\n*   cypress.config.ts\n\n```\nconst { defineConfig } = require('cypress')module.exports = defineConfig({  // setupNodeEvents can be defined in either  // the e2e or component configuration  e2e: {    setupNodeEvents(on, config) {      on('<event>', (arg1, arg2) => {        // plugin stuff here      })    },  },})\n```\n\n```\nimport { defineConfig } from 'cypress'export default defineConfig({  // setupNodeEvents can be defined in either  // the e2e or component configuration  e2e: {    setupNodeEvents(on, config) {      on('<event>', (arg1, arg2) => {        // plugin stuff here      })    },  },})\n```\n\n#### List of events\n\nEach event documents its own argument signature.\n\n| Event | Description |\n| --- | --- |\n| [`after:run`](/llm/markdown/api/node-events/after-run-api.md) | Occurs after the run is finished. |\n| [`after:screenshot`](/llm/markdown/api/node-events/after-screenshot-api.md) | Occurs after a screenshot is taken. |\n| [`after:spec`](/llm/markdown/api/node-events/after-spec-api.md) | Occurs after a spec is finished running. |\n| [`before:browser:launch`](/llm/markdown/api/node-events/browser-launch-api.md) | Occurs immediately before launching a browser. |\n| [`before:run`](/llm/markdown/api/node-events/before-run-api.md) | Occurs before the run starts. |\n| [`before:spec`](/llm/markdown/api/node-events/before-spec-api.md) | Occurs when a spec is about to be run. |\n| [`file:preprocessor`](/llm/markdown/api/node-events/preprocessors-api.md) | Occurs when a spec or spec-related file needs to be transpiled for the browser. |\n| [`task`](/llm/markdown/api/commands/task.md) | Occurs in conjunction with the `cy.task` command. |\n\n### config\n\n`config` is the resolved [Cypress configuration](/llm/markdown/app/references/configuration.md) of the opened project.\n\nThis configuration contains all of the values that get passed into the browser for your project.\n\nSome plugins may utilize or require these values, so they can take certain actions based on the configuration. If these values are programmatically modified, Cypress will use the new values.\n\nThe `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.**\n\n*   `configFile`: The absolute path to the [Cypress configuration file](/llm/markdown/app/references/configuration.md). See the [\\--config-file](/llm/markdown/app/references/command-line.md#cypress-open) and [configFile](/llm/markdown/app/references/module-api.md) docs for more information on this value.\n*   `projectRoot`: The absolute path to the root of the project (e.g. `/Users/me/dev/my-project`)\n*   `version`: The version number of Cypress. This can be used to handle breaking changes.\n\n[Please check out our API docs for modifying configuration here.](/llm/markdown/api/node-events/configuration-api.md)\n",
      "section": "api",
      "anchors": [
        "setupnodeevents"
      ],
      "path": "/llm/json/chunked/api/node-events/overview.json",
      "token_estimate": 688
    },
    {
      "id": "api/node-events/overview#on",
      "doc_id": "api/node-events/overview",
      "heading": "on",
      "heading_level": 3,
      "content_markdown": "### on\n\n`on` is a function that you will use to register listeners on various **events** that Cypress exposes.\n\nRegistering to listen on an event looks like this:\n\n*   cypress.config.js\n*   cypress.config.ts\n\n```\nconst { defineConfig } = require('cypress')module.exports = defineConfig({  // setupNodeEvents can be defined in either  // the e2e or component configuration  e2e: {    setupNodeEvents(on, config) {      on('<event>', (arg1, arg2) => {        // plugin stuff here      })    },  },})\n```\n\n```\nimport { defineConfig } from 'cypress'export default defineConfig({  // setupNodeEvents can be defined in either  // the e2e or component configuration  e2e: {    setupNodeEvents(on, config) {      on('<event>', (arg1, arg2) => {        // plugin stuff here      })    },  },})\n```\n\n#### List of events\n\nEach event documents its own argument signature.\n\n| Event | Description |\n| --- | --- |\n| [`after:run`](/llm/markdown/api/node-events/after-run-api.md) | Occurs after the run is finished. |\n| [`after:screenshot`](/llm/markdown/api/node-events/after-screenshot-api.md) | Occurs after a screenshot is taken. |\n| [`after:spec`](/llm/markdown/api/node-events/after-spec-api.md) | Occurs after a spec is finished running. |\n| [`before:browser:launch`](/llm/markdown/api/node-events/browser-launch-api.md) | Occurs immediately before launching a browser. |\n| [`before:run`](/llm/markdown/api/node-events/before-run-api.md) | Occurs before the run starts. |\n| [`before:spec`](/llm/markdown/api/node-events/before-spec-api.md) | Occurs when a spec is about to be run. |\n| [`file:preprocessor`](/llm/markdown/api/node-events/preprocessors-api.md) | Occurs when a spec or spec-related file needs to be transpiled for the browser. |\n| [`task`](/llm/markdown/api/commands/task.md) | Occurs in conjunction with the `cy.task` command. |\n",
      "section": "api",
      "anchors": [
        "on"
      ],
      "path": "/llm/json/chunked/api/node-events/overview.json",
      "token_estimate": 300
    },
    {
      "id": "api/node-events/overview#list-of-events",
      "doc_id": "api/node-events/overview",
      "heading": "List of events",
      "heading_level": 4,
      "content_markdown": "#### List of events\n\nEach event documents its own argument signature.\n\n| Event | Description |\n| --- | --- |\n| [`after:run`](/llm/markdown/api/node-events/after-run-api.md) | Occurs after the run is finished. |\n| [`after:screenshot`](/llm/markdown/api/node-events/after-screenshot-api.md) | Occurs after a screenshot is taken. |\n| [`after:spec`](/llm/markdown/api/node-events/after-spec-api.md) | Occurs after a spec is finished running. |\n| [`before:browser:launch`](/llm/markdown/api/node-events/browser-launch-api.md) | Occurs immediately before launching a browser. |\n| [`before:run`](/llm/markdown/api/node-events/before-run-api.md) | Occurs before the run starts. |\n| [`before:spec`](/llm/markdown/api/node-events/before-spec-api.md) | Occurs when a spec is about to be run. |\n| [`file:preprocessor`](/llm/markdown/api/node-events/preprocessors-api.md) | Occurs when a spec or spec-related file needs to be transpiled for the browser. |\n| [`task`](/llm/markdown/api/commands/task.md) | Occurs in conjunction with the `cy.task` command. |\n",
      "section": "api",
      "anchors": [
        "list-of-events"
      ],
      "path": "/llm/json/chunked/api/node-events/overview.json",
      "token_estimate": 151
    },
    {
      "id": "api/node-events/overview#config",
      "doc_id": "api/node-events/overview",
      "heading": "config",
      "heading_level": 3,
      "content_markdown": "### config\n\n`config` is the resolved [Cypress configuration](/llm/markdown/app/references/configuration.md) of the opened project.\n\nThis configuration contains all of the values that get passed into the browser for your project.\n\nSome plugins may utilize or require these values, so they can take certain actions based on the configuration. If these values are programmatically modified, Cypress will use the new values.\n\nThe `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.**\n\n*   `configFile`: The absolute path to the [Cypress configuration file](/llm/markdown/app/references/configuration.md). See the [\\--config-file](/llm/markdown/app/references/command-line.md#cypress-open) and [configFile](/llm/markdown/app/references/module-api.md) docs for more information on this value.\n*   `projectRoot`: The absolute path to the root of the project (e.g. `/Users/me/dev/my-project`)\n*   `version`: The version number of Cypress. This can be used to handle breaking changes.\n\n[Please check out our API docs for modifying configuration here.](/llm/markdown/api/node-events/configuration-api.md)\n",
      "section": "api",
      "anchors": [
        "config"
      ],
      "path": "/llm/json/chunked/api/node-events/overview.json",
      "token_estimate": 197
    },
    {
      "id": "api/node-events/overview#use-cases",
      "doc_id": "api/node-events/overview",
      "heading": "Use Cases",
      "heading_level": 2,
      "content_markdown": "## Use Cases\n\n### Configuration\n\nHooking into node events allows you to programmatically alter the resolved configuration and environment variables that come from the [Cypress configuration file](/llm/markdown/app/references/configuration.md), [`cypress.env.json`](/llm/markdown/app/guides/environment-variables.md#2-cypressenvjson), the [command line](/llm/markdown/app/references/command-line.md), or system environment variables.\n\nThis enables you to do things like:\n\n*   Use multiple environments with their own configurations\n*   Swap out environment variables based on an environment\n*   Read in configuration files using the built in `fs` lib\n*   Change the list of browsers used for testing\n*   Write your configuration in `yml`\n\nCheck out our [Configuration API docs](/llm/markdown/api/node-events/configuration-api.md) which describe how to use this event.\n\n### Preprocessors\n\nThe event `file:preprocessor` is used to customize how your test code is transpiled and sent to the browser. By default, Cypress handles ES2015+, TypeScript, and CoffeeScript, using webpack to package it for the browser.\n\nYou can use the `file:preprocessor` event to do things like:\n\n*   Add the latest ES\\* support.\n*   Write your test code in ClojureScript.\n*   Customize the Babel settings to add your own plugins.\n*   Customize the options for compiling TypeScript.\n*   Swap out Webpack for Vite or anything else.\n\nCheck out our [File Preprocessor API docs](/llm/markdown/api/node-events/preprocessors-api.md) which describe how to use this event.\n\n### Run Lifecycle\n\nThe events [`before:run`](/llm/markdown/api/node-events/before-run-api.md) and [`after:run`](/llm/markdown/api/node-events/after-run-api.md) occur before and after a run, respectively.\n\nYou can use [`before:run`](/llm/markdown/api/node-events/before-run-api.md) to do things like:\n\n*   Set up reporting on a run\n*   Start a timer for the run to time how long it takes\n\nYou can use [`after:run`](/llm/markdown/api/node-events/after-run-api.md) to do things like:\n\n*   Finish up reporting on a run set up in `before:run`\n*   Stop the timer for the run set up in `before:run`\n\n### Spec Lifecycle\n\nThe events [`before:spec`](/llm/markdown/api/node-events/before-spec-api.md) and [`after:spec`](/llm/markdown/api/node-events/after-spec-api.md) run before and after a single spec is run, respectively.\n\nYou can use [`before:spec`](/llm/markdown/api/node-events/before-spec-api.md) to do things like:\n\n*   Set up reporting on a spec running\n*   Start a timer for the spec to time how long it takes\n\nYou can use [`after:spec`](/llm/markdown/api/node-events/after-spec-api.md) to do things like:\n\n*   Finish up reporting set up in `before:spec`\n*   Stop the timer for the spec set up in `before:spec`\n*   Delete the video recorded for the spec. This prevents it from taking time and computing resources for compressing and uploading the video. You can do this conditionally based on the results of the spec, such as if it passes (so videos for failing tests are preserved for debugging purposes).\n\nCheck out the [Before Spec API doc](/llm/markdown/api/node-events/before-spec-api.md) and [After Spec API doc](/llm/markdown/api/node-events/after-spec-api.md) which describe how to use these events.\n\n### Browser Launching\n\nThe event `before:browser:launch` can be used to modify the launch arguments for each particular browser.\n\nYou can use the `before:browser:launch` event to do things like:\n\n*   Load a Chrome extension\n*   Enable or disable experimental chrome features\n*   Control which Chrome components are loaded\n\nCheck out our [Browser Launch API docs](/llm/markdown/api/node-events/browser-launch-api.md) which describe how to use this event.\n\n### Screenshot handling\n\nThe event `after:screenshot` is called after a screenshot is taken and saved to disk.\n\nYou can use the `after:screenshot` event to do things like:\n\n*   Save details about the screenshot\n*   Rename the screenshot\n*   Manipulate the screenshot image by resizing or cropping it\n\nCheck out our [After Screenshot API docs](/llm/markdown/api/node-events/after-screenshot-api.md) which describe how to use this event.\n\n### cy.task\n\nThe event `task` is used in conjunction with the [`cy.task()`](/llm/markdown/api/commands/task.md) command. It allows you to write arbitrary code in Node to accomplish tasks that aren't possible in the browser.\n\nYou can use the `task` event to do things like:\n\n*   Manipulating a database (seeding, reading, writing, etc.)\n*   Storing state in Node that you want persisted (since the driver is fully refreshed on visits)\n*   Performing parallel tasks (like making multiple http requests outside of Cypress)\n*   Running an external process (like spinning up a Webdriver instance of another browser like Safari or puppeteer)\n",
      "section": "api",
      "anchors": [
        "use-cases"
      ],
      "path": "/llm/json/chunked/api/node-events/overview.json",
      "token_estimate": 841
    },
    {
      "id": "api/node-events/overview#configuration",
      "doc_id": "api/node-events/overview",
      "heading": "Configuration",
      "heading_level": 3,
      "content_markdown": "### Configuration\n\nHooking into node events allows you to programmatically alter the resolved configuration and environment variables that come from the [Cypress configuration file](/llm/markdown/app/references/configuration.md), [`cypress.env.json`](/llm/markdown/app/guides/environment-variables.md#2-cypressenvjson), the [command line](/llm/markdown/app/references/command-line.md), or system environment variables.\n\nThis enables you to do things like:\n\n*   Use multiple environments with their own configurations\n*   Swap out environment variables based on an environment\n*   Read in configuration files using the built in `fs` lib\n*   Change the list of browsers used for testing\n*   Write your configuration in `yml`\n\nCheck out our [Configuration API docs](/llm/markdown/api/node-events/configuration-api.md) which describe how to use this event.\n",
      "section": "api",
      "anchors": [
        "configuration"
      ],
      "path": "/llm/json/chunked/api/node-events/overview.json",
      "token_estimate": 127
    },
    {
      "id": "api/node-events/overview#preprocessors",
      "doc_id": "api/node-events/overview",
      "heading": "Preprocessors",
      "heading_level": 3,
      "content_markdown": "### Preprocessors\n\nThe event `file:preprocessor` is used to customize how your test code is transpiled and sent to the browser. By default, Cypress handles ES2015+, TypeScript, and CoffeeScript, using webpack to package it for the browser.\n\nYou can use the `file:preprocessor` event to do things like:\n\n*   Add the latest ES\\* support.\n*   Write your test code in ClojureScript.\n*   Customize the Babel settings to add your own plugins.\n*   Customize the options for compiling TypeScript.\n*   Swap out Webpack for Vite or anything else.\n\nCheck out our [File Preprocessor API docs](/llm/markdown/api/node-events/preprocessors-api.md) which describe how to use this event.\n",
      "section": "api",
      "anchors": [
        "preprocessors"
      ],
      "path": "/llm/json/chunked/api/node-events/overview.json",
      "token_estimate": 132
    },
    {
      "id": "api/node-events/overview#run-lifecycle",
      "doc_id": "api/node-events/overview",
      "heading": "Run Lifecycle",
      "heading_level": 3,
      "content_markdown": "### Run Lifecycle\n\nThe events [`before:run`](/llm/markdown/api/node-events/before-run-api.md) and [`after:run`](/llm/markdown/api/node-events/after-run-api.md) occur before and after a run, respectively.\n\nYou can use [`before:run`](/llm/markdown/api/node-events/before-run-api.md) to do things like:\n\n*   Set up reporting on a run\n*   Start a timer for the run to time how long it takes\n\nYou can use [`after:run`](/llm/markdown/api/node-events/after-run-api.md) to do things like:\n\n*   Finish up reporting on a run set up in `before:run`\n*   Stop the timer for the run set up in `before:run`\n",
      "section": "api",
      "anchors": [
        "run-lifecycle"
      ],
      "path": "/llm/json/chunked/api/node-events/overview.json",
      "token_estimate": 97
    },
    {
      "id": "api/node-events/overview#spec-lifecycle",
      "doc_id": "api/node-events/overview",
      "heading": "Spec Lifecycle",
      "heading_level": 3,
      "content_markdown": "### Spec Lifecycle\n\nThe events [`before:spec`](/llm/markdown/api/node-events/before-spec-api.md) and [`after:spec`](/llm/markdown/api/node-events/after-spec-api.md) run before and after a single spec is run, respectively.\n\nYou can use [`before:spec`](/llm/markdown/api/node-events/before-spec-api.md) to do things like:\n\n*   Set up reporting on a spec running\n*   Start a timer for the spec to time how long it takes\n\nYou can use [`after:spec`](/llm/markdown/api/node-events/after-spec-api.md) to do things like:\n\n*   Finish up reporting set up in `before:spec`\n*   Stop the timer for the spec set up in `before:spec`\n*   Delete the video recorded for the spec. This prevents it from taking time and computing resources for compressing and uploading the video. You can do this conditionally based on the results of the spec, such as if it passes (so videos for failing tests are preserved for debugging purposes).\n\nCheck out the [Before Spec API doc](/llm/markdown/api/node-events/before-spec-api.md) and [After Spec API doc](/llm/markdown/api/node-events/after-spec-api.md) which describe how to use these events.\n",
      "section": "api",
      "anchors": [
        "spec-lifecycle"
      ],
      "path": "/llm/json/chunked/api/node-events/overview.json",
      "token_estimate": 191
    },
    {
      "id": "api/node-events/overview#browser-launching",
      "doc_id": "api/node-events/overview",
      "heading": "Browser Launching",
      "heading_level": 3,
      "content_markdown": "### Browser Launching\n\nThe event `before:browser:launch` can be used to modify the launch arguments for each particular browser.\n\nYou can use the `before:browser:launch` event to do things like:\n\n*   Load a Chrome extension\n*   Enable or disable experimental chrome features\n*   Control which Chrome components are loaded\n\nCheck out our [Browser Launch API docs](/llm/markdown/api/node-events/browser-launch-api.md) which describe how to use this event.\n",
      "section": "api",
      "anchors": [
        "browser-launching"
      ],
      "path": "/llm/json/chunked/api/node-events/overview.json",
      "token_estimate": 81
    },
    {
      "id": "api/node-events/overview#screenshot-handling",
      "doc_id": "api/node-events/overview",
      "heading": "Screenshot handling",
      "heading_level": 3,
      "content_markdown": "### Screenshot handling\n\nThe event `after:screenshot` is called after a screenshot is taken and saved to disk.\n\nYou can use the `after:screenshot` event to do things like:\n\n*   Save details about the screenshot\n*   Rename the screenshot\n*   Manipulate the screenshot image by resizing or cropping it\n\nCheck out our [After Screenshot API docs](/llm/markdown/api/node-events/after-screenshot-api.md) which describe how to use this event.\n",
      "section": "api",
      "anchors": [
        "screenshot-handling"
      ],
      "path": "/llm/json/chunked/api/node-events/overview.json",
      "token_estimate": 81
    },
    {
      "id": "api/node-events/overview#cy-task",
      "doc_id": "api/node-events/overview",
      "heading": "cy.task",
      "heading_level": 3,
      "content_markdown": "### cy.task\n\nThe event `task` is used in conjunction with the [`cy.task()`](/llm/markdown/api/commands/task.md) command. It allows you to write arbitrary code in Node to accomplish tasks that aren't possible in the browser.\n\nYou can use the `task` event to do things like:\n\n*   Manipulating a database (seeding, reading, writing, etc.)\n*   Storing state in Node that you want persisted (since the driver is fully refreshed on visits)\n*   Performing parallel tasks (like making multiple http requests outside of Cypress)\n*   Running an external process (like spinning up a Webdriver instance of another browser like Safari or puppeteer)\n",
      "section": "api",
      "anchors": [
        "cy-task"
      ],
      "path": "/llm/json/chunked/api/node-events/overview.json",
      "token_estimate": 128
    },
    {
      "id": "api/node-events/overview#execution-context",
      "doc_id": "api/node-events/overview",
      "heading": "Execution context",
      "heading_level": 2,
      "content_markdown": "## Execution context\n\nThe [`setupNodeEvents`](/llm/markdown/app/references/configuration.md#setupNodeEvents) function is invoked when Cypress opens a project.\n\nCypress does this by spawning an independent `child_process` which then `requires` the [Cypress configuration file](/llm/markdown/app/references/configuration.md). This is similar to the way Visual Studio Code or Atom works.\n\nThis code will be executed using the Node version that launched Cypress.\n\n### npm modules\n\nWhen Cypress executes the [`setupNodeEvents`](/llm/markdown/app/references/configuration.md#setupNodeEvents) function 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, including local files inside your project.\n\nFor example, if your `package.json` looked like this:\n\n```\n{  \"name\": \"My Project\",  \"dependencies\": {    \"debug\": \"x.x.x\"  },  \"devDependencies\": {    \"lodash\": \"x.x.x\"  }}\n```\n\nThen you could do any of the following in your `setupNodeEvents` function:\n\n*   cypress.config.js\n*   cypress.config.ts\n\n```\nconst { defineConfig } = require('cypress')module.exports = defineConfig({  // setupNodeEvents can be defined in either  // the e2e or component configuration  e2e: {    setupNodeEvents(on, config) {      const _ = require('lodash') // yup, dev dependencies      const path = require('path') // yup, core node library      const debug = require('debug') // yup, dependencies      const User = require('./lib/models/user') // yup, relative local modules      console.log(__dirname) // /Users/janelane/Dev/my-project      console.log(process.cwd()) // /Users/janelane/Dev/my-project    },  },})\n```\n\n```\nimport { defineConfig } from 'cypress'export default defineConfig({  // setupNodeEvents can be defined in either  // the e2e or component configuration  e2e: {    setupNodeEvents(on, config) {      const _ = require('lodash') // yup, dev dependencies      const path = require('path') // yup, core node library      const debug = require('debug') // yup, dependencies      const User = require('./lib/models/user') // yup, relative local modules      console.log(__dirname) // /Users/janelane/Dev/my-project      console.log(process.cwd()) // /Users/janelane/Dev/my-project    },  },})\n```\n",
      "section": "api",
      "anchors": [
        "execution-context"
      ],
      "path": "/llm/json/chunked/api/node-events/overview.json",
      "token_estimate": 359
    },
    {
      "id": "api/node-events/overview#npm-modules",
      "doc_id": "api/node-events/overview",
      "heading": "npm modules",
      "heading_level": 3,
      "content_markdown": "### npm modules\n\nWhen Cypress executes the [`setupNodeEvents`](/llm/markdown/app/references/configuration.md#setupNodeEvents) function 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, including local files inside your project.\n\nFor example, if your `package.json` looked like this:\n\n```\n{  \"name\": \"My Project\",  \"dependencies\": {    \"debug\": \"x.x.x\"  },  \"devDependencies\": {    \"lodash\": \"x.x.x\"  }}\n```\n\nThen you could do any of the following in your `setupNodeEvents` function:\n\n*   cypress.config.js\n*   cypress.config.ts\n\n```\nconst { defineConfig } = require('cypress')module.exports = defineConfig({  // setupNodeEvents can be defined in either  // the e2e or component configuration  e2e: {    setupNodeEvents(on, config) {      const _ = require('lodash') // yup, dev dependencies      const path = require('path') // yup, core node library      const debug = require('debug') // yup, dependencies      const User = require('./lib/models/user') // yup, relative local modules      console.log(__dirname) // /Users/janelane/Dev/my-project      console.log(process.cwd()) // /Users/janelane/Dev/my-project    },  },})\n```\n\n```\nimport { defineConfig } from 'cypress'export default defineConfig({  // setupNodeEvents can be defined in either  // the e2e or component configuration  e2e: {    setupNodeEvents(on, config) {      const _ = require('lodash') // yup, dev dependencies      const path = require('path') // yup, core node library      const debug = require('debug') // yup, dependencies      const User = require('./lib/models/user') // yup, relative local modules      console.log(__dirname) // /Users/janelane/Dev/my-project      console.log(process.cwd()) // /Users/janelane/Dev/my-project    },  },})\n```\n",
      "section": "api",
      "anchors": [
        "npm-modules"
      ],
      "path": "/llm/json/chunked/api/node-events/overview.json",
      "token_estimate": 289
    },
    {
      "id": "api/node-events/overview#error-handling",
      "doc_id": "api/node-events/overview",
      "heading": "Error handling",
      "heading_level": 2,
      "content_markdown": "## Error handling\n\nThe [Cypress configuration file](/llm/markdown/app/references/configuration.md) is loaded 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.\n\nIf your [`setupNodeEvents`](/llm/markdown/app/references/configuration.md#setupNodeEvents) function has an uncaught exception, an unhandled rejection from a promise, or a syntax error - Cypress will automatically catch those and display them to you inside of the console and even in Cypress itself.\n\nErrors in your `setupNodeEvents` function _will not crash_ Cypress.\n",
      "section": "api",
      "anchors": [
        "error-handling"
      ],
      "path": "/llm/json/chunked/api/node-events/overview.json",
      "token_estimate": 117
    },
    {
      "id": "api/node-events/overview#file-changes",
      "doc_id": "api/node-events/overview",
      "heading": "File changes",
      "heading_level": 2,
      "content_markdown": "## File changes\n\nNormally when writing code in Node, you typically have to restart the process after changing any files.\n\nCypress automatically watches your [Cypress configuration file](/llm/markdown/app/references/configuration.md) and any changes made will take effect immediately. We will read the file in and execute the exported function again.\n\nThis enables you to iterate on plugin code even with Cypress already running.\n",
      "section": "api",
      "anchors": [
        "file-changes"
      ],
      "path": "/llm/json/chunked/api/node-events/overview.json",
      "token_estimate": 80
    },
    {
      "id": "api/node-events/overview#real-world-example",
      "doc_id": "api/node-events/overview",
      "heading": "Real World Example",
      "heading_level": 2,
      "content_markdown": "## Real World Example\n\nThe [Real World App (RWA)](https://github.com/cypress-io/cypress-realworld-app) uses [tasks](/llm/markdown/api/commands/task.md) to re-seed its database, and to filter/find test data for various testing scenarios.\n\n⚠️ This code is part of the [setupNodeEvents](/llm/markdown/app/plugins/plugins-guide.md#Using-a-plugin) function and thus executes in the Node environment. You cannot call `Cypress` or `cy` commands in this function, but you do have the direct access to the file system and the rest of the operating system.\n\n*   cypress.config.js\n*   cypress.config.ts\n\n```\nconst { defineConfig } = require('cypress')module.exports = defineConfig({  // setupNodeEvents can be defined in either  // the e2e or component configuration  e2e: {    setupNodeEvents(on, config) {      on('task', {        async 'db:seed'() {          // seed database with test data          const { data } = await axios.post(`${testDataApiEndpoint}/seed`)          return data        },        // fetch test data from a database (MySQL, PostgreSQL, etc...)        'filter:database'(queryPayload) {          return queryDatabase(queryPayload, (data, attrs) =>            _.filter(data.results, attrs)          )        },        'find:database'(queryPayload) {          return queryDatabase(queryPayload, (data, attrs) =>            _.find(data.results, attrs)          )        },      })    },  },})\n```\n\n```\nimport { defineConfig } from 'cypress'export default defineConfig({  // setupNodeEvents can be defined in either  // the e2e or component configuration  e2e: {    setupNodeEvents(on, config) {      on('task', {        async 'db:seed'() {          // seed database with test data          const { data } = await axios.post(`${testDataApiEndpoint}/seed`)          return data        },        // fetch test data from a database (MySQL, PostgreSQL, etc...)        'filter:database'(queryPayload) {          return queryDatabase(queryPayload, (data, attrs) =>            _.filter(data.results, attrs)          )        },        'find:database'(queryPayload) {          return queryDatabase(queryPayload, (data, attrs) =>            _.find(data.results, attrs)          )        },      })    },  },})\n```\n\n_Source: [Real World App > cypress.config.ts](https://github.com/cypress-io/cypress-realworld-app/blob/develop/cypress.config.ts)_\n\nCheck out the [Real World App test suites](https://github.com/cypress-io/cypress-realworld-app/tree/develop/cypress/tests/ui) to see these tasks in action.\n",
      "section": "api",
      "anchors": [
        "real-world-example"
      ],
      "path": "/llm/json/chunked/api/node-events/overview.json",
      "token_estimate": 347
    }
  ]
}