Skip to content

Commit

Permalink
feat: Initial plugin (#1)
Browse files Browse the repository at this point in the history
Initial implementation with tests and permissions for Chrome, Edge, and Firefox
  • Loading branch information
kamranayub committed Jul 17, 2020
1 parent 882fa19 commit 16f8513
Show file tree
Hide file tree
Showing 28 changed files with 1,142 additions and 62 deletions.
17 changes: 17 additions & 0 deletions .github/workflows/publish.yml
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,23 @@ jobs:
- run: yarn lint
- run: yarn test

build-and-publish-docs:
needs: lint-and-test
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v1
with:
fetch-depth: 1
- uses: actions/setup-node@v1
with:
node-version: 12
registry-url: https://registry.npmjs.org/
- run: yarn
- run: yarn docs
- run: npx gh-pages -d docs
env:
GH_TOKEN: ${{secrets.GH_TOKEN}}

# Uncomment if you want to publish to GitHub Package Repository
#
# build-and-publish-gpr:
Expand Down
69 changes: 66 additions & 3 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
name: Node.js Package Lint And Test
name: Tests

on:
push:
Expand All @@ -11,11 +11,11 @@ on:

jobs:
lint-and-test:
name: Test on node 12 and ubuntu-latest
name: Node 12
runs-on: ubuntu-latest

steps:
- uses: actions/checkout@v1
- uses: actions/checkout@v2
with:
fetch-depth: 1
- uses: actions/setup-node@v1
Expand All @@ -25,3 +25,66 @@ jobs:
- run: yarn lint
- run: yarn build
- run: yarn test

chrome:
name: Chrome
runs-on: ubuntu-16.04
steps:
- uses: actions/checkout@v2
- uses: cypress-io/github-action@v1
with:
browser: chrome
build: yarn build
- uses: actions/upload-artifact@v1
if: failure()
with:
name: cypress-screenshots
path: cypress/screenshots
- uses: actions/upload-artifact@v1
if: always()
with:
name: cypress-videos
path: cypress/videos

edge:
name: Edge
runs-on: windows-latest
steps:
- uses: actions/checkout@v2
- uses: cypress-io/github-action@v2
with:
browser: edge
build: yarn build
- uses: actions/upload-artifact@v1
if: failure()
with:
name: cypress-screenshots
path: cypress/screenshots
- uses: actions/upload-artifact@v1
if: always()
with:
name: cypress-videos
path: cypress/videos

firefox:
name: Firefox
runs-on: ubuntu-16.04
container:
image: cypress/browsers:node12.14.1-chrome83-ff77
options: --user 1001
steps:
- uses: actions/checkout@v2
- uses: cypress-io/github-action@v2
with:
browser: firefox
build: yarn build
- uses: actions/upload-artifact@v1
if: failure()
with:
name: cypress-screenshots
path: cypress/screenshots
- uses: actions/upload-artifact@v1
if: always()
with:
name: cypress-videos
path: cypress/videos
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,9 @@ typings/
# npm build output
/dist

# typedoc build output
/docs

.sonarlint/

.idea/
18 changes: 18 additions & 0 deletions .vscode/launch.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
{
// Use IntelliSense to learn about possible attributes.
// Hover to view descriptions of existing attributes.
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
"version": "0.2.0",
"configurations": [
{
"type": "node",
"request": "launch",
"name": "Debug Jest Tests",
"skipFiles": ["<node_internals>/**"],
"program": "${workspaceRoot}\\node_modules\\jest\\bin\\jest.js",
"args": ["-i"],
"internalConsoleOptions": "openOnSessionStart",
"outFiles": ["${workspaceFolder}/dist/**/*.js"]
}
]
}
211 changes: 193 additions & 18 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,13 @@
![GitHub last commit](https://img.shields.io/github/last-commit/kamranayub/cypress-browser-permissions.svg)
![npm collaborators](https://img.shields.io/npm/collaborators/cypress-browser-permissions.svg)

A Cypress plugin to manage browser launch permissions for various APIs such as Notifications, Geolocation, Cookies, and more.
A Cypress plugin to manage browser launch permissions for various APIs such as Notifications, Geolocation, Cookies, Images, and more.

![Example of enabling permissions](https://user-images.githubusercontent.com/563819/87628826-63b13100-c6f7-11ea-956a-ca84a137d464.png)

These APIs can be controlled using browser profile preferences which this plugin will generate and pass for you, as well as resetting them for each test run (otherwise they will be persisted).

This enables you to effectively test permissions-based APIs in continuous integration environments and in headed browsers _without prompts._ :tada:

## Usage

Expand All @@ -33,46 +39,215 @@ yarn install cypress-browser-permissions --save-dev

In `cypress/plugins/index.js`:

**CommonJS**

```js
const initializeBrowserPermissionsPlugin = require('cypress-browser-permissions/plugin');
const { cypressBrowserPermissionsPlugin } = require('cypress-browser-permissions')

module.exports = (on, config) => {
initializeBrowserPermissionsPlugin(on, config);
};
```
// The plugin may modify the Cypress config, so be sure
// to return it
config = cypressBrowserPermissionsPlugin(on, config)

#### Set your desired permissions
//
// Any existing plugins you are using
//

Setting permissions should work in Chrome, Edge (Chromium), and Firefox. They won't take effect in Electron or other browsers.
return config
}
```

In `cypress.json` or `cypress.env.json`, you can use Cypress environment variables to control permissions:
**ES2015**

```js
import { cypressBrowserPermissionsPlugin } from 'cypress-browser-permissions'

module.exports = (on, config) => {
// The plugin may modify the Cypress config, so be sure
// to return it
config = cypressBrowserPermissionsPlugin(on, config)

//
// Any existing plugins you are using
//

return config
}
```

## Setting Permissions

Setting permissions should work in Chromium (Google Chrome, Microsoft Edge Chromium) and Firefox. They won't take effect in other browser families.

Permissions cam be set using [Cypress environment variables](https://docs.cypress.io/guides/guides/environment-variables.html). The plugin reads permissions from `Cypress.env.browserPermissions` and supports all the existing ways to set Cypress environment variables.

### In `cypress.json`

In `cypress.json`, set the `env.browserPermissions` property with a map of permissions:

```json
{
"env": {
"plugin_permissions_notifications": "allow",
"plugin_permissions_geolocation": "block",
"plugin_permissions_images": "ask",
"env": {
"browserPermissions": {
"notifications": "allow",
"geolocation": "allow",
"camera": "block",
"microphone": "block",
"images": "allow",
"javascript": "allow",
"popups": "ask",
"plugins": "ask",
"cookies": "allow"
}
}
}
```

Values can be any of the following:
### In `cypress.env.json`

In `cypress.env.json`, it follows the same convention:

```json
{
"browserPermissions": {
"notifications": "allow",
"geolocation": "allow",
"camera": "block",
"microphone": "block",
"images": "allow",
"javascript": "allow",
"popups": "ask",
"plugins": "ask",
"cookies": "allow"
}
}
```

### Via `cypress open` or `cypress run`

Since the configuration is nested, you must pass in the permissions as a stringified JSON object:

```bash
$ cypress run --env '{\"browserPermissions\": {\"notifications\": 1}}'
$ cypress open --env '{\"browserPermissions\": {\"notifications\": 1}}'
```

### Via machine environment variables

By default, Cypress cannot handle nested variable objects but this plugin will correctly find environment variables that match what it expects and will translate them properly for you automatically:

```bash
CYPRESS_browser_permissions_notifications=allow cypress run
```

> **Remember:** When passing Cypress env vars from the outside, such as from a script, prefix them with `CYPRESS_` e.g. `CYPRESS_browser_permissions_notifications=allow`. Cypress automatically strips the prefix when passing to `Cypress.env`
### Supported Permissions

These are the supported permission names of the plugin:

#### Chrome / Edge (Chromium)

- `notifications`
- `geolocation`
- `camera`
- `microphone`
- `images`
- `popups`
- `javascript`
- `cookies`
- `plugins`

#### Firefox

- `notifications`
- `geolocation`
- `camera`
- `microphone`
- `images`

### Supported Values

Values for a permission can be any of the following:

- `0` or `ask` - The default permission, which is to prompt the user
- `1` or `allow` - Allow the permission
- `2` or `block` - Block the permission

## Supported Permissions
## API

### Chrome
In your Cypress test suites, you can import permissions helpers from the the package.

- `notifications`
- `geolocation`
### Usage Example

**my-test.spec.js**

```js
import { isPermissionAllowed, isPermissionBlocked, isPermissionAsk } from 'cypress-browser-permissions'

describe('my site', () => {
before(() => cy.visit('/'))

isPermissionAllowed('notifications') &&
it('should show desktop notification', () => {
/* ... */
})

isPermissionBlocked('notifications') &&
it('should warn user desktop notifications are disabled', () => {
/* ... */
})

isPermissionAsk('notifications') &&
it('should prompt user to allow desktop notifications', () => {
/* ... */
})
})
```

Also see [cypress/integration/](cypress/integration) folder for e2e examples.

### Docs

See [API docs](https://kamranicus.com/cypress-browser-permissions)

## Resetting Permissions

This plugin automatically resets each supported permission to the browser default for each test run since otherwise profile preferences are persisted across sessions, which may not be what you intend.

## Details

### How It Works

Cypress can pass [preferences](https://docs.cypress.io/api/plugins/browser-launch-api.html#Modify-browser-launch-arguments-preferences-and-extensions) when launching browsers. This plugin adds a small abstraction over this low-level API to take care of setting the permission-related preferences in different browsers, mostly Chrome/Chromium and Firefox.

You can listen to the `before:browser:launch` event in your own Cypress application to add any additional preferences.

### Chrome / Edge / Chromium Preferences

Documented in [pref_names](https://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/pref_names.cc?view=markup), the permission-related preferences are grouped under `profile.managed_default_content_settings`.

These modify the "managed" settings, such as when group policy is enforced. In the Chrome settings, there _is_ a way to add specific sites to allow / block lists, and this may be possible to do with the plugin if that is stored in the profile data structure.

### Firefox

In `about:config` within Firefox, search for `permissions.default` to list permissions.

Notably, Firefox does not have some permissions related to JavaScript, Cookies, Plugins, and Popups but those may be managed with other settings.

## Credits

Thanks to BrowserStack for [documenting some of these permissions](https://www.browserstack.com/automate/handle-popups-alerts-prompts-in-automated-tests) as well as these StackOverflow posts:

- [Selenium + Python Allow Firefox Notifications](https://stackoverflow.com/questions/55435198/selenium-python-allow-firefox-notifications)
- [How to allow or deny notification geo-location microphone camera pop up](https://stackoverflow.com/questions/48007699/how-to-allow-or-deny-notification-geo-location-microphone-camera-pop-up)

In Web Driver testing, these are passed under capabilities, such as [shown in the test-runner configuration](https://webdriver.io/docs/configurationfile.html) and then passing as [shown here](https://stackoverflow.com/a/47654122/109458).

## MIT License

See [LICENSE](LICENSE)
See [LICENSE](LICENSE)

```
```

0 comments on commit 16f8513

Please sign in to comment.