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

before:browser:launch api changes #2458

Merged
merged 9 commits into from
Feb 5, 2020
1 change: 1 addition & 0 deletions source/_changelogs/4.0.0.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ Cypress 4.0.0 includes support for {% url "Mozilla Firefox" https://www.mozilla.
- Due to upgrading Mocha, invoking a `done` callback and returning a promise in a test now results in an error. Addresses {% issue 2528 %}.
- Chai has been upgraded which includes a number of breaking changes and new features. Addresses {% issue 2529 %}.
- Sinon.JS has been upgraded which includes a number of breaking changes and new features. Addresses {% issue 2866 %}.
- During `before:browser:launch`, we no longer yield the second argument as an array of browser arguments and instead yield an `options` object with an `args` property in order to support more advanced browser launch options. Addresses {% issue 6306 %}.
- We updated the {% url "Cypress browser objects" browser-launch-api %} of all Chromium-based browsers, including Electron, to have `chromium` set as their `family` field. Addresses {% issue 6243 %}.
- The {% url "`--browser` flag" command-line#cypress-run-browser-lt-browser-name-or-path-gt %} no longer accepts a release candidate browser as its sole argument. You can now specify a specific release channel of a browser by prepending it with the browser name. Addresses {% issue 6243 %}.
- {% url "`cy.writeFile()`" writefile %} now yields `null` instead of the contents written to the file in order to more align with the behavior of `fs`. Addresses {% issue 2466 %}.
Expand Down
138 changes: 100 additions & 38 deletions source/api/plugins/browser-launch-api.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,63 +2,119 @@
title: Browser Launch API
---

Before Cypress launches a browser, it gives you the ability to modify the arguments used to launch it.
Before Cypress launches a browser, it gives you the opportunity to modify the browser preferences, install extensions, add and remove command-line arguments, and modify other options.

This is helpful to modify, remove, or add your own arguments.
# Syntax

```js
on('before:browser:launch', (browser = {}, launchOptions) => { /* ... */ })
```

**{% fa fa-angle-right %} browser** ***(object)***

An object describing the browser being launched, with the following properties:

Property | Type | Description
--- | --- | ---
`name`| `string` | Machine-friendly name, like `chrome`, `electron`, or `firefox`.
`family` | `string` | Rendering engine being used. `chromium` or `firefox`.
`channel` | `string` | Release channel of the browser, such as `stable`, `dev`, or `canary`.
`displayName` | `string` | Human-readable display name for the browser.
`version` | `string` | Full version string.
`path` | `string` | Path to the browser on disk. Blank for Electron.
`majorVersion` | `number` | The major version number of the browser.


**{% fa fa-angle-right %} launchOptions** ***(object)***

Options that can be modified to control how the browser is launched, with the following properties:

Property | Type | Description
--- | --- | ---
`preferences` | `object` | An object describing browser preferences. Differs between browsers. See {% url "\"Changing browser preferences\"" #Changing-browser-preferences %} for details.
`args` | `string[]` | An array of strings that will be passed as command-line args when the browser is launched. Has no effect on Electron. See {% url "\"Modify browser launch arguments\"" #Modify-browser-launch-arguments %} for details.
`extensions` | `string[]` | An array of paths to folders containing unpacked WebExtensions, to be loaded before the browser starts. Note: Electron currently only supports Chrome DevTools extensions. See {% url "\"Add browser extensions\"" #Add-browser-extensions %} for details.
`windowSize` | `string` | By default, browsers will open `maximized`. You can make a browser open in fullscreen mode by passing `fullscreen` here.

The most common use case is adding your own web extension - {% url "example recipe" https://www.cypress.io/blog/2020/01/07/how-to-load-the-react-devtools-extension-in-cypress/ %}.

# Usage

## Modify args based on browser
## Modify browser launch arguments, preferences, and extensions

Using your {% url "`pluginsFile`" plugins-guide %} you can tap into the `before:browser:launch` event and modify how Cypress launches the browser (e.g. modify arguments, user preferences, and extensions).

This event will yield you the `browser` object, which gives you information about the browser, and the `launchOptions` object, which allows you to modify how the browser is launched.

The returned `launchOptions` object will become the new launch options for the browser.

Using your {% url "`pluginsFile`" plugins-guide %} you can tap into the `before:browser:launch` event and modify the arguments based on the browser that Cypress is launching.
### Modify browser launch arguments:

```js
module.exports = (on, config) => {
on('before:browser:launch', (browser = {}, launchOptions) => {
if (browser.family === 'chromium' && browser.name !== 'electron') {
// `args` is an array of all the arguments that will
// be passed to Chromium-based browsers when it launchers
launchOptions.args.push('--start-fullscreen')

This event will yield you the `browser` as an object, and `args` which are the default arguments used to launch the browser.
// whatever you return here becomes the launchOptions
return launchOptions
}

`args` may be an array or an object (based on the type of browser we're launching). Whatever you return from this event will become the new args for launching the browser.
if (browser.family === 'firefox') {
launchOptions.args.push('-some-cli-argument')

Here are options for the currently supported browsers:
return launchOptions
}
})
}
```

* {% url 'Chrome, Chromium, Canary, or Microsoft Edge (Chromium based) browsers' "https://peter.sh/experiments/chromium-command-line-switches/" %}
* {% url 'Firefox' "http://kb.mozillazine.org/About:config_entries" %}
* {% url 'Electron' "https://github.com/electron/electron/blob/master/docs/api/browser-window.md#new-browserwindowoptions" %}
### Add browser extensions:

```js
module.exports = (on, config) => {
on('before:browser:launch', (browser = {}, args) => {
// browser will look something like this
// {
// name: 'chrome',
// family: 'chromium',
// channel: 'stable',
// displayName: 'Chrome',
// version: '63.0.3239.108',
// path: '/Applications/Google Chrome.app/Contents/MacOS/Google Chrome',
// majorVersion: '63'
// }
on('browser:before:launch', (browser, launchOptions) => {
// supply the path to an unpacked WebExtension
// NOTE: extensions cannot be loaded in headless Chrome
launchOptions.extensions.push('/path/to/webextension')

return launchOptions
})
}
```

### Changing browser preferences:

```js
module.exports = (on, config) => {
on('browser:before:launch', (browser, launchOptions) => {
if (browser.family === 'chromium' && browser.name !== 'electron') {
flotwig marked this conversation as resolved.
Show resolved Hide resolved
// `args` is an array of all the arguments
// that will be passed to Chrome when it launchers
args.push('--start-fullscreen')
// in Chromium, preferences can exist in Local State, Preferences, or Secure Preferences
// via launchOptions.preferences, these can be acccssed as `localState`, `default`, and `secureDefault`

// whatever you return here becomes the new args
return args
// for example, to set `somePreference: true` in Preferences:
launchOptions.preferences.default.somePreference = true

// more information about Chromium preferences can be found here:
// https://www.chromium.org/developers/design-documents/preferences

return launchOptions
}

if (browser.family === 'firefox') {
args.extensions.push('/path/to/my/extension')
args.preferences['browser.blink_allowed'] = true
// launchOptions.preferences is a map of preference names to values
launchOptions.preferences['browser.startup.homepage'] = 'https://cypress.io'

return launchOptions
}

if (browser.name === 'electron') {
// `args` is a `BrowserWindow` options object
// launchOptions.preferences is a `BrowserWindow` `options` object:
// https://electronjs.org/docs/api/browser-window#new-browserwindowoptions
args['fullscreen'] = true
launchOptions.preferences.darkTheme = true

// whatever you return here becomes the new args
return args
return launchOptions
}
})
}
Expand Down Expand Up @@ -86,7 +142,7 @@ Cypress already sets some the Electron command line switches internally. See fil

## See all Chrome browser switches

If you are running Cypress tests using Chrome browser, you can see ALL currently set command line switches and the browser version information by opening a new tab and typing `chrome://version` url.
If you are running Cypress tests using a Chromium-based browser, you can see ALL currently set command line switches and the browser version information by opening a new tab and typing `chrome://version` url.

{% imgTag /img/api/chrome-switches.png "See all Chrome switches" %}

Expand All @@ -102,16 +158,22 @@ You can however send your own video file for testing by passing a Chrome command

```js
module.exports = (on, config) => {
on('before:browser:launch', (browser = {}, args) => {
on('before:browser:launch', (browser = {}, launchOptions) => {
if (browser.family === 'chromium' && browser.name !== 'electron') {
// Mac/Linux
args.push('--use-file-for-fake-video-capture=cypress/fixtures/my-video.y4m')
launchOptions.args.push('--use-file-for-fake-video-capture=cypress/fixtures/my-video.y4m')

// Windows
// args.push('--use-file-for-fake-video-capture=c:\\path\\to\\video\\my-video.y4m')
// launchOptions.args.push('--use-file-for-fake-video-capture=c:\\path\\to\\video\\my-video.y4m')
}

return args
return launchOptions
})
}
```

{% history %}
{% url "4.0.0" changelog#4-0-0 %} | New `options` object replaces old `args` as second argument to `before:browser:launch`
{% url "4.0.0" changelog#4-0-0 %} | All Chromium-based browsers, including Electron, have `chromium` set as their `family` property.
{% url "4.0.0" changelog#4-0-0 %} | Added `channel` property to browser.
{% endhistory %}
46 changes: 46 additions & 0 deletions source/guides/references/migration-guide.md
Original file line number Diff line number Diff line change
Expand Up @@ -169,6 +169,52 @@ spy.resetHistory()
stub.resetHistory()
```

## Plugin Event `before:browser:launch`

Since we now support more advanced browser launch options, during `before:browser:launch` we no longer yield the second argument as an array of browser arguments and instead yield an `options` object with an `args` property.

You can see more examples of the new `options` in use in the {% url "Browser Launch API doc" browser-launch-api %}.

{% badge danger Before %} The second argument is no longer an array.

```js
on('browser:before:launch', (browser, args) => {
// will print a deprecation warning telling you
// to change your code to the new signature
args.push('--another-arg')
jennifer-shehane marked this conversation as resolved.
Show resolved Hide resolved
})
```

{% badge success After %} Access the `args` property off `options`

```js
on('browser:before:launch', (browser, options) => {
options.args.push('--another-arg')
})
```

## Electron options in `before:browser:launch`

Previously, you could pass options to the launched Electron {% url "BrowserWindow" https://www.electronjs.org/docs/api/browser-window#new-browserwindowoptions %} in `before:browser:launch` by modifying the `options` object.

Now, you must pass those options as `options.preferences`:

{% badge danger Before %} Passing BrowserWindow options on the `options` object is no longer supported.

```js
on('browser:before:launch', (browser, options) => {
options.darkTheme = true
})
```

{% badge success After %} Pass BrowserWindow options on the `options.preferences` object instead.

```js
on('browser:before:launch', (browser, options) => {
options.preferences.darkTheme = true
})
```

## Chromium-based browser `family`

We updated the {% url "Cypress browser objects" browser-launch-api %} of all Chromium-based browsers, including Electron, to have `chromium` set as their `family` field.
Expand Down