JavaScript Alert Pop Up with Watir v1.9.0
18 June 2011
Simple example for handling a JavaScript Alert popup using the Google preferences page. This was tested on Ruby 1.8.7, Win 7 with IE8.
"$ie.javascript_dialog.button('OK').click" replaces the WinClicker method

require 'watir' $ie = Watir::IE.new $ie.goto 'http://www.google.com/preferences?hl=en' $ie.radio(:id,'nof').set $ie.button(:name,'submit2').click_no_wait $ie.javascript_dialog.button('OK').click $ie.close
JavaScript Pop Ups
These are pop ups created using javascript. The ones below come from the watir unit tests.
They would be created using javascript, and an example is shown under each of them.

<input type = button onClick = 'javascript:x = confirm('Do you really want to do this');">

<input type = button onClick = 'javascript:y = prompt('Enter Something Useful');">

<input type = button onClick = 'javascript:z = alert('This is an alert box');">
You can read more details about JavaScript popups at w3schools .
Simplest way to stop JavaScript Pop Ups from showing when running your Watir tests
You simply override the JavaScript function being called.
For example:
require 'watir'
b = Watir::Browser.start "http://somepagewithdialogs"
# don't return anything for alert
b.execute_script("window.alert = function() {}")
# return some string for prompt to simulate user entering it
b.execute_script("window.prompt = function() {return 'my name'}")
# return null for prompt to simulate clicking Cancel
b.execute_script("window.prompt = function() {return null}")
# return true for confirm to simulate clicking OK
b.execute_script("window.confirm = function() {return true}")
# return false for confirm to simulate clicking Cancel
b.execute_script("window.confirm = function() {return false}")
# interact with some element which would trigger the pop up
b.button(:id => "dialogTrigger").click
Other more complex solutions
Note: AutoIT's dll may not be registered after installing Ruby, in which case you should register it manually. See details here - http://rubyforge.org/pipermail/wtr-general/2006-March/005173.html
Solution #1
http://rubyforge.org/pipermail/wtr-general/2005-April/001461.html
Solution #2
# Auto Popup Handler. Posted by brad@longbrothers.net # require 'win32ole' # already included if you use 'require watir' # # Function to look for popups def check_for_popups autoit = WIN32OLE.new('AutoItX3.Control') # # Do forever - assumes popups could occur anywhere/anytime in your application. loop do # Look for window with given title. Give up after 1 second. ret = autoit.WinWait('Popup Window Title', '', 1) # # If window found, send appropriate keystroke (e.g. {enter}, {Y}, {N}). if (ret==1) then autoit.Send('{enter}') end # # Take a rest to avoid chewing up cycles and give another thread a go. # Then resume the loop. sleep(3) end end # # MAIN APPLICATION CODE # Setup popup handler $popup = Thread.new { check_for_popups } # start popup handler at_exit { Thread.kill($popup) } # kill thread on exit of main application # # Main application code follows # ...
Solution #3
# A Better Popup Handler using the latest Watir version. Posted by Mark_cain@rl.gov # require 'watir\contrib\enabled_popup' # def startClicker( button , waitTime= 9, user_input=nil ) # get a handle if one exists hwnd = $ie.enabled_popup(waitTime) if (hwnd) # yes there is a popup w = WinClicker.new if ( user_input ) w.setTextValueForFileNameField( hwnd, "#{user_input}" ) end # I put this in to see the text being input it is not necessary to work sleep 3 # "OK" or whatever the name on the button is w.clickWindowsButton_hwnd( hwnd, "#{button}" ) # # this is just cleanup w=nil end end # # MAIN APPLICATION CODE # $ie = Watir::IE.start( "c:\test.htm" ) # This is whatever object that uses the click method. # You MUST use the click_no_wait method. $ie.image( :id, '3' ).click_no_wait # # 3rd parameter is optional and is used for input and file dialog boxes. startClicker( "OK ", 7 , "User Input" ) # # Main application code follows # ...
Solution #4
require 'Watir' require 'watir/contrib/enabled_popup' # Use click_no_wait to launch the popup or your script will hang browser.button(:id, /someText/).click_no_wait hwnd = browser.enabled_popup(5) if (hwnd) #yeah! a popup popup = WinClicker.new popup.makeWindowActive(hwnd) popup.clickWindowsButton("Windows Internet Explorer", "OK", "30") end
Solution #5 - Summary - 09 July 2008
I spent some time trying to figure out how to dismiss javascript popups. The information is out there, but it took a while to get it all put together and then to try out the various suggestions until I found one that worked for me. Here's a summary in case it helps someone else.
1.) You need to update the winClicker.rb file in your watir directory(in my case, it was at: c:\ruby\lib\ruby\gems\1.8\gems\watir-1.5.3\watir). Change the dialog title from "Internet Explorer" to "Windows Internet Explorer". I used the regex /Internet Explorer/ so that it will work no matter which version of IE I use.
2.) Require 'watir/contrib/enabled_popup' for your tests.
3.) Define the popupChecker method to watch for a popup and dismiss it (in this case, by clicking the button with the specified text):
def popupChecker(text)
Timeout::timeout(2)do
begin
if ie.enabled_popup
hwnd = ie.enabled_popup(5)
w = WinClicker.new
w.makeWindowActive(hwnd)
w.clickWindowsButton_hWnd(hwnd,text)
end
rescue Timeout::Error
puts 'No popup existed'
end
end
end
4.) Use the click_no_wait method on the link or button that will launch the popup.
ie.button(:text, 'Continue').click_no_wait
5.) Call the popupChecker method in case a popup exists. You may run into timing problems with the Watir actions that follow the popupChecker. To get around this, I added an ie.wait statement after calling the popupChecker method.
popupChecker('OK')
ie.wait
6.) Some popups are launched by selecting an item from a select_list. Since the click_no_wait method is required on the action that launches the popup, you need something like a select_no_wait method for a select list. Charley Baker provided me with this method:
#select_no_wait method for select lists - needed for popups resulting from select lists module Watir class Element #select_no_wait - selects a drop-down element spawning a new process. #this is needed to close potential pop-ups that select drop-down can trigger. def select_no_wait(item) assert_enabled highlight(:set) object = "#{self.class}.new(self, :unique_number,#{self.unique_number})" @page_container.eval_in_spawned_process(object + ".select('#{item}')") highlight(:clear) end end end
7.) Many people has the problem about click "OK/Cancel" or "OK" in the pop up. I think the code below can deal with the problem
require 'watir' def check_for_popups(title="Window Internet Explorer", button="OK") popup=Thread.new { autoit=WIN32OLE.new('AutoItX3.Control') ret=autoit.WinWait(title,"",60) if (ret==1) puts "There is popup." autoit.WinActivate(title) button.downcase! if button.eql?("ok") || button.eql?("yes") || button.eql?("continue") autoit.Send("{Enter}") else autoit.Send("{tab}") autoit.Send("{Enter}") end elsif (ret==0) puts "No popup, please check your code." end } at_exit { Thread.kill(popup) } end $ie.link(:text,//).click_no_wait check_for_popups("Window Internet Explorer", "OK")
Solution #6
>Install autoit-v3-setup.exe (http://www.autoitscript.com/files/autoit3/autoit-v3-setup.exe)
>if you are expecting a pop up, use 'click_no_wait' instead of 'click'.
#///////////////////////////////////////////////////////////////////////////// #Name: check_pop-up #Description: Checks If a pop up with the given title and text appears. Throws error if the pop up does not appear. # If the pop up appears clicks the 'OK' button. #Arguments: title: Title of the pop up to look for # text: Text of the pop up to look for #///////////////////////////////////////////////////////////////////////////// def check_pop_up(title,text) auto=WIN32OLE.new('AutoItX3.control') #Refer to AutoIt WinTitleMatchMode document: "2 = Match any substring in the title" auto.Opt("WinTitleMatchMode", 2) #Check if such pop up appears. Time out after 10 sconds popup_appears=auto.WinWait(title,text,10) assert_equal(popup_appears,1,"The popup did not appear/the popup text is incorrect") #Click 'OK' button w=WinClicker.new w.clickWindowsButton(title,"OK") #Check if the pop up disappeared. popup_disappears=auto.WinExists(title,text) assert_equal(popup_disappears,0,"The popup did not close") end
require "watir" require "test/unit" require "watir/assertions" require #FILE THAT CONTAINS THE ABOVE METHOD# $browser = Watir::IE.attach(:title, #BROWSER TITLE#) class TestSuite < Test::Unit::TestCase include Watir::Assertions def test01 $browser.frame(:name,"content").form(:name,"MainForm").button(:name,"SaveContinue2").click_no_wait check_pop_up(#POP UP TITLE#,#POP UP TEXT#) end end
Solution #7 - Summary by Tony (works on watir 1.6.2)
>This solution doesnt depend on autoit. It uses the win32ole methods to handle the popups.
>The advantage of using this method is, the popup for the ie browser which is currently be used by watir will only be affected. There can be other browser that have popups but these wont be affected. Only the browser that is being handled by watir, its popup will be affected.
>if you are expecting a pop up, use 'click_no_wait' instead of 'click'.
>You would have to add the below code to C:\ruby\lib\ruby\gems\1.8\gems\watir-1.6.2\lib\watir\ie-class.rb
( add into module Watir, class IE )
#///////////////////////////////////////////////////////////////////////////// #Name: clickprompt #Description: Waits for the popup to appear and then clicks the ok or cancel button # #Arguments: button: The button to be pressed - "OK" or "CANCEL" # txt: Text to be passed into the prompt dialog box # waitTime: the waiting time caluclated as waitingtime/0.2 currently set to 50 seconds #Returns: This returns the popup text if popup is found or '' if no popup is found #///////////////////////////////////////////////////////////////////////////// def clickprompt(but="OK",txt ="", waitTime = 10) tim = 0 poptxt= '' while tim < waitTime sleep 0.2 pophwnd = Win32API.new("user32", "GetWindow", 'Li', 'L').Call(@ie.hwnd.to_i, 6) # the above returns any popup windows that are present for the specific window tim += 0.2 tim += waitTime if pophwnd != 0 end return '' if pophwnd == 0 button = but.upcase outval = ' ' * 30 Win32API.new("user32", "GetWindowText", 'Lpi', 'L').Call(pophwnd,outval,30) popwndtitle = outval.rstrip.chomp("\000") # window title stored here outval = nil #poptype = 0 #alert and confirm have ie6 - Microsoft Internet Explorer #ie7 - Windows Internet Explorer #ie8 - Message from webpage if popwndtitle.include?("Microsoft Internet Explorer") || popwndtitle.include?("Windows Internet Explorer") || popwndtitle.include?("Message from webpage") #confirm and alerts have the above 3 window titles # poptype =1 means this is a javascript alert tag #poptype = 1 poptxt = handlepopup1(pophwnd,button) elsif popwndtitle.include?("Explorer User Prompt") #prompts have the above window title #poptype = 2 poptxt = handlepopup2(pophwnd,button, txt) elsif popwndtitle.include?("Connect to") #authentication dialog #also make sure the username and password text fields are present - if present we got the auth dialog cntrlhwnd = 0 cntrlhwnd = Win32API.new("user32", "GetDlgItem", 'Li', 'L').Call(pophwnd, 1002) #poptype = 3 if cntrlhwnd != 0 #verified the 2 textboxes are present to enter the values return '' if cntrlhwnd == 0 poptxt = handlepopup3(pophwnd,button, prompt) end return poptxt end def handlepopup1(pophwnd, button) # handles the alerts and confirm dialogs #Yes there is a popupwindow... hence get the controlhandle for the text control - 65535 cntrlhwnd = Win32API.new("user32", "GetDlgItem", 'Li', 'L').Call(pophwnd, 65535) #now get the text from the popup outval = ' ' * 900 Win32API.new("user32", "GetWindowText", 'Lpi', 'L').Call(cntrlhwnd,outval, 900) poptext = outval.rstrip.chomp("\000") outval = nil #confirm ok-1 and cancel-2, alert ok-2 cntrlhwndOK = 0 cntrlhwndCANCEL = 0 cntrlhwndOK = Win32API.new("user32", "GetDlgItem", 'Li', 'L').Call(pophwnd, 1) if cntrlhwndOK == 0 # only 1 button alert cntrlhwndOK = Win32API.new("user32", "GetDlgItem", 'Li', 'L').Call(pophwnd, 2) clickWin32Button(cntrlhwndOK) # done clicking javascript ok button return poptext else # this is a confirm with 2 buttons cntrlhwndCANCEL = Win32API.new("user32", "GetDlgItem", 'Li', 'L').Call(pophwnd, 2) end button.include?("OK") ? clickWin32Button(cntrlhwndOK) : clickWin32Button(cntrlhwndCANCEL) #clickWin32Button(cntrlhwndCANCEL) return poptext end private :handlepopup1 def handlepopup2(pophwnd, button, prompt) #handles prompt boxes which takes a value as input cntrlhwndOK = Win32API.new("user32", "GetDlgItem", 'Li', 'L').Call(pophwnd, 1) cntrlhwndCANCEL = Win32API.new("user32", "GetDlgItem", 'Li', 'L').Call(pophwnd, 2) # get handle to the text control from the prompt box cntrlpromptText = Win32API.new("user32", "GetDlgItem", 'Li', 'L').Call(pophwnd, 8132) #now get the text from the popup outval = ' ' * 200 Win32API.new("user32", "GetWindowText", 'Lpi', 'L').Call(cntrlpromptText,outval, 200) poptext = outval.rstrip.chomp("\000") outval = nil cntrltextarea = Win32API.new("user32", "GetDlgItem", 'Li', 'L').Call(pophwnd, 8133) unless prompt.empty? sendmessage = Win32API.new("user32", "SendMessage", 'LLpp', 'L') sendmessage.Call(cntrltextarea, 0x000C, '', prompt) # calling sendmessage with WM_SETTEXT end button.include?("OK") ? clickWin32Button(cntrlhwndOK) : clickWin32Button(cntrlhwndCANCEL) return poptext end private :handlepopup2 def handlepopup3(pophwnd, button, prompt) # handles the auth dialog box , 3 tries then the 401 page is shown cntrlhwnd = Win32API.new("user32", "GetDlgItem", 'Li', 'L').Call(pophwnd, 1002) cntrlusername = Win32API.new("user32", "GetDlgItem", 'Li', 'L').Call(cntrlhwnd, 1003) cntrlpassword = Win32API.new("user32", "GetDlgItem", 'Li', 'L').Call(cntrlhwnd, 1005) if prompt.size == 2 sendmessage = Win32API.new("user32", "SendMessage", 'LLpp', 'L') sendmessage.Call(cntrlusername, 0x000C, '', prompt[0]) # calling sendmessage with WM_SETTEXT sendmessage.Call(cntrlpassword, 0x000C, '', prompt[1]) # calling sendmessage with WM_SETTEXT end cntrlhwndOK = Win32API.new("user32", "GetDlgItem", 'Li', 'L').Call(pophwnd, 1) cntrlhwndCANCEL = Win32API.new("user32", "GetDlgItem", 'Li', 'L').Call(pophwnd, 2) button.include?("OK") ? clickWin32Button(cntrlhwndOK) : clickWin32Button(cntrlhwndCANCEL) end private :handlepopup3 def clickWin32Button(cntrlhwnd) Win32API.new("user32", "SendMessage",'LLLL','L').Call(cntrlhwnd, 0x0006, 1,0) Win32API.new("user32", "SendMessage",'LLLL','L').Call(cntrlhwnd, 0x00F5, 0,0) end private :clickWin32Button
require 'watir' iewin = Watir::IE.new iewin.goto("http://www.w3schools.com/js/tryit_view.asp?filename=tryjs_alert") iewin.button(:value, "Show alert box").click_no_wait txt = iewin.clickprompt() # waits for popup and click ok puts txt #prints the popup text
Solution #8 Fetched from watir General discussions by Raghu Kiran
I got the below solution from watir general discussions.Original Contributor Darryl (gem dandy) Brown. I did not face any problems when the script was run for 5 times continuously.
Original discussion is here : http://groups.google.com/group/watir-general/browse_thread/thread/eeb37d3a8562936/e9ec1258c2aa547f?hl=en&q=#e9ec1258c2aa547f
require 'watir/ie'
require 'win32ole'
require 'watir\contrib\enabled_popup'
def jsClick( a, button, user_input=nil)
waitTime=30
hwnd = a.enabled_popup(waitTime)
if (hwnd)
w = WinClicker.new
if ( user_input )
puts("if = user input")
w.setTextValueForFileNameField(hwnd, "#{user_input}")
end
sleep 3
w.clickWindowsButton_hwnd(hwnd, "#{button}")
w=nil
end
end
test_site = "http://www.google.co.in"
$ie = Watir::IE.new
$ie.goto test_site
$ie.maximize()
$ie.link(:text, 'Search settings').flash
$ie.link(:text, 'Search settings').click
$ie.radio(:id,"nof").flash
$ie.radio(:id,"nof").set
$ie.button(:name,"submit2").focus
$ie.button(:name,"submit2").flash
$ie.button(:name,"submit2").click_no_wait
jsClick( $ie, "OK")
sleep 5
$ie.close
Solution #9 Fetched from Watir general discussions
First, create a file called 'popup_closer.rb' and add the following code:
require 'win32ole' begin autoit = WIN32OLE.new('AutoItX3.Control') loop do autoit.ControlClick("Windows Internet Explorer",'', 'OK') autoit.ControlClick("Security Information",'', '&Yes') autoit.ControlClick("Security Alert",'', '&Yes') autoit.ControlClick("Security Warning",'', 'Yes') autoit.ControlClick("Message from webpage",'', 'OK') # other options can be included here sleep 3 end rescue Exception => e puts e end
Next, add the following to your working script:
@pid = Process.create( :app_name => 'ruby popup_closer.rb', :creation_flags => Process::DETACHED_PROCESS ).process_id at_exit{ Process.kill(9,@pid) }
While the script is running, this will continue to check for any popups and click OK. You can always change the options to "No", "Cancel", etc.
If you want to kill the process earlier, remove the last line and just type: Process.kill(9,@pid).
Comments (2)
Aug 12, 2010
David Schulberg says:
I have tried to get the handling of Javascript popups to work with ruby 1.8.6 (2...I have tried to get the handling of Javascript popups to work with ruby 1.8.6 (2010-02-04 patchlevel 398) [i386-mingw32]. However comments in the wiki appear to indicate
that I need to have the earlier version of Ruby ruby186-26.exe installed because the click_no_wait does not work in subsequent versions of Ruby 1.8.
This is a significant issue as I am unable to go back to this earlier version as I find myself unable to install a number of gems that I need for my work when I have ruby186-26.
In particular it seems now that prebuilt native extension gems are not available and when I try to install the gems that I need I get errors:
Building native extensions. This could take a while...
ERROR: While executing gem ... (RuntimeError)
Error instaling linecache-0.43.gem:
ERROR: Failed to build gem native extension.
i.e. native extension gems are not able to be built with that version of Ruby_._
They can be built with the later version of Ruby.
David
P.S. There seem to be some real issues with the compatibility of Ruby and Watir these days that are complicating and jeopardising the ongoing marriage between these two applications.
Aug 13, 2010
Zeljko says:
Please see http://watir.com/support/ to find out how to get support. Not a lot o...Please see http://watir.com/support/ to find out how to get support. Not a lot of people are reading comments.