Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 7 additions & 9 deletions source/api/plugins/writing-a-plugin.md
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ You can programmatically modify these values and Cypress will then respect these

## List of events

***The following events are available:***
### The following events are available:

Event | Description
--- | ---
Expand All @@ -90,16 +90,14 @@ Cypress does this by spawning an independent `child_process` which then `require

You will need to keep in mind it is **Cypress who is requiring your file** - not your local project, not your local Node version, and not anything else under your control.

Because of this, this global context and the version of Node is controlled by Cypress.
Because of this, this global context and the version of Node is controlled under Cypress.

{% note warning "Node version" %}
Keep in mind - code executed in plugins **may** be executed by the Node version that comes bundled in Cypress itself.

Keep in mind - code executed in plugins is executed **by the Node version** that comes bundled in Cypress itself.

This version of Node has **nothing to do** with your locally installed versions. Therefore you have to write Node code which is compatible with this version.

You can find the current Node version we use {% url 'here' https://github.com/cypress-io/cypress/blob/master/.node-version %}.
This version of Node has **nothing to do** with your locally installed versions. Therefore you may want to write Node code which is compatible with this version or document that the user of your plugin will need to set a specific {% url "`nodeVersion`" configuration#Node-version %} in their configuration.

You can find the current Node version we use when the `nodeVersion` is set to the default `bundled` {% url 'here' https://github.com/cypress-io/cypress/blob/master/.node-version %}.
{% endnote %}

## npm modules
Expand Down Expand Up @@ -139,9 +137,9 @@ 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' own execution in any way.
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, a syntax error, or anything else - we will automatically catch those and display them to you inside of the console and even in the Test Runner itself.
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.

Expand Down
3 changes: 1 addition & 2 deletions source/faq/questions/using-cypress-faq.md
Original file line number Diff line number Diff line change
Expand Up @@ -143,7 +143,6 @@ We have seen many different iterations of this question. The answers can be vari

When you load your application using `cy.visit()`, Cypress will wait for the `load` event to fire. It is really this easy. The {% url '`cy.visit()`' visit#Usage %} command loads a remote page and does not resolve until all of the external resources complete their loading phase. Because we expect your applications to observe differing load times, this command's default timeout is set to 60000ms. If you visit an invalid url or a {% url 'second unique domain' web-security#One-Superdomain-per-Test %}, Cypress will log a verbose yet friendly error message.


**_In CI, how do I make sure my server has started?_**

We recommend these great modules for this use case:
Expand Down Expand Up @@ -466,7 +465,7 @@ The code you write in Cypress is executed in the browser, so you can import or r

You can `require` or `import` them as you're accustomed to. We preprocess your spec files with `babel` and `browserify`.

Cypress does not have direct access to Node or your file system. We recommend utilizing one of the following to execute code outside of the browser:
We recommend utilizing one of the following to execute code outside of the browser. Furthermore, you can use your own Node version during code excecution by setting the {% url "`nodeVersion`" configuration#Node-version %} in your configuration.

- {% url `cy.task()` task %} to run code in Node via the {% url "`pluginsFile`" configuration#Folders-Files %}
- {% url `cy.exec()` exec %} to execute a shell command
Expand Down
10 changes: 10 additions & 0 deletions source/guides/references/configuration.md
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,12 @@ Option | Default | Description
`animationDistanceThreshold` | `5` | The distance in pixels an element must exceed over time to be considered animating
`waitForAnimations` | `true` | Whether to wait for elements to finish animating before executing commands

## Node version

Option | Default | Description
----- | ---- | ----
`nodeVersion` | `bundled` | If set to `system`, Cypress will try to find a Node executable on your path to use when executing your {% url plugins plugins-guide %}. Otherwise, Cypress will use the Node version bundled with Cypress.

# Overriding Options

Cypress gives you the option to dynamically alter configuration values. This is helpful when running Cypress in multiple environments and on multiple developer machines.
Expand Down Expand Up @@ -249,3 +255,7 @@ You can turn this option off if the application or site you're testing **does no
## Intelligent Code Completion

IntelliSense is available for Cypress while editing your configuration file. {% url "Learn how to set up Intelligent Code Completion." intelligent-code-completion %}

{% history %}
{% url "3.5.0" changelog %} | Added support for option `nodeVersion`
{% endhistory %}
7 changes: 3 additions & 4 deletions source/guides/tooling/plugins-guide.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,9 @@ Plugins enable you to tap into, modify, or extend the internal behavior of Cypre

Normally, as a user, all of your test code, your application, and Cypress commands are executed in the browser. But Cypress is also a Node process that plugins can use.

> Plugins enable you to tap into the `node` process running outside of the browser.
> Plugins enable you to tap into the Node process running outside of the browser.

Plugins are a "seam" for you to write your own custom code that executes during particular stages of the Cypress lifecycle.
Plugins are a "seam" for you to write your own custom code that executes during particular stages of the Cypress lifecycle. It also allows you to execute code within your own Node version when the {% url "`nodeVersion`" configuration#Node-version %} is set in your configuration.

{% note info "This is a brief overview" %}
If you want more details about how to write a plugin, we've written API docs that show you how to work with each plugin event.
Expand Down Expand Up @@ -52,7 +52,6 @@ The event `before:browser:launch` can be used to modify the launch arguments for
You can use the `before:browser:launch` event to do things like:

- Load a Chrome extension
- Change print media
- Enable or disable experimental chrome features
- Control which Chrome components are loaded

Expand All @@ -72,7 +71,7 @@ Check out our {% url 'After Screenshot API docs' after-screenshot-api %} which d

## cy.task

The event `task` is used in conjunction with the {% url `cy.task()` task %} command. It allows you to write arbitrary code in Node to accomplish tasks that aren't possible in the browser.
The event `task` is used in conjunction with the {% url `cy.task()` task %} command. It allows you to write arbitrary code in Node to accomplish tasks that aren't possible in the browser. It also allows you to execute code within your own Node version when the {% url "`nodeVersion`" configuration#Node-version %} is set in your configuration.

You can use the `task` event to do things like:

Expand Down
152 changes: 152 additions & 0 deletions source/zh-cn/api/plugins/writing-a-plugin.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,152 @@
---
title: Writing a Plugin
---

The Plugins API allows you to hook into and extend Cypress behavior.

{% note info %}
**Note:** This document assumes you have read the {% url 'Plugins Guide' plugins-guide %}.
{% endnote %}

# Plugins API

To get started, open up this file:

```text
cypress/plugins/index.js
```

The plugins file must export a function with the following signature:

```javascript
// cypress/plugins/index.js

