watir-classic 3.3.0 → 3.4.0
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGES +17 -0
- data/Gemfile.lock +9 -8
- data/LICENSE +1 -0
- data/README.rdoc +6 -7
- data/Rakefile +3 -1
- data/VERSION +1 -1
- data/lib/watir-classic.rb +0 -5
- data/lib/watir-classic/browser.rb +58 -35
- data/lib/watir-classic/browsers.rb +1 -1
- data/lib/watir-classic/container.rb +39 -33
- data/lib/watir-classic/cookies.rb +32 -2
- data/lib/watir-classic/core.rb +0 -1
- data/lib/watir-classic/dialogs/alert.rb +12 -0
- data/lib/watir-classic/dialogs/file_field.rb +11 -0
- data/lib/watir-classic/drag_and_drop_helper.rb +14 -0
- data/lib/watir-classic/element.rb +292 -257
- data/lib/watir-classic/element_collection.rb +26 -8
- data/lib/watir-classic/element_extensions.rb +22 -16
- data/lib/watir-classic/exceptions.rb +4 -4
- data/lib/watir-classic/form.rb +52 -49
- data/lib/watir-classic/frame.rb +23 -14
- data/lib/watir-classic/ie-class.rb +363 -315
- data/lib/watir-classic/ie-process.rb +1 -0
- data/lib/watir-classic/ie.rb +0 -17
- data/lib/watir-classic/image.rb +58 -64
- data/lib/watir-classic/input_elements.rb +224 -219
- data/lib/watir-classic/link.rb +14 -15
- data/lib/watir-classic/locator.rb +12 -7
- data/lib/watir-classic/matches.rb +7 -3
- data/lib/watir-classic/modal_dialog.rb +38 -26
- data/lib/watir-classic/non_control_elements.rb +29 -0
- data/lib/watir-classic/options.rb +10 -15
- data/lib/watir-classic/page-container.rb +30 -48
- data/lib/watir-classic/process.rb +4 -2
- data/lib/watir-classic/screenshot.rb +6 -0
- data/lib/watir-classic/supported_elements.rb +36 -14
- data/lib/watir-classic/table.rb +81 -71
- data/lib/watir-classic/util.rb +9 -11
- data/lib/watir-classic/wait.rb +17 -4
- data/lib/watir-classic/wait_helper.rb +15 -2
- data/lib/watir-classic/win32.rb +2 -1
- data/lib/watir-classic/window.rb +35 -7
- data/lib/watir-classic/xpath_locator.rb +1 -0
- data/lib/watir-classic/yard/global_macros.rb +7 -0
- data/spec/frame_spec.rb +17 -0
- metadata +5 -7
- data/lib/watir-classic/close_all.rb +0 -31
- data/lib/watir-classic/contrib/enabled_popup.rb +0 -21
- data/lib/watir-classic/contrib/ie-new-process.rb +0 -27
- data/lib/watir-classic/contrib/page_checker.rb +0 -29
- data/watir.gif +0 -0
@@ -1,11 +1,12 @@
|
|
1
1
|
module Watir
|
2
|
-
#
|
3
|
-
#
|
2
|
+
# This class is the super class for the iterator classes (buttons, links, spans etc).
|
3
|
+
# It would normally only be accessed by the iterator methods (spans, links etc) of {Container}.
|
4
4
|
class ElementCollection
|
5
5
|
include Enumerable
|
6
6
|
|
7
7
|
# Super class for all the iterator classes
|
8
|
-
#
|
8
|
+
# @param [Element] container container element instance.
|
9
|
+
# @param [Hash] specifiers locators for elements.
|
9
10
|
def initialize(container, specifiers)
|
10
11
|
if specifiers[:index]
|
11
12
|
raise Exception::MissingWayOfFindingObjectException,
|
@@ -17,6 +18,7 @@ module Watir
|
|
17
18
|
@page_container = container.page_container
|
18
19
|
end
|
19
20
|
|
21
|
+
# @return [Fixnum] count of elements in this collection.
|
20
22
|
def length
|
21
23
|
count = 0
|
22
24
|
each {|element| count += 1 }
|
@@ -25,28 +27,36 @@ module Watir
|
|
25
27
|
|
26
28
|
alias_method :size, :length
|
27
29
|
|
28
|
-
#
|
30
|
+
# Iterate through each of the elements in the collection in turn.
|
31
|
+
# @yieldparam [Element] element element instance.
|
29
32
|
def each
|
30
33
|
@container.locator_for(TaggedElementLocator, @specifiers, element_class).each {|element| yield element}
|
31
34
|
end
|
32
35
|
|
33
|
-
#
|
36
|
+
# Access a specific item in the collection.
|
37
|
+
#
|
38
|
+
# @note {Element} will be always returned even if the index is out of
|
39
|
+
# bounds. Use {Element#exists?} to verify if the element actually exists.
|
40
|
+
# @param [Fixnum] n n-th element to retrieve.
|
41
|
+
# @return [Element] element with specified index from this collection.
|
34
42
|
def [](n)
|
35
|
-
number = n - Watir::IE.base_index
|
36
|
-
offset = Watir::IE.zero_based_indexing ? (length - 1) : length
|
37
43
|
non_existing_element = element_class.new(@container, @specifiers.merge(:index => n))
|
38
44
|
def non_existing_element.locate; nil end
|
39
|
-
iterator_object(
|
45
|
+
iterator_object(n) || non_existing_element
|
40
46
|
end
|
41
47
|
|
48
|
+
# @return [Element] first element from this collection.
|
42
49
|
def first
|
43
50
|
iterator_object(0)
|
44
51
|
end
|
45
52
|
|
53
|
+
# @return [Element] last element from this collection.
|
46
54
|
def last
|
47
55
|
iterator_object(length - 1)
|
48
56
|
end
|
49
57
|
|
58
|
+
# @return [String] String representation of each element in this collection
|
59
|
+
# separated by line-feed.
|
50
60
|
def to_s
|
51
61
|
map { |e| e.to_s }.join("\n")
|
52
62
|
end
|
@@ -71,12 +81,14 @@ module Watir
|
|
71
81
|
|
72
82
|
end
|
73
83
|
|
84
|
+
# This class represents table elements collection.
|
74
85
|
class TableElementCollection < ElementCollection
|
75
86
|
def initialize(container, specifiers, ole_collection=nil)
|
76
87
|
super container, specifiers
|
77
88
|
@ole_collection = ole_collection
|
78
89
|
end
|
79
90
|
|
91
|
+
# @see ElementCollection#each
|
80
92
|
def each
|
81
93
|
if @ole_collection
|
82
94
|
elements = []
|
@@ -90,17 +102,23 @@ module Watir
|
|
90
102
|
end
|
91
103
|
end
|
92
104
|
|
105
|
+
# This class represents table row elements collection.
|
93
106
|
class TableRowCollection < TableElementCollection; end
|
94
107
|
|
108
|
+
# This class represents table cell elements collection.
|
95
109
|
class TableCellCollection < TableElementCollection; end
|
96
110
|
|
111
|
+
# This class represents input elements collection.
|
97
112
|
class InputElementCollection < ElementCollection
|
113
|
+
# @see ElementCollection#each
|
98
114
|
def each
|
99
115
|
@container.locator_for(InputElementLocator, @specifiers, element_class).each {|element| yield element}
|
100
116
|
end
|
101
117
|
end
|
102
118
|
|
119
|
+
# This class represents general elements collection.
|
103
120
|
class HTMLElementCollection < ElementCollection
|
121
|
+
# @see ElementCollection#each
|
104
122
|
def each
|
105
123
|
@container.locator_for(TaggedElementLocator, @specifiers, Element).each { |element| yield element }
|
106
124
|
end
|
@@ -1,14 +1,13 @@
|
|
1
1
|
# encoding: utf-8
|
2
2
|
|
3
3
|
module Watir
|
4
|
-
# This
|
4
|
+
# This module adds some helper methods for asynchronous testing.
|
5
5
|
module ElementExtensions
|
6
6
|
|
7
|
-
#
|
8
|
-
# Wraps a {Celerity,Watir}::Element so that any subsequent method calls are
|
7
|
+
# Wraps an {Element} so that any subsequent method calls are
|
9
8
|
# put on hold until the element is present on the page.
|
10
9
|
#
|
11
|
-
|
10
|
+
# @private
|
12
11
|
class WhenPresentDecorator
|
13
12
|
def initialize(element, timeout)
|
14
13
|
@element = element
|
@@ -28,26 +27,25 @@ module Watir
|
|
28
27
|
|
29
28
|
end
|
30
29
|
|
31
|
-
#
|
32
|
-
# Returns true if the element exists and is visible on the page
|
33
|
-
#
|
34
|
-
|
30
|
+
# @return [Boolean] true when element exists and is visible, false otherwise.
|
35
31
|
def present?
|
36
32
|
exists? && visible? rescue false
|
37
33
|
end
|
38
34
|
|
35
|
+
# Waits until the element is present before calling its methods.
|
39
36
|
#
|
40
|
-
#
|
37
|
+
# @example
|
38
|
+
# browser.button(:id, 'foo').when_present.click
|
41
39
|
#
|
42
|
-
#
|
40
|
+
# @example
|
41
|
+
# browser.div(:id, 'bar').when_present { |div| ... }
|
43
42
|
#
|
44
|
-
#
|
43
|
+
# @example
|
44
|
+
# browser.p(:id, 'baz').when_present(60).text
|
45
45
|
#
|
46
|
-
#
|
47
|
-
#
|
48
|
-
#
|
49
|
-
#
|
50
|
-
|
46
|
+
# @param [Fixnum] timeout seconds to wait before timing out.
|
47
|
+
# @raise [Watir::Wait::TimeoutError] will be raised when element is not
|
48
|
+
# present within specified timeout.
|
51
49
|
def when_present(timeout = 60)
|
52
50
|
if block_given?
|
53
51
|
Watir::Wait.until(timeout) { self.present? }
|
@@ -57,10 +55,18 @@ module Watir
|
|
57
55
|
end
|
58
56
|
end
|
59
57
|
|
58
|
+
# Wait until element is present before continuing.
|
59
|
+
#
|
60
|
+
# @raise [Watir::Wait::TimeoutError] will be raised when element is not
|
61
|
+
# present within specified timeout.
|
60
62
|
def wait_until_present(timeout = 60)
|
61
63
|
Watir::Wait.until(timeout) { self.present? }
|
62
64
|
end
|
63
65
|
|
66
|
+
# Wait while element is present before continuing.
|
67
|
+
#
|
68
|
+
# @raise [Watir::Wait::TimeoutError] will be raised when element is still present
|
69
|
+
# after specified timeout.
|
64
70
|
def wait_while_present(timeout = 60)
|
65
71
|
Watir::Wait.while(timeout) { self.present? }
|
66
72
|
end
|
@@ -3,11 +3,11 @@ module Watir
|
|
3
3
|
|
4
4
|
# Root class for all Watir Exceptions
|
5
5
|
class WatirException < RuntimeError
|
6
|
-
|
7
|
-
|
8
|
-
|
6
|
+
def initialize(message="")
|
7
|
+
super(message)
|
8
|
+
end
|
9
9
|
end
|
10
|
-
|
10
|
+
|
11
11
|
# This exception is raised if an attempt is made to access an object that doesn't exist
|
12
12
|
class UnknownObjectException < WatirException; end
|
13
13
|
# This exception is raised if an attempt is made to access an object that is in a disabled state
|
data/lib/watir-classic/form.rb
CHANGED
@@ -1,24 +1,33 @@
|
|
1
1
|
module Watir
|
2
2
|
|
3
|
+
# Returned by {Container#form}.
|
3
4
|
class Form < Element
|
5
|
+
|
6
|
+
attr_ole :action
|
7
|
+
|
4
8
|
def initialize(container, specifiers)
|
5
9
|
super
|
6
10
|
copy_test_config container
|
7
11
|
end
|
8
12
|
|
9
|
-
|
10
|
-
|
13
|
+
# @return [String] form name attribute value. Will be empty string if does not
|
14
|
+
# exist.
|
15
|
+
# @macro exists
|
11
16
|
def name
|
12
17
|
assert_exists
|
13
18
|
name = ole_object.getAttributeNode('name')
|
14
19
|
name ? name.value : ''
|
15
20
|
end
|
16
21
|
|
22
|
+
# @return [String] form method attribute value.
|
23
|
+
# @macro exists
|
17
24
|
def form_method
|
18
25
|
assert_exists
|
19
26
|
ole_object.invoke('method')
|
20
27
|
end
|
21
|
-
|
28
|
+
|
29
|
+
# @param [Object] arg when argument is nil, {#form_method} will be called.
|
30
|
+
# Otherwise Ruby's {Kernel#method} will be called.
|
22
31
|
def method(arg = nil)
|
23
32
|
if arg.nil?
|
24
33
|
form_method
|
@@ -27,68 +36,62 @@ module Watir
|
|
27
36
|
end
|
28
37
|
end
|
29
38
|
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
# Submit the data -- equivalent to pressing Enter or Return to submit a form.
|
39
|
+
# Submit the form.
|
40
|
+
# @note Will not submit the form if its onSubmit JavaScript callback
|
41
|
+
# returns false.
|
42
|
+
# @macro exists
|
35
43
|
def submit
|
36
44
|
assert_exists
|
37
45
|
@o.submit(0) if dispatch_event "onSubmit"
|
38
46
|
@container.wait
|
39
47
|
end
|
40
|
-
|
48
|
+
|
49
|
+
# Flash the element the specified number of times for troubleshooting purposes.
|
50
|
+
# @param [Fixnum] number number of times to flash the element.
|
51
|
+
# @macro exists
|
52
|
+
def flash(number=10)
|
53
|
+
assert_exists
|
54
|
+
@original_element_colors = {}
|
55
|
+
number.times do
|
56
|
+
set_highlight
|
57
|
+
sleep 0.05
|
58
|
+
clear_highlight
|
59
|
+
sleep 0.05
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
# @private
|
64
|
+
def locate
|
65
|
+
@o = @container.locator_for(FormLocator, @specifiers, self.class).locate
|
66
|
+
end
|
67
|
+
|
68
|
+
# @private
|
41
69
|
def __ole_inner_elements
|
42
70
|
assert_exists
|
43
71
|
@o.elements
|
44
72
|
end
|
45
73
|
|
46
|
-
|
47
|
-
|
48
|
-
#
|
49
|
-
def
|
50
|
-
|
51
|
-
|
74
|
+
private
|
75
|
+
|
76
|
+
# This method is responsible for setting the colored highlighting on the specified form.
|
77
|
+
def set_highlight
|
78
|
+
@o.elements.each do |element|
|
79
|
+
perform_highlight do
|
52
80
|
original_color = element.style.backgroundColor
|
53
|
-
|
54
|
-
element
|
55
|
-
rescue => e
|
56
|
-
puts e
|
57
|
-
puts e.backtrace.join("\n")
|
58
|
-
original_color = ""
|
59
|
-
end
|
60
|
-
@original_styles[count] = original_color
|
61
|
-
else
|
62
|
-
begin
|
63
|
-
element.style.backgroundColor = @original_styles[ count]
|
64
|
-
rescue => e
|
65
|
-
puts e
|
66
|
-
# we could be here for a number of reasons...
|
67
|
-
ensure
|
81
|
+
element.style.backgroundColor = active_object_highlight_color
|
82
|
+
@original_element_colors[element] = original_color
|
68
83
|
end
|
69
84
|
end
|
70
85
|
end
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
@original_styles = {}
|
78
|
-
number.times do
|
79
|
-
count = 0
|
80
|
-
@o.elements.each do |element|
|
81
|
-
highlight(:set, element, count)
|
82
|
-
count += 1
|
83
|
-
end
|
84
|
-
sleep 0.05
|
85
|
-
count = 0
|
86
|
-
@o.elements.each do |element|
|
87
|
-
highlight(:clear, element, count)
|
88
|
-
count += 1
|
86
|
+
|
87
|
+
# This method is responsible for clearing the colored highlighting on the specified form.
|
88
|
+
def clear_highlight
|
89
|
+
@original_element_colors.each_pair do |element, color|
|
90
|
+
perform_highlight do
|
91
|
+
element.style.backgroundColor = color
|
89
92
|
end
|
90
|
-
sleep 0.05
|
91
93
|
end
|
94
|
+
@original_element_colors.clear
|
92
95
|
end
|
93
96
|
|
94
97
|
end # class Form
|
data/lib/watir-classic/frame.rb
CHANGED
@@ -1,7 +1,9 @@
|
|
1
1
|
module Watir
|
2
|
+
# Returned by the {Container#frame}.
|
2
3
|
class Frame < Element
|
3
4
|
include PageContainer
|
4
|
-
|
5
|
+
|
6
|
+
attr_writer :document
|
5
7
|
|
6
8
|
attr_ole :name
|
7
9
|
attr_ole :src
|
@@ -11,7 +13,26 @@ module Watir
|
|
11
13
|
copy_test_config container
|
12
14
|
end
|
13
15
|
|
16
|
+
# @return [WIN32OLE] frame's document object.
|
17
|
+
# @raise [FrameAccessDeniedException] when IE security settings won't allow
|
18
|
+
# to access the frame
|
19
|
+
# @macro exists
|
20
|
+
def document
|
21
|
+
assert_exists
|
22
|
+
if @document
|
23
|
+
@document
|
24
|
+
else
|
25
|
+
raise FrameAccessDeniedException, "IE will not allow access to this frame for security reasons. You can work around this with ie.goto(frame.src)"
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
# @private
|
30
|
+
def attach_command
|
31
|
+
@container.page_container.attach_command + ".frame(:unique_number => #{unique_number})"
|
32
|
+
end
|
33
|
+
|
14
34
|
# Find the frame denoted by specifiers in the container and return its ole_object
|
35
|
+
# @private
|
15
36
|
def locate
|
16
37
|
frame, document = @container.locator_for(FrameLocator, @specifiers, self.class).locate
|
17
38
|
if frame && document
|
@@ -26,22 +47,10 @@ module Watir
|
|
26
47
|
end
|
27
48
|
end
|
28
49
|
|
50
|
+
# @private
|
29
51
|
def __ole_inner_elements
|
30
52
|
document.body.all
|
31
53
|
end
|
32
54
|
|
33
|
-
def document
|
34
|
-
assert_exists
|
35
|
-
if @document
|
36
|
-
@document
|
37
|
-
else
|
38
|
-
raise FrameAccessDeniedException, "IE will not allow access to this frame for security reasons. You can work around this with ie.goto(frame.src)"
|
39
|
-
end
|
40
|
-
end
|
41
|
-
|
42
|
-
def attach_command
|
43
|
-
@container.page_container.attach_command + ".frame(#{@specifiers.inspect})".gsub('"','\'')
|
44
|
-
end
|
45
|
-
|
46
55
|
end
|
47
56
|
end
|
@@ -1,352 +1,332 @@
|
|
1
1
|
module Watir
|
2
|
+
# Main browser class.
|
2
3
|
class IE
|
3
4
|
include WaitHelper
|
4
5
|
include Exception
|
5
6
|
include Container
|
6
7
|
include PageContainer
|
7
8
|
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
@@attach_timeout
|
12
|
-
end
|
13
|
-
def self.attach_timeout=(timeout)
|
14
|
-
@@attach_timeout = timeout
|
15
|
-
end
|
9
|
+
class << self
|
10
|
+
# Maximum number of seconds to wait when attaching to a window
|
11
|
+
attr_writer :attach_timeout
|
16
12
|
|
17
|
-
|
18
|
-
|
19
|
-
def self.options
|
20
|
-
{:speed => self.speed, :visible => self.visible, :attach_timeout => self.attach_timeout, :zero_based_indexing => self.zero_based_indexing}
|
21
|
-
end
|
22
|
-
# set values for options used when creating new instances of IE.
|
23
|
-
def self.set_options options
|
24
|
-
options.each do |name, value|
|
25
|
-
send "#{name}=", value
|
13
|
+
def attach_timeout
|
14
|
+
@attach_timeout ||= 2
|
26
15
|
end
|
27
|
-
end
|
28
|
-
# The globals $FAST_SPEED and $HIDE_IE are checked both at initialization
|
29
|
-
# and later, because they
|
30
|
-
# might be set after initialization. Setting them beforehand (e.g. from
|
31
|
-
# the command line) will affect the class, otherwise it is only a temporary
|
32
|
-
# effect
|
33
|
-
@@speed = $FAST_SPEED ? :fast : :slow
|
34
|
-
def self.speed
|
35
|
-
return :fast if $FAST_SPEED
|
36
|
-
@@speed
|
37
|
-
end
|
38
|
-
def self.speed= x
|
39
|
-
$FAST_SPEED = nil
|
40
|
-
@@speed = x
|
41
|
-
end
|
42
|
-
@@visible = $HIDE_IE ? false : true
|
43
|
-
def self.visible
|
44
|
-
return false if $HIDE_IE
|
45
|
-
@@visible
|
46
|
-
end
|
47
|
-
def self.visible= x
|
48
|
-
$HIDE_IE = nil
|
49
|
-
@@visible = x
|
50
|
-
end
|
51
16
|
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
17
|
+
# Return the options used when creating new instances of IE.
|
18
|
+
# BUG: this interface invites misunderstanding/misuse such as IE.options[:speed] = :zippy]
|
19
|
+
def options
|
20
|
+
{:speed => self.speed, :visible => self.visible, :attach_timeout => self.attach_timeout}
|
21
|
+
end
|
56
22
|
|
57
|
-
|
58
|
-
|
59
|
-
|
23
|
+
# set values for options used when creating new instances of IE.
|
24
|
+
def set_options options
|
25
|
+
options.each do |name, value|
|
26
|
+
send "#{name}=", value
|
27
|
+
end
|
28
|
+
end
|
60
29
|
|
61
|
-
|
62
|
-
|
63
|
-
|
30
|
+
# The speed in which browser will type keys etc. Possible values are
|
31
|
+
# :slow (default), :fast and :zippy.
|
32
|
+
attr_writer :speed
|
64
33
|
|
65
|
-
|
66
|
-
|
34
|
+
def speed
|
35
|
+
@speed ||= :slow
|
36
|
+
end
|
67
37
|
|
68
|
-
|
69
|
-
|
38
|
+
# Set browser window to visible or hidden. Defaults to true.
|
39
|
+
attr_writer :visible
|
70
40
|
|
71
|
-
|
72
|
-
|
73
|
-
|
41
|
+
def visible
|
42
|
+
@visible ||= true
|
43
|
+
end
|
74
44
|
|
75
|
-
|
76
|
-
|
45
|
+
# Create a new IE window.
|
46
|
+
def new_window
|
47
|
+
ie = new true
|
48
|
+
ie._new_window_init
|
49
|
+
ie
|
50
|
+
end
|
77
51
|
|
78
|
-
|
79
|
-
|
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
|
80
57
|
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
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
|
87
65
|
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
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
|
73
|
+
end
|
92
74
|
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
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
|
81
|
+
end
|
98
82
|
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
83
|
+
# Attach to an existing IE {Browser}.
|
84
|
+
#
|
85
|
+
# @example Attach with full title:
|
86
|
+
# Watir::Browser.attach(:title, "Full title of IE")
|
87
|
+
#
|
88
|
+
# @example Attach with part of the title using {Regexp}:
|
89
|
+
# Watir::Browser.attach(:title, /part of the title of IE/)
|
90
|
+
#
|
91
|
+
# @example Attach with part of the url:
|
92
|
+
# Watir::Browser.attach(:url, /google/)
|
93
|
+
#
|
94
|
+
# @example Attach with window handle:
|
95
|
+
# Watir::Browser.attach(:hwnd, 123456)
|
96
|
+
#
|
97
|
+
# @param [Symbol] how type of the locator. Can be :title, :url or :hwnd.
|
98
|
+
# @param [Symbol] what value of the locator. Can be {String}, {Regexp} or {Fixnum}
|
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).
|
103
|
+
def attach(how, what)
|
104
|
+
ie = new true # don't create window
|
105
|
+
ie._attach_init(how, what)
|
106
|
+
ie
|
107
|
+
end
|
104
108
|
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
ie
|
109
|
-
|
110
|
-
|
111
|
-
|
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 [IE] 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
|
126
|
+
end
|
112
127
|
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
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
|
+
ie_key.read('Version').last
|
134
|
+
end
|
135
|
+
# OR: ::WIN32OLE.new("WScript.Shell").RegRead("HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Internet Explorer\\Version")
|
136
|
+
end
|
137
|
+
end
|
121
138
|
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
initialize_options
|
127
|
-
goto 'about:blank'
|
128
|
-
end
|
139
|
+
# @return [Array<String>] the IE browser version numbers split by "." in an Array.
|
140
|
+
def version_parts
|
141
|
+
version.split('.')
|
142
|
+
end
|
129
143
|
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
end
|
144
|
+
# Find existing IE window with locators.
|
145
|
+
# @see .attach
|
146
|
+
def find(how, what)
|
147
|
+
ie_ole = _find(how, what)
|
148
|
+
bind ie_ole if ie_ole
|
149
|
+
end
|
137
150
|
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
def self.attach how, what
|
148
|
-
ie = new true # don't create window
|
149
|
-
ie._attach_init(how, what)
|
150
|
-
ie
|
151
|
-
end
|
151
|
+
# Return an IE object that wraps the given window, typically obtained from
|
152
|
+
# Shell.Application.windows.
|
153
|
+
# @private
|
154
|
+
def bind(window)
|
155
|
+
ie = new true
|
156
|
+
ie.ie = window
|
157
|
+
ie.initialize_options
|
158
|
+
ie
|
159
|
+
end
|
152
160
|
|
153
|
-
|
154
|
-
|
155
|
-
|
156
|
-
|
157
|
-
|
158
|
-
|
161
|
+
# @private
|
162
|
+
def _find(how, what)
|
163
|
+
_find_all(how, what).first
|
164
|
+
end
|
165
|
+
|
166
|
+
# @private
|
167
|
+
def _find_all(how, what)
|
168
|
+
ies = []
|
169
|
+
count = -1
|
170
|
+
each do |ie|
|
171
|
+
window = ie.ie
|
172
|
+
|
173
|
+
case how
|
174
|
+
when :url
|
175
|
+
ies << window if (what.matches(window.locationURL))
|
176
|
+
when :title
|
177
|
+
# normal windows explorer shells do not have document
|
178
|
+
# note window.document will fail for "new" browsers
|
179
|
+
begin
|
180
|
+
title = window.locationname
|
181
|
+
title = window.document.title
|
182
|
+
rescue WIN32OLERuntimeError
|
183
|
+
end
|
184
|
+
ies << window if what.matches(title)
|
185
|
+
when :hwnd
|
186
|
+
begin
|
187
|
+
ies << window if what == window.HWND
|
188
|
+
rescue WIN32OLERuntimeError
|
189
|
+
end
|
190
|
+
when :index
|
191
|
+
count += 1
|
192
|
+
if count == what
|
193
|
+
ies << window
|
194
|
+
break
|
195
|
+
end
|
196
|
+
when nil
|
197
|
+
ies << window
|
198
|
+
else
|
199
|
+
raise ArgumentError
|
200
|
+
end
|
201
|
+
end
|
202
|
+
|
203
|
+
ies
|
204
|
+
end
|
159
205
|
|
160
|
-
# Return an IE object that wraps the given window, typically obtained from
|
161
|
-
# Shell.Application.windows.
|
162
|
-
def self.bind window
|
163
|
-
ie = new true
|
164
|
-
ie.ie = window
|
165
|
-
ie.initialize_options
|
166
|
-
ie
|
167
206
|
end
|
168
207
|
|
169
|
-
|
170
|
-
|
171
|
-
|
208
|
+
# Used internally to determine when IE has finished loading a page.
|
209
|
+
# @private
|
210
|
+
READYSTATES = {:complete => 4}
|
172
211
|
|
173
|
-
|
174
|
-
|
175
|
-
|
176
|
-
|
177
|
-
|
212
|
+
# The default color for highlighting objects as they are accessed.
|
213
|
+
# @private
|
214
|
+
HIGHLIGHT_COLOR = 'yellow'
|
215
|
+
|
216
|
+
# The time, in seconds, it took for the new page to load after executing
|
217
|
+
# the last command.
|
218
|
+
attr_reader :down_load_time
|
219
|
+
|
220
|
+
# The OLE Internet Explorer object.
|
221
|
+
attr_accessor :ie
|
222
|
+
|
223
|
+
# The list of unique urls that have been visited.
|
224
|
+
attr_reader :url_list
|
225
|
+
|
226
|
+
# @private
|
227
|
+
attr_writer :hwnd
|
228
|
+
|
229
|
+
# Create an IE browser instance.
|
230
|
+
# @param [Boolean] suppress_new_window set to true for not creating a IE
|
231
|
+
# window.
|
232
|
+
def initialize(suppress_new_window=nil)
|
233
|
+
_new_window_init unless suppress_new_window
|
178
234
|
end
|
179
235
|
|
180
|
-
# Specifies the speed that commands will be executed at.
|
236
|
+
# Specifies the speed that commands will be executed at.
|
237
|
+
# Possible choices are:
|
181
238
|
# * :slow (default)
|
182
239
|
# * :fast
|
183
240
|
# * :zippy
|
184
|
-
#
|
185
|
-
#
|
186
|
-
|
241
|
+
#
|
242
|
+
# With :zippy, text fields will be entered at once, instead of
|
243
|
+
# character by character.
|
244
|
+
#
|
245
|
+
# @note :zippy speed does not trigger JavaScript events like onChange etc.
|
246
|
+
#
|
247
|
+
# @param [Symbol] how_fast possible choices are :slow (default), :fast and
|
248
|
+
# :zippy
|
249
|
+
# @raise [ArgumentError] when invalid speed is specified.
|
250
|
+
def speed=(how_fast)
|
187
251
|
case how_fast
|
188
|
-
when :zippy
|
252
|
+
when :zippy
|
189
253
|
@typingspeed = 0
|
190
254
|
@pause_after_wait = 0.01
|
191
255
|
@type_keys = false
|
192
256
|
@speed = :fast
|
193
|
-
when :fast
|
257
|
+
when :fast
|
194
258
|
@typingspeed = 0
|
195
259
|
@pause_after_wait = 0.01
|
196
260
|
@type_keys = true
|
197
261
|
@speed = :fast
|
198
|
-
when :slow
|
262
|
+
when :slow
|
199
263
|
@typingspeed = 0.08
|
200
264
|
@pause_after_wait = 0.1
|
201
265
|
@type_keys = true
|
202
266
|
@speed = :slow
|
203
267
|
else
|
204
|
-
raise ArgumentError, "Invalid speed: #{how_fast}"
|
268
|
+
raise ArgumentError, "Invalid speed: #{how_fast}. Possible choices are :slow, :fast and :zippy."
|
205
269
|
end
|
206
270
|
end
|
207
271
|
|
272
|
+
# @return [Symbol] current speed setting. May be :slow, :fast or :zippy.
|
208
273
|
def speed
|
209
274
|
return @speed if @speed == :slow
|
210
275
|
return @type_keys ? :fast : :zippy
|
211
276
|
end
|
212
277
|
|
213
|
-
# deprecated
|
278
|
+
# @deprecated Use {#speed=} with :fast argument instead.
|
214
279
|
def set_fast_speed
|
280
|
+
Kernel.warn "Deprecated(IE.set_fast_speed) - use Browser#speed = :fast instead."
|
215
281
|
self.speed = :fast
|
216
282
|
end
|
217
283
|
|
218
|
-
# deprecated
|
284
|
+
# @deprecated Use {#speed=} with :slow argument instead.
|
219
285
|
def set_slow_speed
|
286
|
+
Kernel.warn "Deprecated(IE.set_slow_speed) - use Browser#speed = :slow instead."
|
220
287
|
self.speed = :slow
|
221
288
|
end
|
222
289
|
|
290
|
+
# @return [Boolean] true when window is visible, false otherwise.
|
223
291
|
def visible
|
224
292
|
@ie.visible
|
225
293
|
end
|
294
|
+
|
295
|
+
# Set the visibility of IE window.
|
296
|
+
# @param [Boolean] boolean set to true if IE window should be visible, false
|
297
|
+
# otherwise.
|
226
298
|
def visible=(boolean)
|
227
299
|
@ie.visible = boolean if boolean != @ie.visible
|
228
300
|
end
|
229
301
|
|
230
|
-
#
|
231
|
-
#
|
232
|
-
# Watir/Ruby is run under a service (instead of a user).
|
233
|
-
# Yields to the window and its hwnd.
|
234
|
-
def self.each
|
235
|
-
shell = WIN32OLE.new('Shell.Application')
|
236
|
-
ie_browsers = []
|
237
|
-
shell.Windows.each do |window|
|
238
|
-
next unless (window.path =~ /Internet Explorer/ rescue false)
|
239
|
-
next unless (hwnd = window.hwnd rescue false)
|
240
|
-
ie = IE.bind(window)
|
241
|
-
ie.hwnd = hwnd
|
242
|
-
ie_browsers << ie
|
243
|
-
end
|
244
|
-
ie_browsers.each do |ie|
|
245
|
-
yield ie
|
246
|
-
end
|
247
|
-
end
|
248
|
-
|
249
|
-
def self.version
|
250
|
-
@ie_version ||= begin
|
251
|
-
require 'win32/registry'
|
252
|
-
::Win32::Registry::HKEY_LOCAL_MACHINE.open("SOFTWARE\\Microsoft\\Internet Explorer") do |ie_key|
|
253
|
-
ie_key.read('Version').last
|
254
|
-
end
|
255
|
-
# OR: ::WIN32OLE.new("WScript.Shell").RegRead("HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Internet Explorer\\Version")
|
256
|
-
end
|
257
|
-
end
|
258
|
-
|
259
|
-
def self.version_parts
|
260
|
-
version.split('.')
|
261
|
-
end
|
262
|
-
|
263
|
-
# return internet explorer instance as specified. if none is found,
|
264
|
-
# return nil.
|
265
|
-
# arguments:
|
266
|
-
# :url, url -- the URL of the IE browser window
|
267
|
-
# :title, title -- the title of the browser page
|
268
|
-
# :hwnd, hwnd -- the window handle of the browser window.
|
269
|
-
# This method will not work when
|
270
|
-
# Watir/Ruby is run under a service (instead of a user).
|
271
|
-
def self.find(how, what)
|
272
|
-
ie_ole = IE._find(how, what)
|
273
|
-
IE.bind ie_ole if ie_ole
|
274
|
-
end
|
275
|
-
|
276
|
-
def self._find(how, what)
|
277
|
-
self._find_all(how, what).first
|
278
|
-
end
|
279
|
-
|
280
|
-
def self._find_all(how, what)
|
281
|
-
ies = []
|
282
|
-
count = -1
|
283
|
-
IE.each do |ie|
|
284
|
-
window = ie.ie
|
285
|
-
|
286
|
-
case how
|
287
|
-
when :url
|
288
|
-
ies << window if (what.matches(window.locationURL))
|
289
|
-
when :title
|
290
|
-
# normal windows explorer shells do not have document
|
291
|
-
# note window.document will fail for "new" browsers
|
292
|
-
begin
|
293
|
-
title = window.locationname
|
294
|
-
title = window.document.title
|
295
|
-
rescue WIN32OLERuntimeError
|
296
|
-
end
|
297
|
-
ies << window if what.matches(title)
|
298
|
-
when :hwnd
|
299
|
-
begin
|
300
|
-
ies << window if what == window.HWND
|
301
|
-
rescue WIN32OLERuntimeError
|
302
|
-
end
|
303
|
-
when :index
|
304
|
-
count += 1
|
305
|
-
if count == what
|
306
|
-
ies << window
|
307
|
-
break
|
308
|
-
end
|
309
|
-
when nil
|
310
|
-
ies << window
|
311
|
-
else
|
312
|
-
raise ArgumentError
|
313
|
-
end
|
314
|
-
end
|
315
|
-
|
316
|
-
ies
|
317
|
-
end
|
318
|
-
|
319
|
-
# Return the current window handle
|
302
|
+
# @return [Fixnum] current IE window handle.
|
303
|
+
# @raise [RuntimeError] when not attached to a browser.
|
320
304
|
def hwnd
|
321
305
|
raise "Not attached to a browser" if @ie.nil?
|
322
306
|
@hwnd ||= @ie.hwnd
|
323
307
|
end
|
324
|
-
attr_writer :hwnd
|
325
308
|
|
309
|
+
# @return [Symbol] the name of the browser. Is always :ie.
|
326
310
|
def name
|
327
311
|
:ie
|
328
312
|
end
|
329
313
|
|
330
|
-
#
|
314
|
+
# @return [Boolean] true when IE is window exists, false otherwise.
|
331
315
|
def exists?
|
332
|
-
|
333
|
-
|
334
|
-
|
335
|
-
false
|
336
|
-
end
|
316
|
+
!!(@ie.name =~ /Internet Explorer/)
|
317
|
+
rescue WIN32OLERuntimeError, NoMethodError
|
318
|
+
false
|
337
319
|
end
|
338
|
-
alias :exist? :exists?
|
339
320
|
|
340
|
-
|
341
|
-
# Accessing data outside the document
|
342
|
-
#
|
321
|
+
alias :exist? :exists?
|
343
322
|
|
344
|
-
#
|
323
|
+
# @return [String] the title of the document.
|
345
324
|
def title
|
346
325
|
@ie.document.title
|
347
326
|
end
|
348
327
|
|
349
|
-
#
|
328
|
+
# @return [String] the status text of the window, typically from the status bar at the bottom.
|
329
|
+
# Will be empty if there's no status or when there are problems accessing status text.
|
350
330
|
def status
|
351
331
|
@ie.statusText
|
352
332
|
rescue WIN32OLERuntimeError
|
@@ -358,7 +338,8 @@ module Watir
|
|
358
338
|
#
|
359
339
|
|
360
340
|
# Navigate to the specified URL.
|
361
|
-
#
|
341
|
+
# @param [String] url url to navigate to.
|
342
|
+
# @return [Fixnum] time in seconds the page took to load.
|
362
343
|
def goto(url)
|
363
344
|
url = "http://" + url unless url =~ %r{://} || url == "about:blank"
|
364
345
|
@ie.navigate(url)
|
@@ -366,22 +347,22 @@ module Watir
|
|
366
347
|
return @down_load_time
|
367
348
|
end
|
368
349
|
|
369
|
-
# Go to the previous page - the same as clicking the browsers back button
|
370
|
-
#
|
350
|
+
# Go to the previous page - the same as clicking the browsers back button.
|
351
|
+
# @raise [WIN32OLERuntimeError] when the browser can't go back.
|
371
352
|
def back
|
372
353
|
@ie.GoBack
|
373
354
|
wait
|
374
355
|
end
|
375
356
|
|
376
|
-
# Go to the next page - the same as clicking the browsers forward button
|
377
|
-
#
|
357
|
+
# Go to the next page - the same as clicking the browsers forward button.
|
358
|
+
# @raise [WIN32OLERuntimeError] when the browser can't go forward.
|
378
359
|
def forward
|
379
360
|
@ie.GoForward
|
380
361
|
wait
|
381
362
|
end
|
382
363
|
|
383
|
-
# Refresh the current page - the same as clicking the browsers refresh button
|
384
|
-
#
|
364
|
+
# Refresh the current page - the same as clicking the browsers refresh button.
|
365
|
+
# @raise [WIN32OLERuntimeError] when the browser can't refresh.
|
385
366
|
def refresh
|
386
367
|
@ie.refresh2(3)
|
387
368
|
wait
|
@@ -391,12 +372,12 @@ module Watir
|
|
391
372
|
'#<%s:0x%x url=%s title=%s>' % [self.class, hash*2, url.inspect, title.inspect]
|
392
373
|
end
|
393
374
|
|
394
|
-
#
|
375
|
+
# Clear the list of urls that have been visited.
|
395
376
|
def clear_url_list
|
396
377
|
@url_list.clear
|
397
378
|
end
|
398
379
|
|
399
|
-
#
|
380
|
+
# Close the {Browser}.
|
400
381
|
def close
|
401
382
|
return unless exists?
|
402
383
|
@ie.stop
|
@@ -412,95 +393,181 @@ module Watir
|
|
412
393
|
end
|
413
394
|
end
|
414
395
|
|
415
|
-
# Maximize the window (expands to fill the screen)
|
396
|
+
# Maximize the window (expands to fill the screen).
|
416
397
|
def maximize
|
417
398
|
rautomation.maximize
|
418
399
|
end
|
419
400
|
|
420
|
-
# Minimize the window (appears as icon on taskbar)
|
401
|
+
# Minimize the window (appears as icon on taskbar).
|
421
402
|
def minimize
|
422
403
|
rautomation.minimize
|
423
404
|
end
|
424
405
|
|
406
|
+
# @return [Boolean] true when window is minimized, false otherwise.
|
425
407
|
def minimized?
|
426
408
|
rautomation.minimized?
|
427
409
|
end
|
428
410
|
|
429
|
-
# Restore the window (after minimizing or maximizing)
|
411
|
+
# Restore the window (after minimizing or maximizing).
|
430
412
|
def restore
|
431
413
|
rautomation.restore
|
432
414
|
end
|
433
415
|
|
434
|
-
# Make the window come to the front
|
416
|
+
# Make the window come to the front.
|
435
417
|
def activate
|
436
418
|
rautomation.activate
|
437
419
|
end
|
420
|
+
|
438
421
|
alias :bring_to_front :activate
|
439
422
|
|
423
|
+
# @return [Boolean] true when window is in front e.g. in focus, false otherwise.
|
440
424
|
def active?
|
441
425
|
rautomation.active?
|
442
426
|
end
|
427
|
+
|
443
428
|
alias :front? :active?
|
444
429
|
|
430
|
+
# @return [RAutomation::Window] the RAutomation instance for this IE window.
|
431
|
+
# @see https://github.com/jarmo/rautomation
|
445
432
|
def rautomation
|
446
433
|
@rautomation ||= ::RAutomation::Window.new(:hwnd => hwnd)
|
447
|
-
@rautomation
|
448
434
|
end
|
449
435
|
|
436
|
+
# @deprecated use {#rautomation} instead.
|
450
437
|
def autoit
|
451
|
-
Kernel.warn "
|
438
|
+
Kernel.warn "Deprecated(IE#autoit) - use IE#rautomation instead. Refer to https://github.com/jarmo/RAutomation for updating your scripts."
|
452
439
|
@autoit ||= ::RAutomation::Window.new(:hwnd => hwnd, :adapter => :autoit)
|
453
|
-
@autoit
|
454
440
|
end
|
455
441
|
|
456
442
|
# Activates the window and sends keys to it.
|
457
443
|
#
|
458
|
-
#
|
459
|
-
# browser.send_keys("Hello World
|
444
|
+
# @example
|
445
|
+
# browser.send_keys("Hello World", :enter)
|
460
446
|
#
|
461
|
-
#
|
462
|
-
# special characters conversion.
|
463
|
-
# @see RAutomation::Window#send_keys
|
447
|
+
# @see https://github.com/jarmo/RAutomation/blob/master/lib/rautomation/adapter/win_32/window.rb RAutomation::Window#send_keys documentation.
|
464
448
|
def send_keys(*keys)
|
465
449
|
rautomation.send_keys *keys
|
466
450
|
end
|
467
451
|
|
468
|
-
def dir
|
469
|
-
return File.expand_path(File.dirname(__FILE__))
|
470
|
-
end
|
471
|
-
|
472
452
|
#
|
473
453
|
# Document and Document Data
|
474
454
|
#
|
475
455
|
|
476
|
-
#
|
456
|
+
# @return [WIN32OLE] current IE document.
|
477
457
|
def document
|
478
|
-
|
458
|
+
@ie.document
|
479
459
|
end
|
480
460
|
|
481
|
-
#
|
461
|
+
# @return [String] current url, as displayed in the address bar of the browser.
|
482
462
|
def url
|
483
|
-
|
463
|
+
@ie.LocationURL
|
484
464
|
end
|
485
465
|
|
466
|
+
# Create a {Screenshot} instance.
|
486
467
|
def screenshot
|
487
468
|
Screenshot.new(hwnd)
|
488
469
|
end
|
489
470
|
|
471
|
+
# Retrieve a {Window} instance.
|
472
|
+
#
|
473
|
+
# @example Retrieve a different window without block.
|
474
|
+
# browser.window(:title => /other window title/).use
|
475
|
+
# browser.title # => "other window title"
|
476
|
+
#
|
477
|
+
# @example Use different window with block.
|
478
|
+
# browser.window(:title => /other window title/) do
|
479
|
+
# browser.title # => "other window title"
|
480
|
+
# end
|
481
|
+
# browser.title # => "current window title"
|
482
|
+
#
|
483
|
+
# @param [Hash] specifiers options for finding window.
|
484
|
+
# @option specifiers [String,Regexp] :title Title of the window.
|
485
|
+
# @option specifiers [String,Regexp] :url Url of the window.
|
486
|
+
# @option specifiers [Fixnum] :index The index of the window.
|
487
|
+
# @yield yield optionally to the found window.
|
488
|
+
# @return [Window] found window instance.
|
490
489
|
def window(specifiers={}, &blk)
|
491
490
|
win = Window.new(self, specifiers, &blk)
|
492
491
|
win.use &blk if blk
|
493
492
|
win
|
494
493
|
end
|
495
494
|
|
496
|
-
|
497
|
-
|
495
|
+
# @see #window
|
496
|
+
# @return [Array<Window>] array of found windows.
|
497
|
+
def windows(specifiers={})
|
498
|
+
self.class._find_all(specifiers.keys.first, specifiers.values.first).map {|ie| Window.new(self, specifiers, IE.bind(ie))}
|
498
499
|
end
|
499
500
|
|
501
|
+
# Retrieve {Cookies} instance.
|
500
502
|
def cookies
|
501
503
|
Cookies.new(self)
|
502
504
|
end
|
503
505
|
|
506
|
+
# Add an error checker that gets executed after every page load, click etc.
|
507
|
+
#
|
508
|
+
# @example
|
509
|
+
# browser.add_checker lambda { |browser| raise "Error!" if browser.text.include? "Error" }
|
510
|
+
#
|
511
|
+
# @param [Proc] checker Proc object which gets yielded with {IE} instance.
|
512
|
+
def add_checker(checker)
|
513
|
+
@error_checkers << checker
|
514
|
+
end
|
515
|
+
|
516
|
+
# Disable an error checker added via {#add_checker}.
|
517
|
+
#
|
518
|
+
# @param [Proc] checker Proc object to be removed from error checkers.
|
519
|
+
def disable_checker(checker)
|
520
|
+
@error_checkers.delete(checker)
|
521
|
+
end
|
522
|
+
|
523
|
+
# Gives focus to the window frame.
|
524
|
+
def focus
|
525
|
+
active_element = document.activeElement
|
526
|
+
active_element.blur unless active_element.tagName == "BODY"
|
527
|
+
document.focus
|
528
|
+
end
|
529
|
+
|
530
|
+
# @private
|
531
|
+
def attach_command
|
532
|
+
"Watir::IE.attach(:hwnd, #{hwnd})"
|
533
|
+
end
|
534
|
+
|
535
|
+
# @private
|
536
|
+
def _new_window_init
|
537
|
+
create_browser_window
|
538
|
+
initialize_options
|
539
|
+
goto 'about:blank' # this avoids numerous problems caused by lack of a document
|
540
|
+
end
|
541
|
+
|
542
|
+
# @private
|
543
|
+
def _new_process_init
|
544
|
+
iep = Process.start
|
545
|
+
@ie = iep.window
|
546
|
+
@process_id = iep.process_id
|
547
|
+
initialize_options
|
548
|
+
goto 'about:blank'
|
549
|
+
end
|
550
|
+
|
551
|
+
# this method is used internally to attach to an existing window
|
552
|
+
# @private
|
553
|
+
def _attach_init how, what
|
554
|
+
attach_browser_window how, what
|
555
|
+
initialize_options
|
556
|
+
wait
|
557
|
+
end
|
558
|
+
|
559
|
+
# @private
|
560
|
+
def initialize_options
|
561
|
+
self.visible = IE.visible
|
562
|
+
self.speed = IE.speed
|
563
|
+
|
564
|
+
@ole_object = nil
|
565
|
+
@page_container = self
|
566
|
+
@error_checkers = []
|
567
|
+
@active_object_highlight_color = HIGHLIGHT_COLOR
|
568
|
+
@url_list = []
|
569
|
+
end
|
570
|
+
|
504
571
|
#
|
505
572
|
# Synchronization
|
506
573
|
#
|
@@ -508,9 +575,10 @@ module Watir
|
|
508
575
|
# Block execution until the page has loaded.
|
509
576
|
#
|
510
577
|
# Will raise Timeout::Error if page hasn't been loaded within 5 minutes.
|
511
|
-
# =nodoc
|
512
578
|
# Note: This code needs to be prepared for the ie object to be closed at
|
513
579
|
# any moment!
|
580
|
+
#
|
581
|
+
# @private
|
514
582
|
def wait(no_sleep=false)
|
515
583
|
@xml_parser_doc = nil
|
516
584
|
@down_load_time = 0.0
|
@@ -562,34 +630,13 @@ module Watir
|
|
562
630
|
|
563
631
|
# Error checkers
|
564
632
|
|
565
|
-
#
|
633
|
+
# Run the predefined error checks.
|
634
|
+
#
|
635
|
+
# @private
|
566
636
|
def run_error_checks
|
567
637
|
@error_checkers.each { |e| e.call(self) }
|
568
638
|
end
|
569
639
|
|
570
|
-
# this method is used to add an error checker that gets executed on every page load
|
571
|
-
# * checker Proc Object, that contains the code to be run
|
572
|
-
def add_checker(checker)
|
573
|
-
@error_checkers << checker
|
574
|
-
end
|
575
|
-
|
576
|
-
# this allows a checker to be disabled
|
577
|
-
# * checker Proc Object, the checker that is to be disabled
|
578
|
-
def disable_checker(checker)
|
579
|
-
@error_checkers.delete(checker)
|
580
|
-
end
|
581
|
-
|
582
|
-
# Gives focus to the frame
|
583
|
-
def focus
|
584
|
-
active_element = document.activeElement
|
585
|
-
active_element.blur unless active_element.tagName == "BODY"
|
586
|
-
document.focus
|
587
|
-
end
|
588
|
-
|
589
|
-
def attach_command
|
590
|
-
"Watir::IE.attach(:hwnd, #{hwnd})"
|
591
|
-
end
|
592
|
-
|
593
640
|
private
|
594
641
|
|
595
642
|
def create_browser_window
|
@@ -609,5 +656,6 @@ module Watir
|
|
609
656
|
@ie = ieTemp
|
610
657
|
end
|
611
658
|
|
659
|
+
|
612
660
|
end # class IE
|
613
661
|
end
|