Friday, January 28, 2011

How to handle JavaScripts popups?

These JavaScript popups cause trouble as they interrupt the page from fully loading, causing Watir to wait (as the page is waiting), which means the next command in your script will never be reached. Previous work arounds to this were to use watirs built in click_no_wait, but I have that to be extremely temperamental and did not always work depending on which element the click was being performed on.

The new and improved method is to have a completely separate process that runs in the background and is continually checking for JavaScript pop ups. AutoIt commands are used to first locate the pop-up and then depending on what text or title is present in the pop up and different action can be performed on it. Unfortunately the same code cannot be used for both IE and FF due to the fact that the AutoIt controls cannot perform the same actions on IE pop-ups as it can on FF pop-ups. I have included the code for both below:

clickPopupsIE.rb

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')
sleep 1
end
rescue Exception > e
puts e
end

clickPopupsFF.rb

require 'win32ole'
websiteName = "w3schools.com"
begin
autoit = WIN32OLE.new('AutoItX3.Control')
loop do
autoit.winActivate("The page at http://#{websiteName} says:")
autoit.Send("{ENTER}") if(autoit.WinWait("The page at http://#{websiteName} says:",'',2) == 1)
end
rescue Exception => e
puts e
end


These two scripts can then be called from any of your other Watir scripts using the following two functions scripts:

require 'win32/process'
def callPopupKillerFF
$pid = Process.create(:app_name => 'ruby clickPopupsFF.rb', :creation_flags => Process::DETACHED_PROCESS).process_id
end

def callPopupKillerIE
$pid = Process.create(:app_name => 'ruby clickPopupsIE.rb', :creation_flags => Process::DETACHED_PROCESS).process_id
end

def killPopupKiller
Process.kill(9,$pid)
end


As you can see above you do need to require one more ruby gem, ‘win32/process’, this is used to run the popup clicker as a separate process that runs in the background. Once you have those functions in place you can simply call:


callPopupKillerIE #Starts the IE popup killer
#Some watir code that results in a popup#
killPopupKiller #Kills the popup killer process, so that you do not end up with 5 of them running!

2 comments: