watir-classic 3.7.0 → 4.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.gitignore +2 -0
- data/CHANGES +6 -0
- data/Rakefile +2 -0
- data/VERSION +1 -1
- data/lib/watir-classic.rb +36 -3
- data/lib/watir-classic/browser.rb +613 -115
- data/lib/watir-classic/{ie-process.rb → browser_process.rb} +4 -4
- data/lib/watir-classic/cookies.rb +1 -1
- data/lib/watir-classic/element.rb +2 -2
- data/lib/watir-classic/frame.rb +1 -1
- data/lib/watir-classic/ie_deprecated.rb +5 -0
- data/lib/watir-classic/modal_dialog.rb +1 -1
- data/lib/watir-classic/process.rb +1 -1
- data/lib/watir-classic/screenshot.rb +1 -1
- data/lib/watir-classic/window.rb +3 -3
- data/lib/watir-classic/xpath_locator.rb +2 -2
- data/spec/implementation.rb +1 -1
- data/watir-classic.gemspec +1 -1
- metadata +19 -24
- data/Gemfile.lock +0 -79
- data/lib/watir-classic/browsers.rb +0 -7
- data/lib/watir-classic/core.rb +0 -40
- data/lib/watir-classic/ie-class.rb +0 -664
- data/lib/watir-classic/ie.rb +0 -5
- data/lib/watir-classic/options.rb +0 -51
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 9b48648a4afcf9526da12f6baf012a4f0fec8411
|
4
|
+
data.tar.gz: 70def43f23d469fbb1de955b8112c6ce7d4e7a11
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 7980313c5a552ed151618b593bc1742d26c7918241a2fac62871fd8ef0b7f0ce593e5bd02d3953feeb0a68411155ea85bd4059fdefd94363e2dca8a4bbdc69dc
|
7
|
+
data.tar.gz: d89a17e83ebf2e1ae901e89808c1b6ceb9f4551089663a263a45e7a38da368af0ad0a4bcf027879ddf6eccb8e423b8e6bec8eddf72f8e25dd8c8861363e6eb09
|
data/CHANGES
CHANGED
@@ -1,3 +1,9 @@
|
|
1
|
+
== 4.0.0 - 2013/10/05
|
2
|
+
|
3
|
+
* Browser#add_checker also accepts block instead of a proc object.
|
4
|
+
* Browser#initialize suppresses window only when actual "true" value is given as an argument.
|
5
|
+
* Rename Watir::IE to Watir::Browser. Closes #47 and #53.
|
6
|
+
|
1
7
|
== 3.7.0 - 2013/05/10
|
2
8
|
|
3
9
|
* Add #required? method for input elements.
|
data/Rakefile
CHANGED
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
|
1
|
+
4.0.0
|
data/lib/watir-classic.rb
CHANGED
@@ -1,8 +1,41 @@
|
|
1
|
+
require 'timeout'
|
2
|
+
require 'multi_json'
|
3
|
+
require 'rautomation'
|
4
|
+
|
1
5
|
require 'watir-classic/version'
|
2
|
-
require 'watir-classic/
|
3
|
-
require 'watir-classic/wait_helper'
|
4
|
-
require 'watir-classic/element_extensions'
|
6
|
+
require 'watir-classic/win32ole'
|
5
7
|
require 'watir-classic/util'
|
6
8
|
require 'watir-classic/exceptions'
|
7
9
|
require 'watir-classic/matches'
|
10
|
+
require 'watir-classic/wait'
|
11
|
+
require 'watir-classic/wait_helper'
|
12
|
+
require 'watir-classic/element_extensions'
|
13
|
+
require 'watir-classic/container'
|
14
|
+
require 'watir-classic/xpath_locator'
|
15
|
+
require 'watir-classic/locator'
|
16
|
+
require 'watir-classic/page-container'
|
17
|
+
require 'watir-classic/browser_process'
|
18
|
+
require 'watir-classic/screenshot'
|
8
19
|
require 'watir-classic/browser'
|
20
|
+
require 'watir-classic/drag_and_drop_helper'
|
21
|
+
require 'watir-classic/element'
|
22
|
+
require 'watir-classic/element_collection'
|
23
|
+
require 'watir-classic/form'
|
24
|
+
require 'watir-classic/frame'
|
25
|
+
require 'watir-classic/input_elements'
|
26
|
+
require 'watir-classic/non_control_elements'
|
27
|
+
require 'watir-classic/table'
|
28
|
+
require 'watir-classic/image'
|
29
|
+
require 'watir-classic/link'
|
30
|
+
require 'watir-classic/window'
|
31
|
+
require 'watir-classic/cookies'
|
32
|
+
require 'watir-classic/win32'
|
33
|
+
require 'watir-classic/modal_dialog'
|
34
|
+
require 'watir-classic/module'
|
35
|
+
require 'watir-classic/dialogs/file_field'
|
36
|
+
require 'watir-classic/dialogs/alert'
|
37
|
+
require 'watir-classic/supported_elements'
|
38
|
+
|
39
|
+
module Watir
|
40
|
+
autoload :IE, File.expand_path("watir-classic/ie_deprecated", File.dirname(__FILE__))
|
41
|
+
end
|
@@ -1,60 +1,83 @@
|
|
1
|
-
require 'watir-classic/options'
|
2
1
|
module Watir
|
3
|
-
|
4
|
-
|
2
|
+
# Main browser class.
|
3
|
+
class Browser
|
4
|
+
include WaitHelper
|
5
|
+
include Exception
|
6
|
+
include Container
|
7
|
+
include PageContainer
|
5
8
|
|
6
|
-
|
7
|
-
|
9
|
+
class << self
|
10
|
+
# Maximum number of seconds to wait when attaching to a window
|
11
|
+
attr_writer :attach_timeout
|
8
12
|
|
9
|
-
|
10
|
-
|
11
|
-
|
13
|
+
def attach_timeout
|
14
|
+
@attach_timeout ||= 2
|
15
|
+
end
|
12
16
|
|
13
|
-
|
17
|
+
# Return the options used when creating new instances of {Browser}.
|
18
|
+
# BUG: this interface invites misunderstanding/misuse such as Browser.options[:speed] = :zippy]
|
19
|
+
def options
|
20
|
+
{:speed => self.speed, :visible => self.visible, :attach_timeout => self.attach_timeout}
|
21
|
+
end
|
14
22
|
|
15
|
-
|
23
|
+
# set values for options used when creating new instances of {Browser}.
|
24
|
+
def set_options options
|
25
|
+
options.each do |name, value|
|
26
|
+
send "#{name}=", value
|
27
|
+
end
|
28
|
+
end
|
16
29
|
|
17
|
-
|
30
|
+
# The speed in which browser will type keys etc. Possible values are
|
31
|
+
# :slow (default), :fast and :zippy.
|
32
|
+
attr_writer :speed
|
18
33
|
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
browser.text_field(:name => 'q').set 'pickaxe'
|
23
|
-
browser.button(:name => 'btnG').click
|
24
|
-
if browser.text.include? 'Programming Ruby'
|
25
|
-
puts 'Text was found'
|
26
|
-
else
|
27
|
-
puts 'Text was not found'
|
28
|
-
end
|
34
|
+
def speed
|
35
|
+
@speed ||= :slow
|
36
|
+
end
|
29
37
|
|
30
|
-
|
31
|
-
|
32
|
-
class Browser
|
33
|
-
# @private
|
34
|
-
@@browser_classes = {}
|
38
|
+
# Set browser window to visible or hidden. Defaults to true.
|
39
|
+
attr_writer :visible
|
35
40
|
|
36
|
-
|
37
|
-
|
41
|
+
def visible
|
42
|
+
@visible ||= true
|
43
|
+
end
|
38
44
|
|
39
|
-
|
40
|
-
|
45
|
+
# Create a new IE window.
|
46
|
+
def new_window
|
47
|
+
ie = new true
|
48
|
+
ie._new_window_init
|
49
|
+
ie
|
50
|
+
end
|
41
51
|
|
42
|
-
|
52
|
+
# Create a new IE, starting at the specified url.
|
53
|
+
# @param [String] url url to navigate to.
|
54
|
+
def start(url=nil)
|
55
|
+
start_window url
|
56
|
+
end
|
57
|
+
|
58
|
+
# Create a new IE window, starting at the specified url.
|
59
|
+
# @param [String] url url to navigate to.
|
60
|
+
def start_window(url=nil)
|
61
|
+
ie = new_window
|
62
|
+
ie.goto url if url
|
63
|
+
ie
|
64
|
+
end
|
43
65
|
|
44
|
-
# Create a new
|
45
|
-
# @
|
46
|
-
#
|
47
|
-
def
|
48
|
-
|
49
|
-
|
66
|
+
# Create a new IE window in a new process.
|
67
|
+
# @note This method will not work when
|
68
|
+
# Watir/Ruby is run under a service (instead of a user).
|
69
|
+
def new_process
|
70
|
+
ie = new true
|
71
|
+
ie._new_process_init
|
72
|
+
ie
|
50
73
|
end
|
51
74
|
|
52
|
-
# Create a new
|
53
|
-
#
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
75
|
+
# Create a new IE window in a new process, starting at the specified URL.
|
76
|
+
# @param [String] url url to navigate to.
|
77
|
+
def start_process(url=nil)
|
78
|
+
ie = new_process
|
79
|
+
ie.goto url if url
|
80
|
+
ie
|
58
81
|
end
|
59
82
|
|
60
83
|
# Attach to an existing IE {Browser}.
|
@@ -74,99 +97,574 @@ Project Homepage: http://watir.com
|
|
74
97
|
# @param [Symbol] how type of the locator. Can be :title, :url or :hwnd.
|
75
98
|
# @param [Symbol] what value of the locator. Can be {String}, {Regexp} or {Fixnum}
|
76
99
|
# depending of the type parameter.
|
100
|
+
#
|
101
|
+
# @note This method will not work when
|
102
|
+
# Watir/Ruby is run under a service (instead of a user).
|
77
103
|
def attach(how, what)
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
# Set options for the {Browser}.
|
83
|
-
def set_options(options)
|
84
|
-
return unless klass.respond_to?(:set_options)
|
85
|
-
klass.set_options options
|
104
|
+
ie = new true # don't create window
|
105
|
+
ie._attach_init(how, what)
|
106
|
+
ie
|
86
107
|
end
|
87
108
|
|
88
|
-
#
|
89
|
-
|
90
|
-
|
91
|
-
|
109
|
+
# Yields successively to each IE window on the current desktop. Takes a block.
|
110
|
+
# @note This method will not work when
|
111
|
+
# Watir/Ruby is run under a service (instead of a user).
|
112
|
+
# @yieldparam [Browser] ie instances of IE found.
|
113
|
+
def each
|
114
|
+
shell = WIN32OLE.new('Shell.Application')
|
115
|
+
ie_browsers = []
|
116
|
+
shell.Windows.each do |window|
|
117
|
+
next unless (window.path =~ /Internet Explorer/ rescue false)
|
118
|
+
next unless (hwnd = window.hwnd rescue false)
|
119
|
+
ie = bind(window)
|
120
|
+
ie.hwnd = hwnd
|
121
|
+
ie_browsers << ie
|
122
|
+
end
|
123
|
+
ie_browsers.each do |ie|
|
124
|
+
yield ie
|
125
|
+
end
|
92
126
|
end
|
93
127
|
|
94
|
-
|
95
|
-
|
96
|
-
|
128
|
+
# @return [String] the IE browser version number as a string.
|
129
|
+
def version
|
130
|
+
@ie_version ||= begin
|
131
|
+
require 'win32/registry'
|
132
|
+
::Win32::Registry::HKEY_LOCAL_MACHINE.open("SOFTWARE\\Microsoft\\Internet Explorer") do |ie_key|
|
133
|
+
begin
|
134
|
+
ie_key['svcVersion']
|
135
|
+
rescue ::Win32::Registry::Error
|
136
|
+
ie_key['Version']
|
137
|
+
end
|
138
|
+
end
|
139
|
+
end
|
97
140
|
end
|
98
|
-
private :klass
|
99
|
-
|
100
|
-
# Add support for the browser option, using the specified class,
|
101
|
-
# provided as a string. Optionally, additional options supported by
|
102
|
-
# the class can be specified as an array of symbols. Options specified
|
103
|
-
# by the user and included in this list will be passed (as a hash) to
|
104
|
-
# the set_options class method (if defined) before creating an instance.
|
105
|
-
# @todo remove this and autoloading since now only IE is supported.
|
106
|
-
# @private
|
107
|
-
def support hash_args
|
108
|
-
option = hash_args[:name]
|
109
|
-
class_string = hash_args[:class]
|
110
|
-
additional_options = hash_args[:options]
|
111
|
-
library = hash_args[:library]
|
112
|
-
gem = hash_args[:gem] || library
|
113
141
|
|
114
|
-
|
115
|
-
|
142
|
+
# @return [Array<String>] the IE browser version numbers split by "." in an Array.
|
143
|
+
def version_parts
|
144
|
+
version.split('.')
|
145
|
+
end
|
116
146
|
|
117
|
-
|
118
|
-
|
147
|
+
# Find existing IE window with locators.
|
148
|
+
# @see .attach
|
149
|
+
def find(how, what)
|
150
|
+
ie_ole = _find(how, what)
|
151
|
+
bind ie_ole if ie_ole
|
119
152
|
end
|
120
|
-
|
153
|
+
|
154
|
+
# Return an Browser object that wraps the given window, typically obtained from
|
155
|
+
# Shell.Application.windows.
|
121
156
|
# @private
|
122
|
-
def
|
123
|
-
|
157
|
+
def bind(window)
|
158
|
+
ie = new true
|
159
|
+
ie.ie = window
|
160
|
+
ie.initialize_options
|
161
|
+
ie
|
124
162
|
end
|
125
163
|
|
126
|
-
# Specifies a default browser. Must be specified before options are parsed.
|
127
|
-
# @todo remove this since only IE is supported.
|
128
164
|
# @private
|
129
|
-
def
|
130
|
-
|
165
|
+
def _find(how, what)
|
166
|
+
_find_all(how, what).first
|
131
167
|
end
|
132
168
|
|
133
|
-
# Returns the names of the browsers that are supported by this module.
|
134
|
-
# These are the options for 'watir_browser' (env var) or 'browser:' (yaml).
|
135
|
-
# @todo remove this since only IE is supported.
|
136
169
|
# @private
|
137
|
-
def
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
|
152
|
-
|
170
|
+
def _find_all(how, what)
|
171
|
+
ies = []
|
172
|
+
count = -1
|
173
|
+
each do |ie|
|
174
|
+
window = ie.ie
|
175
|
+
|
176
|
+
case how
|
177
|
+
when :url
|
178
|
+
ies << window if (what.matches(window.locationURL))
|
179
|
+
when :title
|
180
|
+
# normal windows explorer shells do not have document
|
181
|
+
# note window.document will fail for "new" browsers
|
182
|
+
begin
|
183
|
+
title = window.locationname
|
184
|
+
title = window.document.title
|
185
|
+
rescue WIN32OLERuntimeError
|
186
|
+
end
|
187
|
+
ies << window if what.matches(title)
|
188
|
+
when :hwnd
|
189
|
+
begin
|
190
|
+
ies << window if what == window.HWND
|
191
|
+
rescue WIN32OLERuntimeError
|
192
|
+
end
|
193
|
+
when :index
|
194
|
+
count += 1
|
195
|
+
if count == what
|
196
|
+
ies << window
|
197
|
+
break
|
198
|
+
end
|
199
|
+
when nil
|
200
|
+
ies << window
|
201
|
+
else
|
202
|
+
raise ArgumentError
|
203
|
+
end
|
204
|
+
end
|
205
|
+
|
206
|
+
ies
|
207
|
+
end
|
208
|
+
|
209
|
+
end
|
210
|
+
|
211
|
+
# Used internally to determine when IE has finished loading a page.
|
212
|
+
# @private
|
213
|
+
READYSTATES = {:complete => 4}
|
214
|
+
|
215
|
+
# The default color for highlighting objects as they are accessed.
|
216
|
+
# @private
|
217
|
+
HIGHLIGHT_COLOR = 'yellow'
|
218
|
+
|
219
|
+
# The time, in seconds, it took for the new page to load after executing
|
220
|
+
# the last command.
|
221
|
+
attr_reader :down_load_time
|
222
|
+
|
223
|
+
# The OLE Internet Explorer object.
|
224
|
+
attr_accessor :ie
|
225
|
+
|
226
|
+
# The list of unique urls that have been visited.
|
227
|
+
attr_reader :url_list
|
228
|
+
|
229
|
+
# @private
|
230
|
+
attr_writer :hwnd
|
231
|
+
|
232
|
+
# Create an IE browser instance.
|
233
|
+
# @param [Boolean] suppress_new_window set to true for not creating a IE
|
234
|
+
# window.
|
235
|
+
def initialize(suppress_new_window=nil)
|
236
|
+
_new_window_init unless suppress_new_window == true
|
237
|
+
end
|
238
|
+
|
239
|
+
# Specifies the speed that commands will be executed at.
|
240
|
+
# Possible choices are:
|
241
|
+
# * :slow (default)
|
242
|
+
# * :fast
|
243
|
+
# * :zippy
|
244
|
+
#
|
245
|
+
# With :zippy, text fields will be entered at once, instead of
|
246
|
+
# character by character.
|
247
|
+
#
|
248
|
+
# @note :zippy speed does not trigger JavaScript events like onChange etc.
|
249
|
+
#
|
250
|
+
# @param [Symbol] how_fast possible choices are :slow (default), :fast and
|
251
|
+
# :zippy
|
252
|
+
# @raise [ArgumentError] when invalid speed is specified.
|
253
|
+
def speed=(how_fast)
|
254
|
+
case how_fast
|
255
|
+
when :zippy
|
256
|
+
@typingspeed = 0
|
257
|
+
@pause_after_wait = 0.01
|
258
|
+
@type_keys = false
|
259
|
+
@speed = :fast
|
260
|
+
when :fast
|
261
|
+
@typingspeed = 0
|
262
|
+
@pause_after_wait = 0.01
|
263
|
+
@type_keys = true
|
264
|
+
@speed = :fast
|
265
|
+
when :slow
|
266
|
+
@typingspeed = 0.08
|
267
|
+
@pause_after_wait = 0.1
|
268
|
+
@type_keys = true
|
269
|
+
@speed = :slow
|
270
|
+
else
|
271
|
+
raise ArgumentError, "Invalid speed: #{how_fast}. Possible choices are :slow, :fast and :zippy."
|
272
|
+
end
|
273
|
+
end
|
274
|
+
|
275
|
+
# @return [Symbol] current speed setting. May be :slow, :fast or :zippy.
|
276
|
+
def speed
|
277
|
+
return @speed if @speed == :slow
|
278
|
+
return @type_keys ? :fast : :zippy
|
279
|
+
end
|
280
|
+
|
281
|
+
# @deprecated Use {#speed=} with :fast argument instead.
|
282
|
+
def set_fast_speed
|
283
|
+
Kernel.warn "Deprecated(Browser.set_fast_speed) - use Browser#speed = :fast instead."
|
284
|
+
self.speed = :fast
|
285
|
+
end
|
286
|
+
|
287
|
+
# @deprecated Use {#speed=} with :slow argument instead.
|
288
|
+
def set_slow_speed
|
289
|
+
Kernel.warn "Deprecated(Browser.set_slow_speed) - use Browser#speed = :slow instead."
|
290
|
+
self.speed = :slow
|
291
|
+
end
|
292
|
+
|
293
|
+
# @return [Boolean] true when window is visible, false otherwise.
|
294
|
+
def visible
|
295
|
+
@ie.visible
|
296
|
+
end
|
297
|
+
|
298
|
+
# Set the visibility of IE window.
|
299
|
+
# @param [Boolean] boolean set to true if IE window should be visible, false
|
300
|
+
# otherwise.
|
301
|
+
def visible=(boolean)
|
302
|
+
@ie.visible = boolean if boolean != @ie.visible
|
303
|
+
end
|
304
|
+
|
305
|
+
# @return [Fixnum] current IE window handle.
|
306
|
+
# @raise [RuntimeError] when not attached to a browser.
|
307
|
+
def hwnd
|
308
|
+
raise "Not attached to a browser" if @ie.nil?
|
309
|
+
@hwnd ||= @ie.hwnd
|
310
|
+
end
|
311
|
+
|
312
|
+
# @return [Symbol] the name of the browser. Is always :internet_explorer.
|
313
|
+
def name
|
314
|
+
:internet_explorer
|
315
|
+
end
|
316
|
+
|
317
|
+
# @return [Boolean] true when IE window exists, false otherwise.
|
318
|
+
def exists?
|
319
|
+
!!(@ie.name =~ /Internet Explorer/)
|
320
|
+
rescue WIN32OLERuntimeError, NoMethodError
|
321
|
+
false
|
322
|
+
end
|
323
|
+
|
324
|
+
alias :exist? :exists?
|
325
|
+
|
326
|
+
# @return [String] the title of the document.
|
327
|
+
def title
|
328
|
+
@ie.document.title
|
329
|
+
end
|
330
|
+
|
331
|
+
# @return [String] the status text of the window, typically from the status bar at the bottom.
|
332
|
+
# Will be empty if there's no status or when there are problems accessing status text.
|
333
|
+
def status
|
334
|
+
@ie.statusText
|
335
|
+
rescue WIN32OLERuntimeError
|
336
|
+
""
|
337
|
+
end
|
338
|
+
|
339
|
+
#
|
340
|
+
# Navigation
|
341
|
+
#
|
342
|
+
|
343
|
+
# Navigate to the specified URL.
|
344
|
+
# @param [String] url url to navigate to.
|
345
|
+
# @return [Fixnum] time in seconds the page took to load.
|
346
|
+
def goto(url)
|
347
|
+
url = "http://" + url unless url =~ %r{://} || url == "about:blank"
|
348
|
+
@ie.navigate(url)
|
349
|
+
wait
|
350
|
+
return @down_load_time
|
351
|
+
end
|
352
|
+
|
353
|
+
# Go to the previous page - the same as clicking the browsers back button.
|
354
|
+
# @raise [WIN32OLERuntimeError] when the browser can't go back.
|
355
|
+
def back
|
356
|
+
@ie.GoBack
|
357
|
+
wait
|
358
|
+
end
|
359
|
+
|
360
|
+
# Go to the next page - the same as clicking the browsers forward button.
|
361
|
+
# @raise [WIN32OLERuntimeError] when the browser can't go forward.
|
362
|
+
def forward
|
363
|
+
@ie.GoForward
|
364
|
+
wait
|
365
|
+
end
|
366
|
+
|
367
|
+
# Refresh the current page - the same as clicking the browsers refresh button.
|
368
|
+
# @raise [WIN32OLERuntimeError] when the browser can't refresh.
|
369
|
+
def refresh
|
370
|
+
@ie.refresh2(3)
|
371
|
+
wait
|
372
|
+
end
|
373
|
+
|
374
|
+
def inspect
|
375
|
+
'#<%s:0x%x url=%s title=%s>' % [self.class, hash*2, url.inspect, title.inspect]
|
376
|
+
end
|
377
|
+
|
378
|
+
# Clear the list of urls that have been visited.
|
379
|
+
def clear_url_list
|
380
|
+
@url_list.clear
|
381
|
+
end
|
382
|
+
|
383
|
+
# Close the {Browser}.
|
384
|
+
def close
|
385
|
+
return unless exists?
|
386
|
+
@ie.stop
|
387
|
+
wait rescue nil
|
388
|
+
chwnd = @ie.hwnd.to_i
|
389
|
+
@ie.quit
|
390
|
+
t = ::Time.now
|
391
|
+
while exists?
|
392
|
+
# just in case to avoid possible endless loop if failing to close some
|
393
|
+
# window or tab
|
394
|
+
break if ::Time.now - t > 10
|
395
|
+
sleep 0.3
|
396
|
+
end
|
397
|
+
end
|
398
|
+
|
399
|
+
# Maximize the window (expands to fill the screen).
|
400
|
+
def maximize
|
401
|
+
rautomation.maximize
|
402
|
+
end
|
403
|
+
|
404
|
+
# Minimize the window (appears as icon on taskbar).
|
405
|
+
def minimize
|
406
|
+
rautomation.minimize
|
407
|
+
end
|
408
|
+
|
409
|
+
# @return [Boolean] true when window is minimized, false otherwise.
|
410
|
+
def minimized?
|
411
|
+
rautomation.minimized?
|
412
|
+
end
|
413
|
+
|
414
|
+
# Restore the window (after minimizing or maximizing).
|
415
|
+
def restore
|
416
|
+
rautomation.restore
|
417
|
+
end
|
418
|
+
|
419
|
+
# Make the window come to the front.
|
420
|
+
def activate
|
421
|
+
rautomation.activate
|
422
|
+
end
|
423
|
+
|
424
|
+
alias :bring_to_front :activate
|
425
|
+
|
426
|
+
# @return [Boolean] true when window is in front e.g. in focus, false otherwise.
|
427
|
+
def active?
|
428
|
+
rautomation.active?
|
429
|
+
end
|
430
|
+
|
431
|
+
alias :front? :active?
|
432
|
+
|
433
|
+
# @return [RAutomation::Window] the RAutomation instance for this IE window.
|
434
|
+
# @see https://github.com/jarmo/rautomation
|
435
|
+
def rautomation
|
436
|
+
@rautomation ||= ::RAutomation::Window.new(:hwnd => hwnd)
|
437
|
+
end
|
438
|
+
|
439
|
+
# @deprecated use {#rautomation} instead.
|
440
|
+
def autoit
|
441
|
+
Kernel.warn "Deprecated(Browser#autoit) - use Browser#rautomation instead. Refer to https://github.com/jarmo/RAutomation for updating your scripts."
|
442
|
+
@autoit ||= ::RAutomation::Window.new(:hwnd => hwnd, :adapter => :autoit)
|
443
|
+
end
|
444
|
+
|
445
|
+
# Activates the window and sends keys to it.
|
446
|
+
#
|
447
|
+
# @example
|
448
|
+
# browser.send_keys("Hello World", :enter)
|
449
|
+
#
|
450
|
+
# @see https://github.com/jarmo/RAutomation/blob/master/lib/rautomation/adapter/win_32/window.rb RAutomation::Window#send_keys documentation.
|
451
|
+
def send_keys(*keys)
|
452
|
+
rautomation.send_keys *keys
|
453
|
+
end
|
454
|
+
|
455
|
+
#
|
456
|
+
# Document and Document Data
|
457
|
+
#
|
458
|
+
|
459
|
+
# @return [WIN32OLE] current IE document.
|
460
|
+
def document
|
461
|
+
@ie.document
|
462
|
+
end
|
463
|
+
|
464
|
+
# @return [String] current url, as displayed in the address bar of the browser.
|
465
|
+
def url
|
466
|
+
@ie.LocationURL
|
467
|
+
end
|
468
|
+
|
469
|
+
# Create a {Screenshot} instance.
|
470
|
+
def screenshot
|
471
|
+
Screenshot.new(hwnd)
|
472
|
+
end
|
473
|
+
|
474
|
+
# Retrieve a {Window} instance.
|
475
|
+
#
|
476
|
+
# @example Retrieve a different window without block.
|
477
|
+
# browser.window(:title => /other window title/).use
|
478
|
+
# browser.title # => "other window title"
|
479
|
+
#
|
480
|
+
# @example Use different window with block.
|
481
|
+
# browser.window(:title => /other window title/) do
|
482
|
+
# browser.title # => "other window title"
|
483
|
+
# end
|
484
|
+
# browser.title # => "current window title"
|
485
|
+
#
|
486
|
+
# @param [Hash] specifiers options for finding window.
|
487
|
+
# @option specifiers [String,Regexp] :title Title of the window.
|
488
|
+
# @option specifiers [String,Regexp] :url Url of the window.
|
489
|
+
# @option specifiers [Fixnum] :index The index of the window.
|
490
|
+
# @yield yield optionally to the found window.
|
491
|
+
# @return [Window] found window instance.
|
492
|
+
def window(specifiers={}, &blk)
|
493
|
+
win = Window.new(self, specifiers, &blk)
|
494
|
+
win.use &blk if blk
|
495
|
+
win
|
496
|
+
end
|
497
|
+
|
498
|
+
# @see #window
|
499
|
+
# @return [Array<Window>] array of found windows.
|
500
|
+
def windows(specifiers={})
|
501
|
+
self.class._find_all(specifiers.keys.first, specifiers.values.first).map {|ie| Window.new(self, specifiers, self.class.bind(ie))}
|
502
|
+
end
|
503
|
+
|
504
|
+
# Retrieve {Cookies} instance.
|
505
|
+
def cookies
|
506
|
+
Cookies.new(self)
|
507
|
+
end
|
508
|
+
|
509
|
+
# Add an error checker that gets executed after every page load, click etc.
|
510
|
+
#
|
511
|
+
# @example
|
512
|
+
# browser.add_checker lambda { |browser| raise "Error!" if browser.text.include? "Error" }
|
513
|
+
#
|
514
|
+
# @param [Proc] checker Proc object which gets yielded with {Browser} instance.
|
515
|
+
def add_checker(checker = nil, &block)
|
516
|
+
if block_given?
|
517
|
+
@error_checkers << block
|
518
|
+
elsif checker.respond_to? :call
|
519
|
+
@error_checkers << checker
|
520
|
+
else
|
521
|
+
raise ArgumentError, "expected block or object responding to #call"
|
522
|
+
end
|
523
|
+
end
|
524
|
+
|
525
|
+
# Disable an error checker added via {#add_checker}.
|
526
|
+
#
|
527
|
+
# @param [Proc] checker Proc object to be removed from error checkers.
|
528
|
+
def disable_checker(checker)
|
529
|
+
@error_checkers.delete(checker)
|
530
|
+
end
|
531
|
+
|
532
|
+
# Gives focus to the window frame.
|
533
|
+
def focus
|
534
|
+
active_element = document.activeElement
|
535
|
+
active_element.blur if active_element && active_element.tagName != "BODY"
|
536
|
+
document.focus
|
537
|
+
end
|
538
|
+
|
539
|
+
# @private
|
540
|
+
def attach_command
|
541
|
+
"Watir::Browser.attach(:hwnd, #{hwnd})"
|
542
|
+
end
|
543
|
+
|
544
|
+
# @private
|
545
|
+
def _new_window_init
|
546
|
+
create_browser_window
|
547
|
+
initialize_options
|
548
|
+
goto 'about:blank' # this avoids numerous problems caused by lack of a document
|
549
|
+
end
|
550
|
+
|
551
|
+
# @private
|
552
|
+
def _new_process_init
|
553
|
+
iep = Process.start
|
554
|
+
@ie = iep.window
|
555
|
+
@process_id = iep.process_id
|
556
|
+
initialize_options
|
557
|
+
goto 'about:blank'
|
558
|
+
end
|
559
|
+
|
560
|
+
# this method is used internally to attach to an existing window
|
561
|
+
# @private
|
562
|
+
def _attach_init how, what
|
563
|
+
attach_browser_window how, what
|
564
|
+
initialize_options
|
565
|
+
wait
|
566
|
+
end
|
567
|
+
|
568
|
+
# @private
|
569
|
+
def initialize_options
|
570
|
+
self.visible = self.class.visible
|
571
|
+
self.speed = self.class.speed
|
572
|
+
|
573
|
+
@ole_object = nil
|
574
|
+
@page_container = self
|
575
|
+
@error_checkers = []
|
576
|
+
@active_object_highlight_color = HIGHLIGHT_COLOR
|
577
|
+
@url_list = []
|
578
|
+
end
|
579
|
+
|
580
|
+
#
|
581
|
+
# Synchronization
|
582
|
+
#
|
583
|
+
|
584
|
+
# Block execution until the page has loaded.
|
585
|
+
#
|
586
|
+
# Will raise Timeout::Error if page hasn't been loaded within 5 minutes.
|
587
|
+
# Note: This code needs to be prepared for the ie object to be closed at
|
588
|
+
# any moment!
|
589
|
+
#
|
590
|
+
# @private
|
591
|
+
def wait(no_sleep=false)
|
592
|
+
@xml_parser_doc = nil
|
593
|
+
@down_load_time = 0.0
|
594
|
+
interval = 0.05
|
595
|
+
start_load_time = ::Time.now
|
596
|
+
|
597
|
+
Timeout::timeout(5*60) do
|
153
598
|
begin
|
154
|
-
|
155
|
-
|
156
|
-
|
599
|
+
while @ie.busy
|
600
|
+
sleep interval
|
601
|
+
end
|
602
|
+
|
603
|
+
until READYSTATES.has_value?(@ie.readyState)
|
604
|
+
sleep interval
|
605
|
+
end
|
606
|
+
|
607
|
+
until @ie.document
|
608
|
+
sleep interval
|
609
|
+
end
|
610
|
+
|
611
|
+
documents_to_wait_for = [@ie.document]
|
612
|
+
rescue WIN32OLERuntimeError # IE window must have been closed
|
613
|
+
@down_load_time = ::Time.now - start_load_time
|
614
|
+
return @down_load_time
|
615
|
+
end
|
616
|
+
|
617
|
+
while doc = documents_to_wait_for.shift
|
618
|
+
begin
|
619
|
+
until READYSTATES.has_key?(doc.readyState.to_sym)
|
620
|
+
sleep interval
|
621
|
+
end
|
622
|
+
@url_list << doc.location.href unless @url_list.include?(doc.location.href)
|
623
|
+
doc.frames.length.times do |n|
|
624
|
+
begin
|
625
|
+
documents_to_wait_for << doc.frames[n.to_s].document
|
626
|
+
rescue WIN32OLERuntimeError, NoMethodError
|
627
|
+
end
|
628
|
+
end
|
629
|
+
rescue WIN32OLERuntimeError
|
630
|
+
end
|
157
631
|
end
|
158
632
|
end
|
159
633
|
|
160
|
-
|
161
|
-
|
162
|
-
|
163
|
-
|
164
|
-
|
165
|
-
|
634
|
+
@down_load_time = ::Time.now - start_load_time
|
635
|
+
run_error_checks
|
636
|
+
sleep @pause_after_wait unless no_sleep
|
637
|
+
@down_load_time
|
638
|
+
end
|
639
|
+
|
640
|
+
# Error checkers
|
641
|
+
|
642
|
+
# Run the predefined error checks.
|
643
|
+
#
|
644
|
+
# @private
|
645
|
+
def run_error_checks
|
646
|
+
@error_checkers.each { |e| e.call(self) }
|
647
|
+
end
|
648
|
+
|
649
|
+
private
|
650
|
+
|
651
|
+
def create_browser_window
|
652
|
+
@ie = WIN32OLE.new('InternetExplorer.Application')
|
653
|
+
end
|
654
|
+
|
655
|
+
def attach_browser_window how, what
|
656
|
+
ieTemp = nil
|
657
|
+
begin
|
658
|
+
Wait.until(self.class.attach_timeout) do
|
659
|
+
ieTemp = self.class._find how, what
|
660
|
+
end
|
661
|
+
rescue Wait::TimeoutError
|
662
|
+
raise NoMatchingWindowFoundException,
|
663
|
+
"Unable to locate a window with #{how} of #{what}"
|
166
664
|
end
|
665
|
+
@ie = ieTemp
|
167
666
|
end
|
168
|
-
end
|
169
667
|
|
170
|
-
end
|
171
668
|
|
172
|
-
|
669
|
+
end
|
670
|
+
end
|