Here's the way I've found to control IE popups (asking for  
certificates, asking whether to remember passwords, etc.) on Windows  
Vista with Watir 1.5.1.1166 and nothing else:

1. Just before sending the click that will generate the popup, popen 
() a subprocess ("the watcher").

2. Have the watcher spin, checking for a window with a given title,  
then send the right keys to dismiss the window. After that, create a  
file to signal completion and exit.

3. Have the parent process spin, waiting for that file to be created,  
then continue.

I've not succeeded in doing it a simpler way because:

1. Putting the click() and an @autoit.WinWait in different threads  
always seems to lead to a hang. (I'm guessing I/O is happening when  
Watir is waiting for the click to finish, so the thread that wants to  
WinWait never gets started. Or the WinWait thread causes the click  
thread never to be started.)

2. Windows doesn't support fork() and derivatives, so I can't just  
fork a watcher, click, and wait for the child to terminate.

3. I can't even have the watcher send the "I'm done" message to its  
stdout because the parent hangs reading it, presumably for the same  
reason as threads do.

My question is whether I've missed an easier or better way to do this  
using stock Watir. I'm assuming that if I dug into Win32api, I could  
find the secret to how Windows lets one process create and control  
another, but I find myself strangely without the desire to do so. But  
if someone tells me it's easy...

---------------------------

Here is a sample script that logs in and deals with a demand for a  
digital certificate. Because I want to be cool, I made a little  
Domain! Specific! Language! for talking about popups. In the  
following, it's marked with
# !W!O!W!

require 'watir'
include Watir

at_exit do
   $ie.close
end


class IE
   def after(&block)
     @block = block
     self
   end

   def grab_window(window_title)
     @window_title = window_title
     self
   end

   def and_send(*keys)
     dropping = dropping_name_from(@window_title)
     File.delete(dropping) if File.exist?(dropping)
     commandline = ["/ruby/bin/ruby",
                           "watcher.rb",
                           "'" + @window_title + "'",
                           dropping] +
                           keys
     IO.popen(commandline.join(' '))
     instance_eval(&@block) if @block
     until File.exists?(dropping)
       sleep 1
     end
   end

   private

   def dropping_name_from(title)
     "got-past-" + title.gsub(/\s/, '-')
   end
end

$ie = IE.new
$ie.goto("https://example.com/cmd/logon";)
$ie.text_field(:name, "U").set("marick")
$ie.text_field(:name, "P").set("not the real one")
$ie.after {                                                                     
# !W!O!W!
   button(:name, "action").click
}.grab_window("Choose a digital certificate").
    and_send("{Tab}", "{Space}")

puts "Th-th-th that's all, folks!"
sleep 5  # display final page in all its glory.


====

And here's the watcher script:

require 'watir'

# Do this in JMock style, just because.

class Watcher

   private_class_method :new

   def self.after_seeing(title)
     new(title)
   end

   def initialize(title)
     @autoit = Watir.autoit
     @title = title
   end

   def send(keys)
     @keys = keys
     self
   end

   def and_leave_dropping_in(dropping_file)
     @dropping_file = dropping_file
     do_await_window
     do_send_keys
     do_leave_dropping
     nil
   end

   private

   def do_await_window
     @autoit.WinWait @title, ""
   end

   def do_send_keys
     @keys.each do | key |
       sleep 1  # Just to watch it happen.
       @autoit.Send key
     end
   end

   def do_leave_dropping
     File.open(@dropping_file, "w") do | io |
       io.puts("Finished at #{Time.now}.")
     end
   end
end

if $0 == __FILE__
   title = ARGV[0]
   dropping_file = ARGV[1]
   keys = ARGV[2..-1]
   $stderr.puts title, dropping_file, keys.inspect; $stderr.flush

   Watcher.after_seeing(title).send(keys).
               and_leave_dropping_in(dropping_file)

end



-----
Brian Marick, independent consultant
Mostly on agile methods with a testing slant
www.exampler.com, www.exampler.com/blog


-----
Brian Marick, independent consultant
Mostly on agile methods with a testing slant
www.exampler.com, www.exampler.com/blog


_______________________________________________
Wtr-general mailing list
Wtr-general@rubyforge.org
http://rubyforge.org/mailman/listinfo/wtr-general

Reply via email to