vapir-ie 1.7.0.rc1
Sign up to get free protection for your applications and to get access to all the features.
- data/History.txt +437 -0
- data/LICENSE.txt +41 -0
- data/README.txt +0 -0
- data/lib/vapir-ie.rb +44 -0
- data/lib/vapir-ie/AutoItX.chm +0 -0
- data/lib/vapir-ie/AutoItX3.dll +0 -0
- data/lib/vapir-ie/IEDialog/Release/IEDialog.dll +0 -0
- data/lib/vapir-ie/autoit.rb +13 -0
- data/lib/vapir-ie/close_all.rb +32 -0
- data/lib/vapir-ie/container.rb +51 -0
- data/lib/vapir-ie/element.rb +376 -0
- data/lib/vapir-ie/elements.rb +9 -0
- data/lib/vapir-ie/form.rb +8 -0
- data/lib/vapir-ie/frame.rb +24 -0
- data/lib/vapir-ie/ie-class.rb +880 -0
- data/lib/vapir-ie/ie-process.rb +60 -0
- data/lib/vapir-ie/image.rb +59 -0
- data/lib/vapir-ie/input_elements.rb +158 -0
- data/lib/vapir-ie/link.rb +23 -0
- data/lib/vapir-ie/logger.rb +21 -0
- data/lib/vapir-ie/modal_dialog.rb +224 -0
- data/lib/vapir-ie/non_control_elements.rb +77 -0
- data/lib/vapir-ie/page_container.rb +203 -0
- data/lib/vapir-ie/process.rb +22 -0
- data/lib/vapir-ie/screen_capture.rb +7 -0
- data/lib/vapir-ie/scripts/select_file.rb +79 -0
- data/lib/vapir-ie/table.rb +33 -0
- data/lib/vapir-ie/version.rb +5 -0
- data/lib/vapir-ie/win32ole.rb +45 -0
- data/lib/vapir-ie/win32ole/win32ole.so +0 -0
- data/lib/vapir/ie.rb +1 -0
- metadata +130 -0
@@ -0,0 +1,60 @@
|
|
1
|
+
require 'win32/process'
|
2
|
+
require 'vapir-ie/ie-class'
|
3
|
+
|
4
|
+
module Vapir
|
5
|
+
class IE
|
6
|
+
# the version string, from the registry key HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Internet Explorer\Version
|
7
|
+
def self.version
|
8
|
+
@@ie_version ||= begin
|
9
|
+
require 'win32/registry'
|
10
|
+
::Win32::Registry::HKEY_LOCAL_MACHINE.open("SOFTWARE\\Microsoft\\Internet Explorer") do |ie_key|
|
11
|
+
ie_key.read('Version').last
|
12
|
+
end
|
13
|
+
# OR: ::WIN32OLE.new("WScript.Shell").RegRead("HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Internet Explorer\\Version")
|
14
|
+
end
|
15
|
+
end
|
16
|
+
# the version string divided into its numeric parts returned as an array of integers
|
17
|
+
def self.version_parts
|
18
|
+
@@ie_version_parts ||= IE.version.split('.').map{|part| part.to_i }
|
19
|
+
end
|
20
|
+
class Process
|
21
|
+
# Vapir::IE::Process.start is called by Vapir::IE.new_process and does not start a new process correctly in IE8.
|
22
|
+
# Calling IE8 with the -nomerge option correctly starts a new process, so call Process.create with this option if
|
23
|
+
# IE's version is 8
|
24
|
+
def self.start
|
25
|
+
program_files = ENV['ProgramFiles'] || "c:\\Program Files"
|
26
|
+
startup_command = "#{program_files}\\Internet Explorer\\iexplore.exe"
|
27
|
+
startup_command << " -nomerge" if ::Vapir::IE.version_parts.first==8
|
28
|
+
# maybe raise an error here if it's > 8, as not-yet-supported? who knows what incompatibilities the future will hold
|
29
|
+
process_info = ::Process.create('app_name' => "#{startup_command} about:blank")
|
30
|
+
process_id = process_info.process_id
|
31
|
+
new process_id
|
32
|
+
end
|
33
|
+
|
34
|
+
def initialize process_id
|
35
|
+
@process_id = process_id
|
36
|
+
end
|
37
|
+
attr_reader :process_id
|
38
|
+
|
39
|
+
def window
|
40
|
+
Waiter.wait_until do
|
41
|
+
IE.each do | ie |
|
42
|
+
window = ie.ie
|
43
|
+
hwnd = ie.hwnd
|
44
|
+
process_id = Process.process_id_from_hwnd hwnd
|
45
|
+
return window if process_id == @process_id
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
# Returns the process id for the specifed hWnd.
|
51
|
+
def self.process_id_from_hwnd hwnd
|
52
|
+
pid_info = ' ' * 32
|
53
|
+
Win32API.new('user32', 'GetWindowThreadProcessId', 'ip', 'i').
|
54
|
+
call(hwnd, pid_info)
|
55
|
+
process_id = pid_info.unpack("L")[0]
|
56
|
+
end
|
57
|
+
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
@@ -0,0 +1,59 @@
|
|
1
|
+
require 'vapir-ie/element'
|
2
|
+
require 'vapir-common/elements/elements'
|
3
|
+
|
4
|
+
module Vapir
|
5
|
+
|
6
|
+
# This class is the means of accessing an image on a page.
|
7
|
+
# Normally a user would not need to create this object as it is returned by the Vapir::Container#image method
|
8
|
+
#
|
9
|
+
# many of the methods available to this object are inherited from the Element class
|
10
|
+
#
|
11
|
+
class IE::Image < IE::Element
|
12
|
+
include Vapir::Image
|
13
|
+
|
14
|
+
dom_attr :fileSize => :file_size
|
15
|
+
dom_attr :fileCreatedDate => :file_created_date
|
16
|
+
|
17
|
+
# This method attempts to find out if the image was actually loaded by the web browser.
|
18
|
+
# If the image was not loaded, the browser is unable to determine some of the properties.
|
19
|
+
# We look for these missing properties to see if the image is really there or not.
|
20
|
+
# If the Disk cache is full (tools menu -> Internet options -> Temporary Internet Files), it may produce incorrect responses.
|
21
|
+
def loaded?
|
22
|
+
assert_exists do
|
23
|
+
!(element_object.fileCreatedDate == "" and element_object.fileSize.to_i == -1)
|
24
|
+
end
|
25
|
+
end
|
26
|
+
alias_deprecated :hasLoaded?, :loaded?
|
27
|
+
|
28
|
+
# This method saves the image to the file path that is given. The
|
29
|
+
# path must be in windows format (c:\\dirname\\somename.gif). This method
|
30
|
+
# will not overwrite a previously existing image. If an image already
|
31
|
+
# exists at the given path then a dialog will be displayed prompting
|
32
|
+
# for overwrite.
|
33
|
+
# Raises a VapirException if AutoIt is not correctly installed
|
34
|
+
# path - directory path and file name of where image should be saved
|
35
|
+
def save(path)
|
36
|
+
# TODO: FIX
|
37
|
+
require 'vapir-ie/windowhelper'
|
38
|
+
WindowHelper.check_autoit_installed
|
39
|
+
@container.goto(src)
|
40
|
+
begin
|
41
|
+
thrd = fill_save_image_dialog(path)
|
42
|
+
@container.document.execCommand("SaveAs")
|
43
|
+
thrd.join(5)
|
44
|
+
ensure
|
45
|
+
@container.back
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
def fill_save_image_dialog(path)
|
50
|
+
raise NotImplementedError
|
51
|
+
#todo: FIX
|
52
|
+
Thread.new do
|
53
|
+
system("ruby -e \"require 'win32ole'; @autoit=WIN32OLE.new('AutoItX3.Control'); waitresult=@autoit.WinWait 'Save Picture', '', 15; if waitresult == 1\" -e \"@autoit.ControlSetText 'Save Picture', '', '1148', '#{path}'; @autoit.ControlSend 'Save Picture', '', '1', '{ENTER}';\" -e \"end\"")
|
54
|
+
end
|
55
|
+
end
|
56
|
+
private :fill_save_image_dialog
|
57
|
+
end
|
58
|
+
|
59
|
+
end
|
@@ -0,0 +1,158 @@
|
|
1
|
+
require 'vapir-ie/element'
|
2
|
+
require 'vapir-common/elements/elements'
|
3
|
+
|
4
|
+
module Vapir
|
5
|
+
|
6
|
+
class IE::InputElement < IE::Element
|
7
|
+
include InputElement
|
8
|
+
end
|
9
|
+
|
10
|
+
#
|
11
|
+
# Input: Select
|
12
|
+
#
|
13
|
+
|
14
|
+
# This class is the way in which select boxes are manipulated.
|
15
|
+
# Normally a user would not need to create this object as it is returned by the Vapir::Container#select_list method
|
16
|
+
class IE::SelectList < IE::InputElement
|
17
|
+
include SelectList
|
18
|
+
end
|
19
|
+
|
20
|
+
# An item in a select list
|
21
|
+
class IE::Option < IE::Element
|
22
|
+
include Option
|
23
|
+
end
|
24
|
+
|
25
|
+
#
|
26
|
+
# Input: Button
|
27
|
+
#
|
28
|
+
|
29
|
+
# Returned by the Vapir::Container#button method
|
30
|
+
class IE::Button < IE::InputElement
|
31
|
+
include Button
|
32
|
+
dom_attr :value => :caption
|
33
|
+
end
|
34
|
+
|
35
|
+
#
|
36
|
+
# Input: Text
|
37
|
+
#
|
38
|
+
|
39
|
+
# This class is the main class for Text Fields
|
40
|
+
# Normally a user would not need to create this object as it is returned by the Vapir::Container#text_field method
|
41
|
+
class IE::TextField < IE::InputElement
|
42
|
+
include TextField
|
43
|
+
# def_wrap_guard :size
|
44
|
+
|
45
|
+
# Returns true if the text field contents is matches the specified target,
|
46
|
+
# which can be either a string or a regular expression.
|
47
|
+
# Raises UnknownObjectException if the object can't be found
|
48
|
+
#
|
49
|
+
# TODO: move to common
|
50
|
+
def verify_contains(target) # FIXME: verify_contains should have same name and semantics as IE#contains_text (prolly make this work for all elements)
|
51
|
+
assert_exists do
|
52
|
+
if target.kind_of? String
|
53
|
+
return true if self.value == target
|
54
|
+
elsif target.kind_of? Regexp
|
55
|
+
return true if self.value.match(target) != nil
|
56
|
+
end
|
57
|
+
return false
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
# Drag the entire contents of the text field to another text field
|
62
|
+
# 19 Jan 2005 - It is added as prototype functionality, and may change
|
63
|
+
# * destination_how - symbol, :id, :name how we identify the drop target
|
64
|
+
# * destination_what - string or regular expression, the name, id, etc of the text field that will be the drop target
|
65
|
+
def drag_contents_to(destination_how, destination_what)
|
66
|
+
assert_exists do
|
67
|
+
destination = @container.text_field!(destination_how, destination_what)
|
68
|
+
|
69
|
+
element_object.focus
|
70
|
+
element_object.select
|
71
|
+
value = self.value
|
72
|
+
|
73
|
+
with_highlight do
|
74
|
+
fire_event("onSelect")
|
75
|
+
fire_event("ondragstart")
|
76
|
+
fire_event("ondrag")
|
77
|
+
destination.with_highlight do
|
78
|
+
destination.fire_event("onDragEnter")
|
79
|
+
destination.fire_event("onDragOver")
|
80
|
+
destination.fire_event("ondrop")
|
81
|
+
destination.value = destination.value + value.to_s
|
82
|
+
end
|
83
|
+
fire_event("ondragend")
|
84
|
+
self.value = ""
|
85
|
+
end
|
86
|
+
|
87
|
+
end
|
88
|
+
end
|
89
|
+
alias_deprecated :dragContentsTo, :drag_contents_to
|
90
|
+
|
91
|
+
def requires_typing
|
92
|
+
@type_keys = true
|
93
|
+
self
|
94
|
+
end
|
95
|
+
def abhors_typing
|
96
|
+
@type_keys = false
|
97
|
+
self
|
98
|
+
end
|
99
|
+
end
|
100
|
+
|
101
|
+
# this class can be used to access hidden field objects
|
102
|
+
# Normally a user would not need to create this object as it is returned by the Vapir::Container#hidden method
|
103
|
+
class IE::Hidden < IE::TextField
|
104
|
+
include Hidden
|
105
|
+
end
|
106
|
+
|
107
|
+
# For fields that accept file uploads
|
108
|
+
# Windows dialog is opened and handled by WinWindow (see scripts/select_file.rb), launched in a new process.
|
109
|
+
class IE::FileField < IE::InputElement
|
110
|
+
include FileField
|
111
|
+
|
112
|
+
# set the file location in the Choose file dialog
|
113
|
+
def set(file_path)
|
114
|
+
assert_exists do
|
115
|
+
# it would be nice to do a click_no_wait and then enter the select file dialog information
|
116
|
+
# in the same thread, but that won't work here, because #click_no_wait runs in a javascript
|
117
|
+
# setTimeout, and javascript calling to a file input's .click() method doesn't work. it appears
|
118
|
+
# to work until you submit the form, at which point it says access is denied. so, the click has
|
119
|
+
# to be done via WIN32OLE, but it doesn't return until the file field is set, so we need two
|
120
|
+
# ruby processes (since WIN32OLE blocking blocks all ruby threads).
|
121
|
+
# since locating this element is a much more complicated task than locating the enabled_popup
|
122
|
+
# of this browser, this process will handle the former, and we'll spawn another to do the
|
123
|
+
# latter.
|
124
|
+
require 'win32/process'
|
125
|
+
require 'vapir-common/win_window'
|
126
|
+
rubyw_exe= File.join(Config::CONFIG['bindir'], 'rubyw')
|
127
|
+
error_file_name=File.expand_path(File.join(File.dirname(__FILE__), 'scripts', 'select_file_error_status.marshal_dump'))
|
128
|
+
select_file_script=File.expand_path(File.join(File.dirname(__FILE__), 'scripts', 'select_file.rb'))
|
129
|
+
command_line=rubyw_exe+[select_file_script, browser.hwnd.to_s, file_path, error_file_name].map{|arg| " \"#{arg.gsub("/", "\\")}\""}.join('')
|
130
|
+
# TODO/FIX: the above method of escaping seems to have issues with trailing slashes.
|
131
|
+
select_file_process=::Process.create('command_line' => command_line)
|
132
|
+
|
133
|
+
click
|
134
|
+
|
135
|
+
if ::Waiter.try_for(2, :exception => nil) { File.exists?(error_file_name) } # wait around a moment for the script to finish writing - #click returns before that script exits
|
136
|
+
marshaled_error=File.read(error_file_name)
|
137
|
+
error=Marshal.load(marshaled_error)
|
138
|
+
error[:backtrace]+= caller(0)
|
139
|
+
File.delete(error_file_name)
|
140
|
+
raise error[:class], error[:message], error[:backtrace]
|
141
|
+
end
|
142
|
+
return file_path
|
143
|
+
# TODO/FIX: figure out what events ought to be fired here - onchange, maybe others
|
144
|
+
end
|
145
|
+
end
|
146
|
+
end
|
147
|
+
|
148
|
+
# This class is the watir representation of a radio button.
|
149
|
+
class IE::Radio < IE::InputElement
|
150
|
+
include Radio
|
151
|
+
end
|
152
|
+
|
153
|
+
# This class is the watir representation of a check box.
|
154
|
+
class IE::CheckBox < IE::InputElement
|
155
|
+
include CheckBox
|
156
|
+
end
|
157
|
+
|
158
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
require 'vapir-ie/element'
|
2
|
+
require 'vapir-common/elements/elements'
|
3
|
+
|
4
|
+
module Vapir
|
5
|
+
|
6
|
+
# This class is the means of accessing a link on a page
|
7
|
+
# Normally a user would not need to create this object as it is returned by the Vapir::Container#link method
|
8
|
+
# many of the methods available to this object are inherited from the Element class
|
9
|
+
#
|
10
|
+
class IE::Link < IE::Element
|
11
|
+
include Vapir::Link
|
12
|
+
|
13
|
+
# if an image is used as part of the link, this will return true
|
14
|
+
def link_has_image
|
15
|
+
images.length > 0
|
16
|
+
end
|
17
|
+
|
18
|
+
def src
|
19
|
+
raise NotImplementedError, "Link#src is gone. use Link#images to get a collection of images from which you may get the #src attribute"
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
require 'logger'
|
2
|
+
|
3
|
+
module Vapir
|
4
|
+
class VapirLogger < Logger
|
5
|
+
def initialize(filName, logsToKeep, maxLogSize)
|
6
|
+
super(filName, logsToKeep, maxLogSize)
|
7
|
+
self.level = Logger::DEBUG
|
8
|
+
self.datetime_format = "%d-%b-%Y %H:%M:%S"
|
9
|
+
self.debug("Vapir starting")
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
class DefaultLogger < Logger
|
14
|
+
def initialize
|
15
|
+
super(STDERR)
|
16
|
+
self.level = Logger::WARN
|
17
|
+
self.datetime_format = "%d-%b-%Y %H:%M:%S"
|
18
|
+
self.info "Log started"
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
@@ -0,0 +1,224 @@
|
|
1
|
+
require 'vapir-common/win_window'
|
2
|
+
require 'vapir-common/modal_dialog'
|
3
|
+
require 'vapir-ie/page_container'
|
4
|
+
require 'Win32API'
|
5
|
+
|
6
|
+
module Vapir
|
7
|
+
class IE::ModalDialog
|
8
|
+
include Vapir::ModalDialog
|
9
|
+
def locate
|
10
|
+
@modal_window=@browser.win_window.enabled_popup
|
11
|
+
end
|
12
|
+
|
13
|
+
def exists?
|
14
|
+
@modal_window && @modal_window.exists?
|
15
|
+
end
|
16
|
+
|
17
|
+
def text
|
18
|
+
assert_exists
|
19
|
+
@modal_window.children.select{|child| child.class_name.downcase=='static' && child.text!=''}.map{|c| c.text }.join(' ')
|
20
|
+
end
|
21
|
+
|
22
|
+
def set_text_field(value)
|
23
|
+
assert_exists
|
24
|
+
edit_field=@modal_window.children.detect{|child| child.class_name=='Edit'} || (raise "No Edit field in the popup!")
|
25
|
+
edit_field.send_set_text!(value)
|
26
|
+
value
|
27
|
+
end
|
28
|
+
|
29
|
+
def click_button(button_text, options={})
|
30
|
+
assert_exists
|
31
|
+
options=handle_options(options, :timeout => ModalDialog::DEFAULT_TIMEOUT)
|
32
|
+
@modal_window.click_child_button_try_for!(button_text, options[:timeout])
|
33
|
+
end
|
34
|
+
|
35
|
+
def close
|
36
|
+
if (document=IE::ModalDialogDocument.new(self, :error => false, :timeout => 0)) && document.exists?
|
37
|
+
document.close
|
38
|
+
else
|
39
|
+
@modal_window.send_close!
|
40
|
+
end
|
41
|
+
::Waiter.try_for(ModalDialog::DEFAULT_TIMEOUT, :exception => Vapir::Exception::WindowException.new("The modal window failed to close")) do
|
42
|
+
!exists?
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
def hwnd
|
47
|
+
assert_exists
|
48
|
+
@modal_window.hwnd
|
49
|
+
end
|
50
|
+
def win_window
|
51
|
+
@modal_window
|
52
|
+
end
|
53
|
+
|
54
|
+
def document
|
55
|
+
assert_exists
|
56
|
+
IE::ModalDialogDocument.new(self)
|
57
|
+
end
|
58
|
+
end
|
59
|
+
class IE::ModalDialogDocument
|
60
|
+
include IE::PageContainer
|
61
|
+
@@iedialog_file = (File.expand_path(File.dirname(__FILE__) + '/..') + "/vapir-ie/IEDialog/Release/IEDialog.dll").gsub('/', '\\')
|
62
|
+
|
63
|
+
GetUnknown = Win32API.new(@@iedialog_file, 'GetUnknown', ['l', 'p'], 'v')
|
64
|
+
def initialize(containing_modal_dialog, options={})
|
65
|
+
options=handle_options(options, :timeout => ModalDialog::DEFAULT_TIMEOUT, :error => true)
|
66
|
+
@containing_modal_dialog=containing_modal_dialog
|
67
|
+
|
68
|
+
intUnknown = nil
|
69
|
+
::Waiter.try_for(options[:timeout], :exception => (options[:error] && "Unable to attach to Modal Window after #{options[:timeout]} seconds.")) do
|
70
|
+
intPointer = [0].pack("L") # will contain the int value of the IUnknown*
|
71
|
+
GetUnknown.call(@containing_modal_dialog.hwnd, intPointer)
|
72
|
+
intArray = intPointer.unpack('L')
|
73
|
+
intUnknown = intArray.first
|
74
|
+
intUnknown > 0
|
75
|
+
end
|
76
|
+
if intUnknown && intUnknown > 0
|
77
|
+
@document_object = WIN32OLE.connect_unknown(intUnknown)
|
78
|
+
end
|
79
|
+
end
|
80
|
+
attr_reader :containing_modal_dialog
|
81
|
+
attr_reader :document_object
|
82
|
+
def locate!(options={})
|
83
|
+
exists? || raise(Vapir::Exception::NoMatchingWindowFoundException, "The modal dialog seems to have stopped existing.")
|
84
|
+
end
|
85
|
+
|
86
|
+
def exists?
|
87
|
+
# todo/fix: will the document object change / become invalid / need to be relocated?
|
88
|
+
@document_object && @containing_modal_dialog.exists?
|
89
|
+
end
|
90
|
+
|
91
|
+
# this looks for a modal dialog on this modal dialog. but really it's modal to the same browser window
|
92
|
+
# that this is modal to, so we will check for the modal on the browser, see if it isn't the same as our
|
93
|
+
# self, and return it if so.
|
94
|
+
def modal_dialog(options={})
|
95
|
+
::Waiter.try_for(ModalDialog::DEFAULT_TIMEOUT,
|
96
|
+
:exception => NoMatchingWindowFoundException.new("No other modal dialog was found on the browser."),
|
97
|
+
:condition => proc{|md| md.hwnd != containing_modal_dialog.hwnd }
|
98
|
+
) do
|
99
|
+
modal_dialog=containing_modal_dialog.browser.modal_dialog(options)
|
100
|
+
end
|
101
|
+
end
|
102
|
+
end
|
103
|
+
end
|
104
|
+
=begin
|
105
|
+
module Watir
|
106
|
+
class IE::ModalDialog
|
107
|
+
include IE::Container
|
108
|
+
include IE::PageContainer
|
109
|
+
include Win32
|
110
|
+
|
111
|
+
# Return the current window handle
|
112
|
+
attr_reader :hwnd
|
113
|
+
|
114
|
+
def find_modal_from_window
|
115
|
+
# Use handle of our parent window to see if we have any currently
|
116
|
+
# enabled popup.
|
117
|
+
hwnd = @container.hwnd
|
118
|
+
hwnd_modal = 0
|
119
|
+
begin
|
120
|
+
Watir::until_with_timeout do
|
121
|
+
hwnd_modal, arr = GetWindow.call(hwnd, GW_ENABLEDPOPUP) # GW_ENABLEDPOPUP = 6
|
122
|
+
hwnd_modal > 0
|
123
|
+
end
|
124
|
+
rescue TimeOutException
|
125
|
+
return nil
|
126
|
+
end
|
127
|
+
if hwnd_modal == hwnd || hwnd_modal == 0
|
128
|
+
hwnd_modal = nil
|
129
|
+
end
|
130
|
+
@hwnd = hwnd_modal
|
131
|
+
end
|
132
|
+
private :find_modal_from_window
|
133
|
+
|
134
|
+
def locate
|
135
|
+
how = @how
|
136
|
+
what = @what
|
137
|
+
|
138
|
+
case how
|
139
|
+
when nil
|
140
|
+
unless find_modal_from_window
|
141
|
+
raise NoMatchingWindowFoundException,
|
142
|
+
"Modal Dialog not found. Timeout = #{Watir::IE.attach_timeout}"
|
143
|
+
end
|
144
|
+
when :title
|
145
|
+
case what.class.to_s
|
146
|
+
# TODO: re-write like WET's so we can select on regular expressions too.
|
147
|
+
when "String"
|
148
|
+
begin
|
149
|
+
Watir::until_with_timeout do
|
150
|
+
title = "#{what} -- Web Page Dialog"
|
151
|
+
@hwnd, arr = FindWindowEx.call(0, 0, nil, title)
|
152
|
+
@hwnd > 0
|
153
|
+
end
|
154
|
+
rescue TimeOutException
|
155
|
+
raise NoMatchingWindowFoundException,
|
156
|
+
"Modal Dialog with title #{what} not found. Timeout = #{Watir::IE.attach_timeout}"
|
157
|
+
end
|
158
|
+
else
|
159
|
+
raise ArgumentError, "Title value must be String"
|
160
|
+
end
|
161
|
+
else
|
162
|
+
raise ArgumentError, "Only null and :title methods are supported"
|
163
|
+
end
|
164
|
+
|
165
|
+
intUnknown = 0
|
166
|
+
begin
|
167
|
+
Watir::until_with_timeout do
|
168
|
+
intPointer = " " * 4 # will contain the int value of the IUnknown*
|
169
|
+
GetUnknown.call(@hwnd, intPointer)
|
170
|
+
intArray = intPointer.unpack('L')
|
171
|
+
intUnknown = intArray.first
|
172
|
+
intUnknown > 0
|
173
|
+
end
|
174
|
+
rescue TimeOutException => e
|
175
|
+
raise NoMatchingWindowFoundException,
|
176
|
+
"Unable to attach to Modal Window #{what.inspect} after #{e.duration} seconds."
|
177
|
+
end
|
178
|
+
|
179
|
+
copy_test_config @parent_container
|
180
|
+
@document = WIN32OLE.connect_unknown(intUnknown)
|
181
|
+
end
|
182
|
+
|
183
|
+
def initialize(container, how, what=nil)
|
184
|
+
set_container container
|
185
|
+
@how = how
|
186
|
+
@what = what
|
187
|
+
@parent_container = container
|
188
|
+
# locate our modal dialog's Document object and save it
|
189
|
+
begin
|
190
|
+
locate
|
191
|
+
rescue NoMethodError => e
|
192
|
+
message =
|
193
|
+
"IE#modal_dialog not supported with the current version of Ruby (#{RUBY_VERSION}).\n" +
|
194
|
+
"See http://jira.openqa.org/browse/WTR-2 for details.\n" +
|
195
|
+
e.message
|
196
|
+
raise NoMethodError.new(message)
|
197
|
+
end
|
198
|
+
end
|
199
|
+
|
200
|
+
def document
|
201
|
+
@document
|
202
|
+
end
|
203
|
+
|
204
|
+
# Return the title of the document
|
205
|
+
def title
|
206
|
+
document.title
|
207
|
+
end
|
208
|
+
|
209
|
+
def attach_command
|
210
|
+
"Watir::IE.find(:hwnd, #{@container.hwnd}).modal_dialog"
|
211
|
+
end
|
212
|
+
|
213
|
+
def wait(options={})
|
214
|
+
end
|
215
|
+
|
216
|
+
# Return true if the modal exists. Mostly this is useful for testing whether
|
217
|
+
# a modal has closed.
|
218
|
+
def exists?
|
219
|
+
Watir::Win32::window_exists? @hwnd
|
220
|
+
end
|
221
|
+
alias :exist? :exists?
|
222
|
+
end
|
223
|
+
end
|
224
|
+
=end
|