Skip to content
This repository has been archived by the owner on Jun 6, 2018. It is now read-only.

Commit

Permalink
add modal dialog support for IE9. This is a refactor of modal_dialog …
Browse files Browse the repository at this point in the history
…but is backward compatible to IE8. This does deprecate the ability to attach to a modal by :title, but truthfully that's not useful. There should only be one modal dialog active at any one time. If that's necessary you can always use a Watir::Wait method to wait for the right ie.modal_dialog.title to appear.
  • Loading branch information
Hugh McGowan committed Jun 9, 2011
1 parent 766823d commit 87c4266
Show file tree
Hide file tree
Showing 5 changed files with 53 additions and 138 deletions.
9 changes: 1 addition & 8 deletions watir/lib/watir/close_all.rb
Expand Up @@ -23,15 +23,8 @@ def self.close_all_but(except=nil)
# to appear and does not raise exception if no window is found.
# returns true if modal was found and close, otherwise false
def close_modal
begin
original_attach_timeout = IE.attach_timeout
IE.attach_timeout = 0
while self.modal_dialog.exists?(0) do
self.modal_dialog.close
true
rescue NoMatchingWindowFoundException, Wait::TimeoutError
false
ensure
IE.attach_timeout = original_attach_timeout
end
end
end
Expand Down
2 changes: 1 addition & 1 deletion watir/lib/watir/container.rb
Expand Up @@ -209,7 +209,7 @@ def rows
# loaded.

def modal_dialog(how=nil, what=nil)
ModalDialog.new(self, how, what)
ModalDialog.new(self)
end

# This is the main method for accessing a button. Often declared as an <tt><input type = submit></tt> tag.
Expand Down
3 changes: 3 additions & 0 deletions watir/lib/watir/core.rb
Expand Up @@ -28,6 +28,9 @@
require 'watir/link'
require 'watir/html_element'

require 'watir/win32'
require 'watir/modal_dialog'

require 'watir/module'

require 'rautomation'
Expand Down
107 changes: 29 additions & 78 deletions watir/lib/watir/modal_dialog.rb
Expand Up @@ -10,100 +10,33 @@ class ModalDialog
include PageContainer
include Win32

# Return the current window handle
attr_reader :hwnd

def find_modal_from_window
# Use handle of our parent window to see if we have any currently
# enabled popup.
hwnd = @container.hwnd
hwnd_modal = 0
begin
Watir::until_with_timeout do
hwnd_modal, arr = GetWindow.call(hwnd, GW_ENABLEDPOPUP) # GW_ENABLEDPOPUP = 6
hwnd_modal > 0
end
rescue Wait::TimeoutError
return nil
end
if hwnd_modal == hwnd || hwnd_modal == 0
hwnd_modal = nil
end
@hwnd = hwnd_modal
def initialize(container)
set_container container
@modal = ::RAutomation::Window.new(:hwnd=>@container.hwnd).child(:class => 'Internet Explorer_TridentDlgFrame')
end
private :find_modal_from_window

def locate
how = @how
what = @what

case how
when nil
unless find_modal_from_window
raise NoMatchingWindowFoundException,
"Modal Dialog not found. Timeout = #{Watir::IE.attach_timeout}"
end
when :title
case what.class.to_s
# TODO: re-write like WET's so we can select on regular expressions too.
when "String"
begin
Watir::until_with_timeout do
title = "#{what} -- Web Page Dialog"
@hwnd, arr = FindWindowEx.call(0, 0, nil, title)
@hwnd > 0
end
rescue Wait::TimeoutError
raise NoMatchingWindowFoundException,
"Modal Dialog with title #{what} not found. Timeout = #{Watir::IE.attach_timeout}"
end
else
raise ArgumentError, "Title value must be String"
end
else
raise ArgumentError, "Only null and :title methods are supported"
end

intUnknown = 0
begin
Watir::until_with_timeout do
intPointer = " " * 4 # will contain the int value of the IUnknown*
GetUnknown.call(@hwnd, intPointer)
GetUnknown.call(hwnd, intPointer)
intArray = intPointer.unpack('L')
intUnknown = intArray.first
intUnknown > 0
end
rescue Wait::TimeoutError => e
raise NoMatchingWindowFoundException,
"Unable to attach to Modal Window #{what.inspect} after #{e.duration} seconds."
raise NoMatchingWindowFoundException,
"Unable to attach to Modal Window after #{e.duration} seconds."
end

copy_test_config @parent_container
@document = WIN32OLE.connect_unknown(intUnknown)
end

