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.
Electron built-in headless browser should prohibit beforeunload behaviour - same as Chrome does.
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.
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')
})
})
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>')
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.
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
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: