Search code examples
javascriptreactjstestingcypressonbeforeunload

Is there a work-around for the Chrome error: "Require user gesture for beforeunload dialogs" during Cypress tests


https://www.chromestatus.com/feature/5082396709879808

Require user gesture for beforeunload dialogs

The beforeunload dialog will only be shown if the frame attempting to display it has received a user gesture or user interaction (or if any embedded frame has received such a gesture). (There will be no change to the dispatch of the beforeunload event, just a change to whether the dialog is shown.)

Here is the problem we're running into. In our single page app, business rules dictate that we alert the user if they click the browser back button.

Which is what this code does below in our app.js:

componentDidMount = () => {
    window.addEventListener('beforeunload', event => {
        event.returnValue = `Are you sure you want to leave?`;
    });
}

If the user navigates away on any page, the default alert box will pop up.

However in our Cypress tests we we have a beforeEach which goes back to the start of the app's flow before each test. This triggers the beforeunload event since we're leaving the page, but we don't see the alert, rather we get that chrome error:

Require user gesture for beforeunload dialogs

Anyone run into this before or have a clue on a work around?

Only thing I can think off at the moment is to remove the beforeEach but then we will need individual tests for each thing we want to test. Rather than just a few page test files...


Solution

  • We were not able to disable the Chrome action for checking if the user has interacted so we came up with a simple work around:

    /* istanbul ignore next */
    componentDidMount = () => {
        if (process.env.NODE_ENV === 'production') {
            window.addEventListener('beforeunload', onBrowserBack);
        }
    }
    
    /* istanbul ignore next */
    componentDidUpdate() {
        // If another error modal is up, DO NOT trigger the beforeunload alert
        if (process.env.NODE_ENV === 'production' && this.props.hasError) {
            window.removeEventListener('beforeunload', onBrowserBack);
        }
    }
    

    Basically the beforeunload alert modal will now only display in the production env, and when we are cypress testing, they will not.