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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 73e938bbd43dbc55379ce36d3fc826bb636a65d4
4
- data.tar.gz: b9894a14322b0077c26cbfd1d729966f3a355e78
3
+ metadata.gz: 9b48648a4afcf9526da12f6baf012a4f0fec8411
4
+ data.tar.gz: 70def43f23d469fbb1de955b8112c6ce7d4e7a11
5
5
  SHA512:
6
- metadata.gz: b04aa3fde25905e96a31297f6de93dad85618c8a3aef68801ba02c234c9eb44650471355342c349625473cf736f074acc23db1ac8de4d6d74063f031f549d259
7
- data.tar.gz: cde4f06da44866e0890e618b91c9e555c7895cfd27d2ae146ccb28ccc8607859d505413ae4a7b43956f01789624f9429ffc4587af8ab0db7ea85d88628147047
6
+ metadata.gz: 7980313c5a552ed151618b593bc1742d26c7918241a2fac62871fd8ef0b7f0ce593e5bd02d3953feeb0a68411155ea85bd4059fdefd94363e2dca8a4bbdc69dc
7
+ data.tar.gz: d89a17e83ebf2e1ae901e89808c1b6ceb9f4551089663a263a45e7a38da368af0ad0a4bcf027879ddf6eccb8e423b8e6bec8eddf72f8e25dd8c8861363e6eb09
data/.gitignore CHANGED
@@ -5,3 +5,5 @@ pkg/
5
5
  .idea/
6
6
  .yardoc/
7
7
  doc/
8
+
9
+ Gemfile.lock
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
@@ -5,6 +5,8 @@ Bundler::GemHelper.install_tasks
5
5
 
6
6
  task :default => :spec
7
7
 
8
+ task :release => :spec
9
+
8
10
  require 'rspec/core/rake_task'
9
11
  RSpec::Core::RakeTask.new(:spec)
10
12
 
data/VERSION CHANGED
@@ -1 +1 @@
1
- 3.7.0
1
+ 4.0.0
@@ -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/wait'
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
- =begin rdoc
2
+ # Main browser class.
3
+ class Browser
4
+ include WaitHelper
5
+ include Exception
6
+ include Container
7
+ include PageContainer
5
8
 
6
- Watir is a family of open-source drivers for automating web browsers. You
7
- can use it to write tests that are easy to read and maintain.
9
+ class << self
10
+ # Maximum number of seconds to wait when attaching to a window
11
+ attr_writer :attach_timeout
8
12
 
9
- Watir drives browsers the same way people do. It clicks links, fills in forms,
10
- presses buttons. Watir also checks results, such as whether expected text
11
- appears on a page.
13
+ def attach_timeout
14
+ @attach_timeout ||= 2
15
+ end
12
16
 
13
- The Watir Classic is a driver for Internet Explorer (on Windows).
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
- Project Homepage: http://watir.com
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
- @example usage
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
- require 'watir-classic'
20
- browser = Watir::Browser.new
21
- browser.goto 'http://google.com'
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
- =end rdoc
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
- # @private
37
- @@sub_options = {}
41
+ def visible
42
+ @visible ||= true
43
+ end
38
44
 
39
- # @private
40
- @@default = nil
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
- class << self
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 instance of the {Browser} object
45
- # @param [Object] ignored Argument is only needed to make
46
- # watir-classic more compatible with watir-webdriver and is really ignored.
47
- def new(ignored=nil)
48
- set_sub_options
49
- klass.new
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 {Browser} instance as with {.new} and start the browser on the
53
- # specified url.
54
- # @param [String] url Url to start the browser at.
55
- def start(url)
56
- set_sub_options
57
- klass.start url
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
- set_sub_options
79
- klass.attach(how, what)
80
- end
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
- # @return [Hash] options of the {Browser}.
89
- def options
90
- return {} unless klass.respond_to?(:options)
91
- klass.options
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
- def klass
95
- key = Watir.options[:browser]
96
- eval @@browser_classes[key] # this triggers the autoload
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
- @@browser_classes[option] = class_string
115
- @@sub_options[option] = additional_options
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
- autoload class_string, library
118
- activate_gem gem, option
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 default
123
- @@default
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 default= option
130
- @@default = option
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 browser_names
138
- @@browser_classes.keys
139
- end
140
-
141
- private
142
-
143
- # @todo remove this since only IE is supported.
144
- def autoload class_string, library
145
- mod, klass = class_string.split('::')
146
- eval "module ::#{mod}; autoload :#{klass}, '#{library}'; end"
147
- end
148
-
149
- # Activate the gem (if installed). The default browser will be set
150
- # to the first gem that activates.
151
- # @todo remove this since only IE is supported.
152
- def activate_gem gem_name, option
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
- gem gem_name
155
- @@default ||= option
156
- rescue Gem::LoadError
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
- # @todo remove this since only IE is supported.
161
- def set_sub_options
162
- sub_options = @@sub_options[Watir.options[:browser]]
163
- return if sub_options.nil?
164
- specified_options = Watir.options.reject {|k, v| !sub_options.include? k}
165
- self.set_options specified_options
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
- require 'watir-classic/browsers'
669
+ end
670
+ end