Cypress: beforeunload when running Electron

Created on 23 Oct 2017  路  11Comments  路  Source: cypress-io/cypress

Current behavior:

When I run a test suite on a page that has a beforeunload event listener - hence, it triggers an alert -, first test goes fine, but the second test onwards fails to open the page.

This works fine using Chrome, as the Debugger console shows the following:

Blocked attempt to show a 'beforeunload' confirmation panel for a frame that never had a user gesture since its load. https://www.chromestatus.com/feature/5082396709879808

This makes CI headless tests unfeasible, as they fail for no consistent reason.

Desired behavior:

Electron built-in headless browser should prohibit beforeunload behaviour - same as Chrome does.

How to reproduce:

Open a page that has

window.addEventListener("beforeunload", function (e) {
    (e || window.event).returnValue = 'Are you sure you want to close this page?';
})

in two tests within the same test suite.

Test code:

index.html # started with any node server of your preference

<html>
<head>
    <title>
        Testing
    </title>
    <script>
        window.addEventListener("beforeunload", function (e) {
            (e || window.event).returnValue = 'Are you sure you want to close this page?';
        })
    </script>
</head>
<body>
<div id="helloWorld">Hello World!</div>
<button onClick="document.getElementById('helloWorld').style.display = 'none';">Click me!</button>
</body>
</html>
describe(`failing electron test suite`, () => {

        beforeEach(() => {
            cy.visit('http://127.0.0.1:8080/index.html')
        })
        it('sees hello and clicks to hide', () => {
            cy.contains('Hello').should('be.visible')
            cy.get('button').click();
        })

        it('should see world opening the page again', () => {
            cy.contains('World').should('be.visible')
        })

})

Additional Info (images, stack traces, etc)

I managed to fix this by exposing the listener in window, and run

cy.window()
    .then(win => win.myListener && win.removeEventListener('beforeunload', win.myListener))

straight after

cy.visit('<url>')
  • Operating System: MacOS Sierra 10.12.6 (16G29)
  • Cypress Version: 0.20.1
  • Failing Browser Version: Electron 53
  • Working Browser Version: Chrome 61.0.3163.100
duplicate

Most helpful comment

I thought this may have been fixed in 3.3.0 Cypress version, but it's not. Experiencing this same issue documented in electron:

All 11 comments

I'm confused why this behavior causes tests in Electron to fail. What about your test code requires this dialog? Can you post your test code?

Electron isn't showing the dialog because its using Chromium 53, and you're likely using a new version of Chrome which has had this feature implemented.

You could also avoid adding this event listener entirely under Cypress tests.

if (window.Cypress) {
  ...
}

I've updated the comment, it's happening whenever you change something within DOM.

Okay thank you - this should be enough for us to reproduce.

Also BTW you could run Chrome in CI by using the --browser chrome option. You'll need it locally installed but we provide docker images with it prebuilt.

Good to know. Regarding window.Cypress, I'd rather leave the code agnostic to testing frameworks, and I can live with a global signature of the listener, that I can control in the testing environment.

That's fair. At the very least you could conditionally make the event listener global only in the Cypress test environment.

There is potentially a different approach here where you use the unload event listeners from within Cypress itself and then you remove the e.returnValue which then would prevent that error from occurring.

In that situation you could test that the returnValue was set correctly (programmatically) but remove it to prevent the browser from reacting to it - since you don't care about it anyway.

https://docs.cypress.io/api/events/catalog-of-events.html#

It appears this feature was implemented in Chrome 60.

I think the actual fix for this are Lifecycle Events where instead of navigating the <iframe> we blow away the application directly, which avoids trigger beforeunload events.

I thought this may have been fixed in 3.3.0 Cypress version, but it's not. Experiencing this same issue documented in electron:

I have exactly the same issue with 3.3.0 with Electron only. Chrome works fine even the error message stays in the console

Closing as duplicate of #2118

There are workarounds as well as a full explanation of this issue in this comment: https://github.com/cypress-io/cypress/issues/2118#issuecomment-580095512

Was this page helpful?
0 / 5 - 0 ratings