DEV Community

Cover image for Controlling Browser Permissions in Cypress End-to-End Tests
Kamran Ayub
Kamran Ayub

Posted on • Originally published at kamranicus.com

Controlling Browser Permissions in Cypress End-to-End Tests

I am excited to release a new open source package cypress-browser-permissions. 🎉

GitHub logo kamranayub / cypress-browser-permissions

A Cypress plugin to set launched browser preferences including permissions like Geolocation, Notifications, Microphone, etc.

cypress-browser-permissions

GitHub code size in bytes GitHub repo size npm npm npm npm NPM npm GitHub last commit npm collaborators

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

Video of notification being displayed

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

Table of Contents

Usage

👋 Read the dev.to introduction post for a quick start guide and an example!

Install the

This package solves a real need when testing more sophisticated applications when using Cypress, the end-to-end testing framework. It helps control the permission level of various browser features such as:

  • Desktop Notifications
  • Geolocation
  • Images
  • Camera
  • Microphone
  • etc.

image

How to Use It

To get started, you'll need to install the package and you'll need Cypress installed already.

npm i cypress cypress-browser-permissions --save-dev

If this is your first time installing Cypress, you'll need to run it once to generate a project structure:

npx cypress open

Then, you need to initialize the plugin to hook it into Cypress' plugin pipeline. In cypress/plugins/index.js, modify it as follows:

+ const { cypressBrowserPermissionsPlugin } = require('cypress-browser-permissions')

/**
 * @type {Cypress.PluginConfig}
 */
module.exports = (on, config) => {
  // `on` is used to hook into various events Cypress emits
  // `config` is the resolved Cypress config
+ config = cypressBrowserPermissionsPlugin(on, config);
+ return config;
};

Now you will have the ability to control various permissions for Chrome, Edge, and Firefox using Cypress environment variables.

For example, if you want to just set permissions for your project you can do so in cypress.json:

{
  "env": {
    "browserPermissions": {
      "notifications": "allow",
      "geolocation": "allow"
    }
  }
}

The plugin will read the permission settings and apply them when launching the browser. It will also reset between launches since modifying the browser profile is persisted across sessions.

You can read more about supported permissions and values in the README.

Writing an End-to-End Notification Test

So let's try it out! Once I finish my Testing Progressive Web Apps Pluralsight course, it will come with an open source sample app. In the meantime, we can write a basic test to see if permissions are working. This same test is included in the repo.

First, we have an HTML file that uses window.Notification to display a desktop notification:

cypress/html/notification.html

<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Cypress Notification Test</title>
</head>
<body>
    <script type="text/javascript">
        const n = new window.Notification('test', { body: 'This is a test!' })
        n.addEventListener('show', (e) => {
            window.__CypressNotificationShown = e;
        })
    </script>
</body>
</html>

You can learn more about how the Notification API works but what we are doing is immediately triggering a notification. Once the browser shows the toast, it triggers the show event on the Notification instance. Since Cypress is awesome and we can hook directly into the window object, we set a callback value globally that we can then inspect/wait for in our test.

If you have a blank Cypress project you do not even need a server as Cypress will automatically host the root of the project when there is no other configuration.

Save the notification.html file under cypress/html and then we can visit that page in the test.

We can create a test suite in cypress/integration:

cypress/integration/notification.test.js

import { isPermissionAllowed } from 'cypress-browser-permissions';

describe("notifications", () => {
    it("should be enabled", () => {
        expect(isPermissionAllowed("notifications")).to.be.true;
    })

    // Only test notification showing in "headed" browsers, which also
    // works in CI :tada:
    Cypress.browser.isHeaded && it("should display desktop notification", () => {

        // Visit the page we created previously
        cy.visit('/cypress/html/notification.html')

        // Wait for the window callback to populate with the event data
        cy.window().its('__CypressNotificationShown').should('exist');
    })
})

Now we can run our tests:

npx cypress open

That's all! If browserPermissions.notifications is set to allow then our test should pass:

test run

And a notification will be shown!

toast

How It Works

In Cypress, you have control over the launch preferences for browsers, so the magic lies in what preferences to pass to each browser.

This topic is not heavily documented as evidenced by this open issue in the Cypress repo I came across while researching this. It has been open since 2018 with no one mentioning the ability to control launch preferences.

Thanks to BrowserStack for documenting some of these permissions as well as these StackOverflow posts:

there is such a question how to implement so that Selenium resolves in that case notifications like this photo https://prod-cdn.sumo.mozilla.net/uploads/gallery/images/2017-10-18-05-45-38-20e1d7.png

it is desirable that he press himself I will be very grateful

I'm not able to click on Allow button of access camera authentication pop up.

Here is the look of pop up.

here

I was able to piece together the information needed to tackle this with a Cypress plugin. Since each browser family uses different preferences, I thought it would be best to abstract it.

What's Next?

My hope is that this package is actually short-lived and the Cypress team can incorporate these permission settings into the core of the product, since it's such an important feature especially when testing new, modern APIs.

There will be a full sample of using Cypress with this plugin (as well as other black magicks such as bypassing service workers and more!) in my Testing Progressive Web Apps course soon on Pluralsight. It should be released in August, you can follow me there to get notified when it releases. The sample app will be open source on GitHub so you'll be able to reference it 👍

Top comments (3)

Collapse
 
kamranayub profile image
Kamran Ayub

Wow, I meant to publish this tomorrow lol 😅

Collapse
 
fenrirthehangry profile image
Tavis Fong

Sorry I am late to the party: Should this still work on the latest Chrome 2 years later? I am having a bit of an issue getting the preferences to actually be set. Cypress says they are, but the browser session says otherwise.

Collapse
 
ktxxt profile image
Darko Riđić

Great post!