watir-classic 3.3.0 → 3.4.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.
- 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
|