def initialize(container, how, what=nil)
set_container container
@how = how
@what = what
@parent_container = container
# locate our modal dialog's Document object and save it
begin
locate
rescue NoMethodError => e
message =
"IE#modal_dialog not supported with the current version of Ruby (#{RUBY_VERSION}).\n" +
"See http://jira.openqa.org/browse/WTR-2 for details.\n" +
e.message
raise NoMethodError.new(message)
end
end

def document
locate
@document
end

# Return the title of the document
def title
document.title
end
Expand All @@ -117,12 +50,30 @@ def attach_command
end

def wait(no_sleep=false)
sleep 1
if exists?
# do nothing
else
@container.page_container.wait
end
end

# Return true if the modal exists. Mostly this is useful for testing whether
# a modal has closed.
def exists?
Watir::Win32::window_exists? @hwnd
def hwnd
@modal.hwnd
end

def active?
@modal.active?
end

# When checking to see if the modal exists we give it some time to
# find it. So if it does see a modal it returns immediately, otherwise it waits and checks
def exists?(timeout=5)
begin
Watir::Wait.until(timeout) {@modal.exists?}
rescue Watir::Wait::TimeoutError
end
return @modal.exists?
end
alias :exist? :exists?
end
Expand Down
70 changes: 19 additions & 51 deletions watir/unittests/windows/modal_dialog_test.rb
Expand Up @@ -13,25 +13,16 @@ def setup
IE.attach_timeout = 10.0
end

def teardown
if browser
while browser.close_modal do; end
def teardown
if browser
while browser.modal_dialog.exists?(0) do
browser.modal_dialog.close
sleep 0.5
end
end
sleep 0.1
IE.attach_timeout = @original_timeout
end

def assert_no_modals
IE.attach_timeout = 0.2
begin
assert_raises(NoMatchingWindowFoundException) do
browser.modal_dialog
end
ensure
IE.attach_timeout = @original_timeout
end
end


def test_modal_simple_use_case
browser.button(:value, 'Launch Dialog').click_no_wait
modal = browser.modal_dialog(:title, 'Modal Dialog')
Expand Down Expand Up @@ -68,60 +59,37 @@ def test_modal_dialog_use_case_default
modal.text_field(:name, 'modal_text').set('hello')
modal.button(:value, 'Close').click

assert_no_modals
assert !browser.modal_dialog.exists?
assert_equal('hello', browser.text_field(:name, 'modaloutput').value)
end

# Now explicitly supply the :title parameter.
def test_modal_dialog_use_case_title
browser.button(:value, 'Launch Dialog').click_no_wait

modal = browser.modal_dialog(:title, 'Modal Dialog')
assert_not_equal(browser.hwnd, modal.hwnd)

assert_equal('Modal Dialog', modal.title)

assert(modal.text.include?('Enter some text:'))
modal.button(:value, 'Close').click
end

# Now explicitly supply the :title parameter with regexp match
def test_modal_dialog_use_case_title_regexp
assert_raises(ArgumentError){browser.modal_dialog(:title, /dal Dia/)}
end

# Now explicitly supply an invalid "how" value
def test_modal_dialog_use_case_invalid
assert_raise(ArgumentError) { browser.modal_dialog(:esp) }
end

def test_double_modal
browser.button(:value, 'Launch Dialog').click_no_wait
modal1 = browser.modal_dialog
modal1.button(:text, 'Another Modal').click_no_wait
modal2 = modal1.modal_dialog
assert_equal modal2.title, 'Pass Page'
modal2.close
modal1.close
browser.modal_dialog.button(:text, 'Another Modal').click_no_wait
assert_nothing_raised {
Watir::Wait.until {browser.modal_dialog.title == 'Pass Page'}
}
browser.modal_dialog.close
browser.modal_dialog.close
end

def xtest_modal_with_frames
browser.button(:value, 'Launch Dialog').click_no_wait
modal1 = browser.modal_dialog
modal1.button(:value, 'Modal with Frames').click_no_wait
modal2 = browser.modal_dialog
modal2.frame('buttonFrame').button(:value, 'Click Me').click
assert(modal2.frame('buttonFrame').text.include?('PASS'))
assert(modal2.frame('buttonFrame').text.include?('PASS'))
modal2.frame('buttonFrame').button(:value, 'Close Window').click
modal1.close
end

def test_modal_exists
browser.button(:value, 'Launch Dialog').click_no_wait
modal = browser.modal_dialog(:title, 'Modal Dialog')
modal = browser.modal_dialog
assert(modal.exists?)
modal.button(:value, 'Close').click
assert_false(modal.exists?)
end

end

0 comments on commit 87c4266

Please sign in to comment.