// export a function
module.exports = (on, config) => {
// configure plugins here
}
```

The exported function is called whenever a project is opened either with {% url "`cypress open`" command-line#cypress-open %} or {% url "`cypress run`" command-line#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:

```javascript
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 {% urlHash 'refer to the docs for each one' 'List-of-events' %}.

## config

`config` is the resolved {% url "Cypress configuration" configuration %} of the opened project.

This configuration contains all of the values that get passed into the browser for your project.

{% url 'For a comprehensive list of all configuration values look here.' https://github.com/cypress-io/cypress/blob/master/packages/server/lib/config.coffee %}

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.

{% url "Please check out our API docs for modifying configuration here." configuration-api %}

## List of events

### The following events are available:

Event | Description
--- | ---
{% url `file:preprocessor` preprocessors-api %} | Occurs when a spec or spec-related file needs to be transpiled for the browser.
{% url `before:browser:launch` browser-launch-api %} | Occurs immediately before launching a browser.
{% url `task` task %} | Occurs in conjunction with the `cy.task` command.
{% url `after:screenshot` after-screenshot-api %} | Occurs after a screenshot is taken.

{% note warning "More Coming Soon" %}
The Plugins API is relatively new.

We have many new plugin events {% issue 684 'we are adding' %}.
{% endnote %}

# 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.

You will need to keep in mind it is **Cypress who is requiring your file** - not your local project, not your local Node version, and not anything else under your control.

Because of this, this global context and the version of Node is controlled under Cypress.

{% note warning "Node version" %}
Keep in mind - code executed in plugins **may** be executed by the Node version that comes bundled in Cypress itself.

This version of Node has **nothing to do** with your locally installed versions. Therefore you may want to write Node code which is compatible with this version or document that the user of your plugin will need to set a specific {% url "`nodeVersion`" configuration#Node-version %} in their configuration.

You can find the current Node version we use when the `nodeVersion` is set to the default `bundled` {% url 'here' https://github.com/cypress-io/cypress/blob/master/.node-version %}.
{% endnote %}

## 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:**

```json
{
"name": "My Project",
"dependencies": {
"debug": "x.x.x"
},
"devDependencies": {
"lodash": "x.x.x"
}
}
```

**Then you could do any of the following in your `pluginsFile`:**

```js
// 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.
6 changes: 6 additions & 0 deletions source/zh-cn/guides/references/configuration.md
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,12 @@ Cypress的默认行为可以通过提供以下任何配置选项来修改。下
`animationDistanceThreshold` | `5` | 元素的距离(以像素为单位)必须超过一定的时间才能被认为是动画
`waitForAnimations` | `true` | 是否在执行命令之前等待元素结束动画

## Node 版

选项 | 默认值 | 描述
----- | ---- | ----
`nodeVersion` | `bundled` | 如果设置为`system`,赛普拉斯将尝试在您的路径上找到 Node 可执行文件,以便在执行{% url plugins plugins-guide %}时使用。 否则,赛普拉斯将使用与赛普拉斯捆绑的Node版本。

# 重写选项

Cypress提供了动态更改配置值的选项。这对于在多个环境和多个开发人员机器上运行Cypress非常有用。
Expand Down
5 changes: 3 additions & 2 deletions source/zh-cn/guides/tooling/plugins-guide.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ title: 插件

> 插件能够使你在浏览器外部运行`node`进程。

插件是一个"接缝"你可以编写自己的自定义代码,该代码在Cypress生命周期的特定阶段执行。
插件是一个"接缝"你可以编写自己的自定义代码,该代码在Cypress生命周期的特定阶段执行。 It also allows you to execute code within your own Node version when the {% url "`nodeVersion`" configuration#Node-version %} is set in your configuration.

{% note info "这是一个简短的概述" %}
如果你想了解更多一些关于如何编写插件,我们已经编写了API文档,向你展示如何处理每个插件事件。
Expand Down Expand Up @@ -72,7 +72,8 @@ title: 插件

## cy.task

事件`task`是与{% url `cy.task()` task %}命令一起使用。 它允许你在node中编写任意代码,以完成浏览器中不可能完成的任务。
事件`task`是与{% url `cy.task()` task %}命令一起使用。 它允许你在node中编写任意代码,以完成浏览器中不可能完成的任务。 It also allows you to execute code within your own Node version when the {% url "`nodeVersion`" configuration#Node-version %} is set in your configuration.


你可以使用`task`事件执行以下操作:

Expand Down