vapir-ie 1.7.0.rc1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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
|