JavaScript Pop Ups

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). 



Enter labels to add to this page:
Please wait 
Looking for a label? Just start typing.
  1. 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.

  2. 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.