I am trying to write a Cypress test to validate that a beforeunload dialogue appears when a user tries to navigate away from an incomplete form.
When a user tries to leave a page after interacting with a form, my site activates a beforeunload dialogue to warn them unsaved data may be lost. Everything works fine when I test the behavior manually but When I try to write a test in Cypress I get
'[Intervention] 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 is after typing in various fields and simulating click() events. It seams that JS does not trigger a true "user gesture" . I understand why Chrome does this but I would hope there would still be a way to write tests. I've found workarounds for a similar problem with video playback # https://github.com/cypress-io/cypress/issues/2376. But this does not seam to work for "beforeunload". None of the flags I found here seam to work https://peter.sh/experiments/chromium-command-line-switches/
on('before:browser:launch', (browser = {}, args) => {
if (browser.name === 'chrome') {
// Mac/Linux
args.push('--disable-gesture-requirement-for-presentation')
}
return args
})
Hoping there might be a work around. Can I either simulate an actual "gesture" in Cypress or disable the requirement in Chrome? Any help is greatly appreciated.
Related
I'm sure I'm missing something relatively simple - but for the life of me I can't find the answer. When trying to do a reload prevention in react, my onbeforeunload function is not firing when I press the reload button in the browser menu (Chrome). It works if I press CMD+R/F5 and once that's done once - the browser button also fires the function. It simply doesn't work if I attempt to click reload first. Additionally, if I navigate through the router once, it also seems to register. I am using the following code to register the refresh on my top level template:
class Template extends React.Component {
constructor(props) {
super(props);
}
refreshPrevent = (e) => {
e.preventDefault();
e.returnValue = true;
}
componentDidMount() {
console.log("registering refresh handlers");
window.addEventListener("beforeunload", this.refreshPrevent );
}
componentWillUnmount() {
window.removeEventListener("beforeunload", this.refreshPrevent);
}
Any ideas would be appreciated.
I don't see any errors in your code. I use similar code in my react applications, but I hadn't tested this particular problem before until you posted.
It seems, according to the MDN documentation that this behavior is normal:
To combat unwanted pop-ups, some browsers don't display prompts
created in beforeunload event handlers unless the page has been
interacted with. Moreover, some don't display them at all.
So, when your app first loads, until you interact with the page in some way, you can hit the browser refresh button and depending on the browser, the page will reload without displaying a prompt.
However, once you have done something on the page with your mouse or keyboard or via touch, then the prompt will be displayed.
The MDN documentation concludes (emphasis added):
Note also, that various browsers ignore the result of the event and do not ask the user for confirmation at all. In such cases, the document will always be unloaded automatically. Firefox has a switch named dom.disable_beforeunload in about:config to enable this behaviour. As of Chrome 60, the confirmation will be skipped if the user has not performed a gesture in the frame or page since it was loaded.
This fits with the spec that we should expect certain situations, like an uninteracted-with page plus refresh, to skip prompting the user:
The user agent is encouraged to avoid asking the user for confirmation if it judges that doing so would be annoying, deceptive, or pointless. A simple heuristic might be that if the user has not interacted with the document, the user agent would not ask for confirmation before unloading it.
When ever u made some change to page and try to leave chrome/firefox throws a alert. Data you entered may not be saved with (Leave or Stay) buttons.
How i can do certain action when user clicks leaves or stay.
To which event i need to listen to to make actions when we click leave or stay?
TIA
There is no window close event.You can use onbeforeunload to prevent asking for simple confirmation etc.
That is what is done internally by website developers on their page. But you can't read that answer from an user script. It is simply the website developers implementation.You can't read user's response given to website developers confirm question by user from an application.
Those popups are implemented by the corresponding websites not browser.
Solution
Modern browsers now consider displaying a custom message to be a security hazard and it is removed therefore. Browsers now only display generic messages. So we can simply do this:-
window.onbeforeunload = function() {
return false;
};
window.onbeforeunload = null; // this will not show any popup.
So just remove everything fron onbeforeunload and return false and make it null. This will solve your problem.
Note: You can't show custom message or do anything significant using onbeforeunload. That is the answer to your question originally asked.
My wedsite getting "Prevented site from opening window." after deployment.
There is no much tricky code in that.
if( $('#textbox').val().length == 0 ) {
alert("please fill the details");
}
While showing the alert I am getting the above alert. When I click on Allow its working fine .
Happening only in IE and firefox.
Please help. Really annoying. And in development mode its not coming. After deploy on tomcat getting this.
This is a setting in your browser. In development it didn't happen because you were probably running it locally. Try disabling your popup blocker or adding your domain to the allow list
You are using an alert box to warn a user that they haven't filled in a form correctly. There's all sorts of reasons why you don't want to do this. One of them is that the browser may prevent the page from doing so. The other reasons all have to do with how annoying this behaviour is to the user.
The user may have their speakers turned up so high that your alert box deafens them. They may happen to click on something as the alert box shows, causing them to lose the alert box on their desktop and preventing them from navigating your site. More than ever though, you are probably going to annoy your user - the browser is doing you a favour by blocking the alert box!
If the form has been filled in incorrectly, show an HTML element with a red background that will warn them. This achieves what you want without making noise or forcing the user to find something and click on it. Everyone's a winner!
If the user refreshes the page in question it will add another record to the database, so I want to warn the user through an alert box if they really want to refresh the page and if they click ok then the page should be refreshed otherwise if they click cancel it won't be.
How to make this type of alert box appear when the browser's refresh button is clicked in a way that is cross browser compatible?
You can do it like this:
window.onbeforeunload = function() {
return "Data will be lost if you leave the page, are you sure?";
};
This would show a prompt to the user allowing them to cancel. It's not refresh specific, but for your purposes (like editing a question on SO) that doesn't seem to matter, it's loss of info no matter where you're leaving to.
There isn't a way to tie it to just the refresh action, but you may want to look into window.onbeforeunload. This will allow you to run a function that returns a string just before the page is unloaded. If this string is not empty, then a popup confirmation dialog, containing this string and some other boilerplate text provided from the browser.
For example:
window.onbeforeunload = function () {
if (someConditionThatIndicatesIShouldConfirm) {
return "If you reload this page, your previous action will be repeated";
} else {
//Don't return anything
}
}
Also, if the current page was loaded via a POST operation, then the browser should already display a confirmation box when the user tries to refresh it. As a general rule, any action that changes the state of the data on the server should be done through a POST request, rather than a GET.
All the answers are quite old, as of today 2020, according to HTML specification, you can do it this way.
Important Note: Custom text is not supported in most of the browsers now. (it was supported in older browsers).
https://developer.mozilla.org/en-US/docs/Web/API/WindowEventHandlers/onbeforeunload
window.addEventListener('beforeunload', function (e) {
// Cancel the event
e.preventDefault(); // If you prevent default behavior in Mozilla Firefox prompt will always be shown
// Chrome requires returnValue to be set
e.returnValue = '';
});
There are two possible ways forward with this, both quite different.
One way would be to have an event handler bound to onbeforeunload event so that you can detect when the user is browsing away from the current page. If my memory serves me correctly however, onbeforeunload is not consistent across browsers (I don't think Opera responds to it IIRC, but have no way to currently test). Of course, this solution fails if the user turns off JavaScript.
The second and more robust way would be to implement the Post Redirect Get pattern which when used, prevents the data from being posted again when a user refreshes the page.
This is not possible. The best you can do is use the onbeforeunload event but that will fire on any event leaving the current page. It is not possible to target the refresh button specifically.
See e.g. this question on onbeforeunload
It might be better though to build a duplicate check into your database. That would catch accidental submissions using the "back" button as well.
An alternative would be using a random one-time token that gets built into the form. If two operations are attempted using the same token, you would stop it.
Quoting from official Mozilla site here, It is no longer supported to supply a custom message.
When this event returns (or sets the returnValue property to) a value other than null or undefined, the user will be prompted to confirm the page unload. In older browsers, the return value of the event is displayed in this dialog. Starting with Firefox 44, Chrome 51, Opera 38, and Safari 9.1, a generic string not under the control of the webpage will be shown instead of the returned string. For example:
Firefox displays the string, "This page is asking you to confirm that you want to leave - data you have entered may not be saved." (see bug 588292).
Chrome displays the string, "Do you want to leave this site? Changes you made may not be saved." (see Chrome Platform Status).
This question already has answers here:
Identifying Between Refresh And Close Browser Actions
(13 answers)
Closed 6 years ago.
After being through numerous forums available on the net for last 5 days, I am still not able to completely track down the browser close event. My requirement is to generate a popup message, when user tries to close the browser.
I have called my javascript function on body 'onbeforeunload' event. And I have hardcoded the conditions to check the mouse-coordinates for the red 'X' buton of browser, refresh, File-close or Alt-F4.
My code works fine when browser window is Maximized, but fails if we shrink it after a limit. Please help me, if some body has already found the solution to a similar problem.
Thank you.
Aggregated Responses of OP
------
Ok, just tell me if it is possible to detect if a user has clicked on the Refresh button of the browser. Also, Refresh can be triggered by Right-click - Refresh or Ctrl-R. My requirement is to make a variable false on Refresh. I am just able to do it on F5, but all other ways are still out of my reach. The same would be applied to Back button.
Hi ppl, Thanks for all who replied at least. I have talked to my seniors regarding this and they have now understood and have compromised with the browser menu buttons. So now my task has become easy. Now, I am using a variable and making it true by default. As, I mentioned earlier I just have to catch the onbeforeunload and popup a message when user tries to leave. The message will not popup when user is navigating to other pages, as I have made the variable as false on all the links of my page using following piece of code:
document.onclick = function() {
//To check if user is navigating from the page by clicking on a hyperlink.
if (event.srcElement.tagName == 'A')
blnShowMsg = false; //To not popup the warning message
else
blnShowMsg = true; //To popup the warning message
}
In my case still the message is shown when user does Refresh, back or goes to any link in Favorites, etc.
Thanks buddy, but I have already gone through that and didn't find much help there too. My seniors are not happy with that solution as putting a flag on every link of my application is a complicated job and they fear of breaking the application. Any other suggestions would be appreciated. Thanks once again.
Is there no one who can think of a solution here!!! where are all the experts???
The question isn't an unusual one. Yet after 5 days searching the internet you still haven't found a satisfactory answer. That in itself should be a fairly plain indicator.
What I've found on the web is there is a serious aversion to the 'no can do' answer. When something can't be done the normal response is to make no response.
Bottom line is not only can what you are trying do not be done it should not be done.
I think you need to go back to your seniors and explain to them that a Web UI is a guest hosted by a browser on a client machine. This guest status is an important one.
Would you want a guest in your home to have the power to enforce you to alert them when you want to go to the toilet? No?
Similarly the browser limits what info the guest UI is allowed to access. Even if you found a workaround for the fact that browsers aren't giving up this info voluntarily, such clever hacks are fragile and likely to be constant source of bugs.
Since its likely that the application was originally intended to be delivered via the browser before any code was cut, the fault lies with including the requirement in the first place.
All we can do sympathise with you in being asked to perform an near impossible and certainly not sensible requirement.
Add this script to your HTML:
window.onbeforeunload = function (e)
{
e = e || window.event;
var y = e.pageY || e.clientY;
if (y < 0){
return "Do You really Want to Close the window ?"
}
else {
return "Refreshing this page can result in data loss.";
}
}
In your function:
document.onclick = function()
{
//To check if user is navigating from the page by clicking on a hyperlink.
if (event.srcElement.tagName == 'A')
blnShowMsg = false; //To not popup the warning message
else
blnShowMsg = true; //To popup the warning message
}
blnShowMsg will be true for any click on your page except sometimes when the user click a link. I say sometimes because if event.srcElement.tagName doesn't work in some browser it will allways be true. And you have to add lots of cases to to allow using form controls etc... Some browsers can even automatically reload a page, and I'm not sure if onload events will run then or not.
But popping a warning about leaving the page (or similar) all the time is sure to annoy a lot of people, and they'll probably leave permanently...
If you're making for instance a online program where it's critical that something is saved before leaving, I'll say that catching the before unload event is a little too late, better to make some kind of autosave (see Gmail) and/or some kind of non-obtrusive warning when the user mouseover the navigation menues without saving.
But you can't force stupid users not to do anything stupid, on a web interface this is even more true because you have less controll: if the user want to terminate the program before saving they will find a way to do so, and they will call you and complain when the unsaved data dissapears ;P
I have a method that is a bit clunky but it will work in most instances.
Create a "Holding" popup page containing a FRAMESET with one, 100% single FRAME and place the normal onUnload and onbeforeUnload event handlers in the HEAD.
<html>
<head>
<script language="Javascript" type="text/javascript">
window.onbeforeunload = exitCheck;
window.onunload = onCloseDoSomething;
function onCloseDoSomething()
{
alert("This is executed at unload");
}
function exitCheck(evt)
{
return "Any string here."}
</script>
</head>
<frameset rows="100%">
<FRAME name="main" src="http://www.yourDomain.com/yourActualPage.aspx">
</frameset>
<body>
</body>
</html>
Using this method you are free to use the actual page you want to see, post back and click hyperlinks without the outer frame onUnload or onbeforeUnload event being fired.
If the outer frame is refreshed or actually closed the events will fire.
Like i said, not full-proof but will get round the firing of the event on every postback.
I believe there was some ways to do this in some browsers (and probably not very reliably) some years ago. Because I remember those awful massive spam-popups that spawned more popups as you closed one. But that's why it's not a good idea to allow scripts to detect this, and why browsers should prevent it and most modern browsers probably does.
I was asked to do something similar for a survey invitation script; they wanted to ask the visitor if they would like to answer a survey about their website, and then the survey should pop up when they leave the site. The solution I found was to (repeatedly) explain the management that this was probably impossible, or at best very unreliable; and instead the survey should popup immediately (if the visitor agreed to take the survey) and the intro page should tell the visitor to leave this window open and go back to it after reviewing the page.
onunload and onbeforeunload are not meant for this, so will naturally be unreliable.
A better solution is to change the problem. Have the client send a heartbeat, periodically telling the server the page is still active. When the hearbeat stops, you know you can clean up the server.
You might find this interesting: https://stackoverflow.com/a/3586772/1483977
Or this: Identifying Between Refresh And Close Browser Actions
"Thanks buddy, but I have already gone through that and didn't find much help there
too. My seniors are not happy with that solution as putting a flag on evry link of my
application is a complicated job and they fear of breaking the application. Any other
suggestions would be appreciated. Thanks once again."
If you use jQuery, you can add link flags automatically. The way I would handle your problem is when the user performs the "dangerous" actions, iterate all the page links that are "dangerous" and then bind events to them.
$("#dangerbutton").click(function(){
$("a").not( safeList ).click(function()
{
var dest = $(this).attr('href');
someWarningFunction(function(){
/* Stay where we are because user opted to stay */
},function(){
/* Continue Following Link because user didn't mind */
window.location= dest;
});
return false;
});
});
This way will only fire on link clicks on your page. Users have to get used to the fact that "close window == cancel everything" logic, because many use and trust that facility.
You might have seen in many of the web form pages to warn the user before closing the page.When somebody refreshes the page, then there is a chance for loosing all filled data. In that case it is very helpful.
Page life cycle includes two events like onunload and onbeforeunload. For this case you need to bind the script function in window. Onbeforeunload so that it will be called when page is unloading.
Again this warning should not be fired when you are actually submitting the page. For that set a boolean value (e.g. shouldsubmit) to submit the page.