Originally posted at itreallymatters.net by Jarmo Pertman.
Usually when a JavaScript dialog pops up at some webpage then there is a highly possibility that it shouldn’t be there in the first place. It adds just more inconvenience to any user when needing to perform an additional click to get rid of some pointless message. If possible then solve the problem by removing those pointless usability mishaps altogether!
If there indeed exists some actual need of having a dialog window - perhaps the user is confirmed about starting a nuclear war and there’s no sufficient possibility to undo that action - then it’s needed to deal with those popups during automated testing. If the testing tool doesn’t support this types of obstacles then I’m recommending to ditch that tool and choosing something else. For Watir there are a number of possibilities to handle these dialogs, one more complex than another.
But there exists a very easy and elegant way to handle the JavaScript dialogs also. For some reason this technique hasn’t been recommended much before in Watir’s community until Alister Scott wrote about it in his blog. The main idea is to override the JavaScript dialog functions.
I’m writing my own blog post on that topic because I don’t agree with everything Alister has written. He’s recommending to override the functions to return true
, but i don’t think that this is a correct way to do. Main reason for my thoughts is that it’s just not simulating the real functions properly. In real scenario, alert returns true
in Firefox and undefined
in IE. It doesn’t matter though since no-one is using return value of an alert for any functionality, right? At least i hope so. But it’s different altogether for prompt and confirm! Check out the following output from JavaScript console:
>>prompt("enter!")
"info"
>>prompt("cancel!")
null
>>confirm("yes!")
true
>>confirm("no!")
false
gist.github.com/663313#file_console.js
As you can see then if user enters anything into the prompt’s text field then that value is returned from the function and if he decides to click on a Cancel
instead then null
is returned. For the confirm, true
was returned when “OK” was clicked and false
otherwise.
Since both of the confirm and prompt might return different values then these values might be used in web pages for different functionality. This means that they should be simulated to work in both ways also in tests. Instead of returning true
all the time, a different values should be returned as needed:
# don't return anything for alert
browser.execute_script("window.alert = function() {}")
# return some string for prompt to simulate user entering it
browser.execute_script("window.prompt = function() {return 'my name'}")
# return null for prompt to simulate clicking Cancel
browser.execute_script("window.prompt = function() {return null}")
# return true for confirm to simulate clicking OK
browser.execute_script("window.confirm = function() {return true}")
# return false for confirm to simulate clicking Cancel
browser.execute_script("window.confirm = function() {return false}")
gist.github.com/663313#file_dialogs.rb
This code works with Watir, but not for FireWatir for some reason. I’m suspecting that FireWatir’s JavaScript execution doesn’t happen in the same scope as the page under test. This same technique might work with any testing tool that allows to execute JavaScript on the page. You’d just have to perform execute_script
right before interacting with an element which triggers the dialog.
Since Watir-Webdriver returns the executed JavaScript back to the Ruby then it allows for even cooler solutions where you can verify that an alert was shown indeed. For the prompt and confirm, the actual behavior of the web page itself should be enough for verification.
Hopefully next time if you happen to see any JavaScript dialog, you remember that it’s possible to get rid of them very easily.