watir-classic 3.7.0 → 4.0.0

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.
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