watir-webdriver 0.0.7 → 0.0.8
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/Gemfile +2 -0
- data/Gemfile.lock +48 -0
- data/Rakefile +23 -8
- data/VERSION +1 -1
- data/lib/watir-webdriver.rb +7 -5
- data/lib/watir-webdriver/browser.rb +9 -2
- data/lib/watir-webdriver/browserbot.js +5 -2
- data/lib/watir-webdriver/container.rb +6 -9
- data/lib/watir-webdriver/{collections/element_collection.rb → element_collection.rb} +5 -0
- data/lib/watir-webdriver/elements/button.rb +5 -4
- data/lib/watir-webdriver/{element.rb → elements/element.rb} +29 -5
- data/lib/watir-webdriver/elements/file_field.rb +21 -4
- data/lib/watir-webdriver/elements/frame.rb +1 -1
- data/lib/watir-webdriver/elements/generated.rb +750 -750
- data/lib/watir-webdriver/elements/image.rb +6 -0
- data/lib/watir-webdriver/elements/link.rb +0 -4
- data/lib/watir-webdriver/elements/select.rb +22 -24
- data/lib/watir-webdriver/elements/table_row.rb +11 -1
- data/lib/watir-webdriver/elements/text_field.rb +5 -15
- data/lib/watir-webdriver/extensions/wait.rb +107 -0
- data/lib/watir-webdriver/html/generator.rb +1 -1
- data/lib/watir-webdriver/html/util.rb +1 -10
- data/lib/watir-webdriver/html/visitor.rb +2 -14
- data/lib/watir-webdriver/locators/button_locator.rb +22 -3
- data/lib/watir-webdriver/locators/element_locator.rb +54 -28
- data/lib/watir-webdriver/locators/table_row_locator.rb +3 -1
- data/lib/watir-webdriver/locators/text_field_locator.rb +7 -3
- data/lib/watir-webdriver/window_switching.rb +78 -0
- data/spec/browser_spec.rb +43 -0
- data/spec/container_spec.rb +43 -0
- data/spec/element_locator_spec.rb +305 -0
- data/spec/element_spec.rb +34 -5
- data/spec/html/closeable.html +13 -0
- data/spec/html/data_attributes.html +9 -0
- data/spec/html/wait.html +27 -0
- data/spec/html/window_switching.html +12 -0
- data/spec/input_spec.rb +14 -2
- data/spec/locator_spec_helper.rb +37 -0
- data/spec/spec_helper.rb +3 -0
- data/spec/wait_spec.rb +98 -0
- data/spec/watirspec/area_spec.rb +4 -4
- data/spec/watirspec/browser_spec.rb +37 -35
- data/spec/watirspec/button_spec.rb +22 -17
- data/spec/watirspec/buttons_spec.rb +1 -1
- data/spec/watirspec/checkbox_spec.rb +4 -0
- data/spec/watirspec/checkboxes_spec.rb +1 -1
- data/spec/watirspec/collections_spec.rb +4 -2
- data/spec/watirspec/dd_spec.rb +4 -0
- data/spec/watirspec/dds_spec.rb +1 -1
- data/spec/watirspec/del_spec.rb +4 -0
- data/spec/watirspec/dels_spec.rb +1 -1
- data/spec/watirspec/div_spec.rb +38 -12
- data/spec/watirspec/divs_spec.rb +1 -1
- data/spec/watirspec/dl_spec.rb +20 -6
- data/spec/watirspec/dls_spec.rb +1 -1
- data/spec/watirspec/dt_spec.rb +4 -0
- data/spec/watirspec/dts_spec.rb +1 -1
- data/spec/watirspec/em_spec.rb +4 -0
- data/spec/watirspec/ems_spec.rb +1 -1
- data/spec/watirspec/filefield_spec.rb +37 -2
- data/spec/watirspec/filefields_spec.rb +1 -1
- data/spec/watirspec/font_spec.rb +4 -0
- data/spec/watirspec/form_spec.rb +4 -0
- data/spec/watirspec/forms_spec.rb +6 -4
- data/spec/watirspec/frame_spec.rb +6 -0
- data/spec/watirspec/hidden_spec.rb +5 -4
- data/spec/watirspec/hiddens_spec.rb +1 -1
- data/spec/watirspec/hn_spec.rb +4 -0
- data/spec/watirspec/image_spec.rb +4 -0
- data/spec/watirspec/images_spec.rb +1 -1
- data/spec/watirspec/ins_spec.rb +4 -0
- data/spec/watirspec/inses_spec.rb +1 -1
- data/spec/watirspec/label_spec.rb +4 -0
- data/spec/watirspec/labels_spec.rb +2 -2
- data/spec/watirspec/li_spec.rb +4 -0
- data/spec/watirspec/link_spec.rb +15 -10
- data/spec/watirspec/links_spec.rb +6 -0
- data/spec/watirspec/lis_spec.rb +1 -1
- data/spec/watirspec/map_spec.rb +4 -0
- data/spec/watirspec/maps_spec.rb +1 -1
- data/spec/watirspec/meta_spec.rb +4 -0
- data/spec/watirspec/metas_spec.rb +1 -1
- data/spec/watirspec/ol_spec.rb +23 -9
- data/spec/watirspec/option_spec.rb +19 -7
- data/spec/watirspec/p_spec.rb +4 -0
- data/spec/watirspec/pre_spec.rb +4 -0
- data/spec/watirspec/pres_spec.rb +1 -1
- data/spec/watirspec/ps_spec.rb +1 -1
- data/spec/watirspec/radio_spec.rb +22 -13
- data/spec/watirspec/radios_spec.rb +6 -0
- data/spec/watirspec/select_list_spec.rb +29 -17
- data/spec/watirspec/select_lists_spec.rb +6 -0
- data/spec/watirspec/span_spec.rb +10 -2
- data/spec/watirspec/spans_spec.rb +1 -1
- data/spec/watirspec/strong_spec.rb +14 -4
- data/spec/watirspec/table_body_spec.rb +4 -0
- data/spec/watirspec/table_cell_spec.rb +9 -3
- data/spec/watirspec/table_cells_spec.rb +0 -1
- data/spec/watirspec/table_footer_spec.rb +4 -0
- data/spec/watirspec/table_header_spec.rb +4 -0
- data/spec/watirspec/table_row_spec.rb +15 -7
- data/spec/watirspec/table_rows_spec.rb +2 -2
- data/spec/watirspec/table_spec.rb +13 -7
- data/spec/watirspec/tables_spec.rb +1 -1
- data/spec/watirspec/text_field_spec.rb +21 -12
- data/spec/watirspec/text_fields_spec.rb +6 -0
- data/spec/watirspec/ul_spec.rb +4 -0
- data/spec/window_switching_spec.rb +116 -0
- data/watir-webdriver.gemspec +38 -16
- metadata +51 -27
- data/lib/watir-webdriver/collections/table_row_collection.rb +0 -11
@@ -56,7 +56,7 @@ module Watir
|
|
56
56
|
#
|
57
57
|
|
58
58
|
def select(str_or_rx)
|
59
|
-
select_by :text, str_or_rx
|
59
|
+
select_by :text, str_or_rx
|
60
60
|
end
|
61
61
|
|
62
62
|
#
|
@@ -70,7 +70,7 @@ module Watir
|
|
70
70
|
#
|
71
71
|
|
72
72
|
def select_value(str_or_rx)
|
73
|
-
select_by :value, str_or_rx
|
73
|
+
select_by :value, str_or_rx
|
74
74
|
end
|
75
75
|
|
76
76
|
#
|
@@ -116,25 +116,25 @@ module Watir
|
|
116
116
|
|
117
117
|
private
|
118
118
|
|
119
|
-
def select_by(how, str_or_rx
|
119
|
+
def select_by(how, str_or_rx)
|
120
|
+
assert_exists
|
121
|
+
|
120
122
|
case str_or_rx
|
121
123
|
when String, Numeric
|
122
|
-
select_by_string(how, str_or_rx.to_s
|
124
|
+
select_by_string(how, str_or_rx.to_s)
|
123
125
|
when Regexp
|
124
|
-
select_by_regexp(how, str_or_rx
|
126
|
+
select_by_regexp(how, str_or_rx)
|
125
127
|
else
|
126
|
-
raise
|
128
|
+
raise TypeError, "expected String or Regexp, got #{str_or_rx.inspect}:#{str_or_rx.class}"
|
127
129
|
end
|
128
130
|
end
|
129
131
|
|
130
|
-
def select_by_string(how, string
|
132
|
+
def select_by_string(how, string)
|
131
133
|
xpath = option_xpath_for(how, string)
|
132
|
-
if multiple
|
133
|
-
elements = @element.find_elements(:xpath, xpath)
|
134
134
|
|
135
|
-
|
136
|
-
|
137
|
-
|
135
|
+
if multiple?
|
136
|
+
elements = @element.find_elements(:xpath, xpath)
|
137
|
+
no_value_found(string) if elements.empty?
|
138
138
|
|
139
139
|
elements.each { |e| e.select unless e.selected? }
|
140
140
|
elements.first.text
|
@@ -142,7 +142,7 @@ module Watir
|
|
142
142
|
begin
|
143
143
|
e = @element.find_element(:xpath, xpath)
|
144
144
|
rescue WebDriver::Error::NoSuchElementError
|
145
|
-
|
145
|
+
no_value_found(string)
|
146
146
|
end
|
147
147
|
|
148
148
|
e.select unless e.selected?
|
@@ -151,29 +151,23 @@ module Watir
|
|
151
151
|
end
|
152
152
|
end
|
153
153
|
|
154
|
-
def select_by_regexp(how, exp
|
154
|
+
def select_by_regexp(how, exp)
|
155
155
|
elements = @element.find_elements(:tag_name, 'option')
|
156
|
-
if elements.empty?
|
157
|
-
raise NoValueFoundException, "no options in select list"
|
158
|
-
end
|
156
|
+
no_value_found(nil, "no options in select list") if elements.empty?
|
159
157
|
|
160
|
-
if multiple
|
158
|
+
if multiple?
|
161
159
|
found = elements.select do |e|
|
162
160
|
next unless matches_regexp?(how, e, exp)
|
163
161
|
e.select unless e.selected?
|
164
162
|
true
|
165
163
|
end
|
166
164
|
|
167
|
-
if found.empty?
|
168
|
-
raise NoValueFoundException, "#{exp.inspect} not found in select list"
|
169
|
-
end
|
165
|
+
no_value_found(exp) if found.empty?
|
170
166
|
|
171
167
|
found.first.text
|
172
168
|
else
|
173
169
|
element = elements.find { |e| matches_regexp?(how, e, exp) }
|
174
|
-
unless element
|
175
|
-
raise NoValueFoundException, "#{exp.inspect} not found in select list"
|
176
|
-
end
|
170
|
+
no_value_found(exp) unless element
|
177
171
|
|
178
172
|
element.select unless element.selected?
|
179
173
|
|
@@ -210,6 +204,10 @@ module Watir
|
|
210
204
|
|
211
205
|
''
|
212
206
|
end
|
207
|
+
|
208
|
+
def no_value_found(arg, msg = nil)
|
209
|
+
raise NoValueFoundException, msg || "#{arg.inspect} not found in select list"
|
210
|
+
end
|
213
211
|
end # Select
|
214
212
|
|
215
213
|
module Container
|
@@ -23,4 +23,14 @@ module Watir
|
|
23
23
|
end
|
24
24
|
|
25
25
|
end # TableRow
|
26
|
-
|
26
|
+
|
27
|
+
|
28
|
+
class TableRowCollection < ElementCollection
|
29
|
+
private
|
30
|
+
|
31
|
+
def locator_class
|
32
|
+
@parent.kind_of?(Watir::Table) ? TableRowLocator : super
|
33
|
+
end
|
34
|
+
|
35
|
+
end # TableRowCollection
|
36
|
+
end # Watir
|
@@ -3,6 +3,7 @@ module Watir
|
|
3
3
|
class TextField < Input
|
4
4
|
|
5
5
|
attributes Watir::TextArea.typed_attributes
|
6
|
+
remove_method :type # we want Input#type here, which was overriden by TextArea's attributes
|
6
7
|
|
7
8
|
def self.from(parent, element)
|
8
9
|
type = element.attribute(:type)
|
@@ -14,14 +15,6 @@ module Watir
|
|
14
15
|
super
|
15
16
|
end
|
16
17
|
|
17
|
-
# hacky, but we want Input#type here, which was overriden by TextArea's attributes
|
18
|
-
# so we're *overwriting* that method definition here
|
19
|
-
def type; super; end
|
20
|
-
|
21
|
-
def inspect
|
22
|
-
'#<%s:0x%x located=%s selector=%s>' % [self.class, hash*2, !!@element, selector_string]
|
23
|
-
end
|
24
|
-
|
25
18
|
#
|
26
19
|
# Clear the element, the type in the given value.
|
27
20
|
#
|
@@ -73,13 +66,10 @@ module Watir
|
|
73
66
|
end
|
74
67
|
|
75
68
|
def selector_string
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
s = @selector.dup
|
81
|
-
s[:type] = '(any text type)'
|
82
|
-
s
|
69
|
+
selector = @selector.dup
|
70
|
+
selector[:type] = '(any text type)'
|
71
|
+
selector[:tag_name] = "input or textarea"
|
72
|
+
selector.inspect
|
83
73
|
end
|
84
74
|
end
|
85
75
|
|
@@ -0,0 +1,107 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
module Watir
|
3
|
+
module Wait
|
4
|
+
module_function
|
5
|
+
|
6
|
+
class TimeoutError < StandardError
|
7
|
+
end
|
8
|
+
|
9
|
+
#
|
10
|
+
# Wait until the block evaluates to true or times out.
|
11
|
+
#
|
12
|
+
|
13
|
+
def until(timeout = 30, &block)
|
14
|
+
end_time = ::Time.now + timeout
|
15
|
+
|
16
|
+
until ::Time.now > end_time
|
17
|
+
result = yield(self)
|
18
|
+
return result if result
|
19
|
+
sleep 0.5
|
20
|
+
end
|
21
|
+
|
22
|
+
raise TimeoutError, "timed out after #{timeout} seconds"
|
23
|
+
end
|
24
|
+
|
25
|
+
#
|
26
|
+
# Wait while the block evaluates to true or times out.
|
27
|
+
#
|
28
|
+
|
29
|
+
def while(timeout = 30, &block)
|
30
|
+
end_time = ::Time.now + timeout
|
31
|
+
|
32
|
+
until ::Time.now > end_time
|
33
|
+
return unless yield(self)
|
34
|
+
sleep 0.5
|
35
|
+
end
|
36
|
+
|
37
|
+
raise TimeoutError, "timed out after #{timeout} seconds"
|
38
|
+
end
|
39
|
+
|
40
|
+
end # Wait
|
41
|
+
|
42
|
+
#
|
43
|
+
# Wraps an Element so that any subsequent method calls are
|
44
|
+
# put on hold until the element is present (exists and is visible) on the page.
|
45
|
+
#
|
46
|
+
|
47
|
+
class WhenPresentDecorator
|
48
|
+
def initialize(element, timeout)
|
49
|
+
@element = element
|
50
|
+
@timeout = timeout
|
51
|
+
end
|
52
|
+
|
53
|
+
def method_missing(m, *args, &block)
|
54
|
+
unless @element.respond_to?(m)
|
55
|
+
raise NoMethodError, "undefined method `#{m}' for #{@element.inspect}:#{@element.class}"
|
56
|
+
end
|
57
|
+
|
58
|
+
Watir::Wait.until(@timeout) { @element.present? }
|
59
|
+
|
60
|
+
@element.__send__(m, *args, &block)
|
61
|
+
end
|
62
|
+
end # WhenPresentDecorator
|
63
|
+
|
64
|
+
class Element
|
65
|
+
|
66
|
+
#
|
67
|
+
# Returns true if the element exists and is visible on the page
|
68
|
+
#
|
69
|
+
|
70
|
+
def present?
|
71
|
+
exists? && visible?
|
72
|
+
end
|
73
|
+
|
74
|
+
#
|
75
|
+
# Waits until the element is present.
|
76
|
+
#
|
77
|
+
# Optional argument:
|
78
|
+
#
|
79
|
+
# timeout - seconds to wait before timing out (default: 30)
|
80
|
+
#
|
81
|
+
# browser.button(:id, 'foo').when_present.click
|
82
|
+
# browser.div(:id, 'bar').when_present { |div| ... }
|
83
|
+
# browser.p(:id, 'baz').when_present(60).text
|
84
|
+
#
|
85
|
+
|
86
|
+
def when_present(timeout = 30)
|
87
|
+
if block_given?
|
88
|
+
Watir::Wait.until(timeout) { self.present? }
|
89
|
+
yield self
|
90
|
+
else
|
91
|
+
WhenPresentDecorator.new(self, timeout)
|
92
|
+
end
|
93
|
+
end
|
94
|
+
|
95
|
+
def wait_until_present(timeout = 30)
|
96
|
+
Watir::Wait.until(timeout) { self.present? }
|
97
|
+
end
|
98
|
+
|
99
|
+
def wait_while_present(timeout = 30)
|
100
|
+
Watir::Wait.while(timeout) { self.present? }
|
101
|
+
rescue Selenium::WebDriver::Error::ObsoleteElementError
|
102
|
+
# it's not present
|
103
|
+
end
|
104
|
+
end # Element
|
105
|
+
|
106
|
+
|
107
|
+
end # Watir
|
@@ -104,7 +104,7 @@ CODE
|
|
104
104
|
|
105
105
|
def indent(code, indent = 1)
|
106
106
|
indent_string = " "*indent
|
107
|
-
code.split("\n").map { |line| indent_string + line }.join("\n")
|
107
|
+
code.split("\n").map { |line| line.empty? ? line : indent_string + line }.join("\n")
|
108
108
|
end
|
109
109
|
|
110
110
|
end # Generator
|
@@ -4,7 +4,6 @@ module Watir
|
|
4
4
|
|
5
5
|
module_function
|
6
6
|
|
7
|
-
|
8
7
|
def classify(name)
|
9
8
|
if name =~ /^HTML(.+)Element$/
|
10
9
|
$1
|
@@ -13,16 +12,8 @@ module Watir
|
|
13
12
|
end
|
14
13
|
end
|
15
14
|
|
16
|
-
SPECIALS = {
|
17
|
-
'img' => 'image'
|
18
|
-
}
|
19
|
-
|
20
15
|
def paramify(str)
|
21
|
-
|
22
|
-
SPECIALS[str]
|
23
|
-
else
|
24
|
-
classify(str).snake_case
|
25
|
-
end
|
16
|
+
classify(str).snake_case
|
26
17
|
end
|
27
18
|
|
28
19
|
end # Util
|
@@ -111,22 +111,10 @@ module Watir
|
|
111
111
|
|
112
112
|
attrs = Hash.new { |hash, key| hash[key] = [] }
|
113
113
|
attributes.each do |a|
|
114
|
-
attrs[ruby_type_for(a.type)] << a.name.snake_case
|
114
|
+
attrs[ruby_type_for(a.type)] << a.name.snake_case.to_sym
|
115
115
|
end
|
116
116
|
|
117
|
-
call :attributes, [
|
118
|
-
end
|
119
|
-
|
120
|
-
def identifier_call(tag_name)
|
121
|
-
call :identifier, [literal_hash(:tag_name => tag_name)]
|
122
|
-
end
|
123
|
-
|
124
|
-
def container_call(name)
|
125
|
-
call :container_method, [[:lit, Util.paramify(name).to_sym]]
|
126
|
-
end
|
127
|
-
|
128
|
-
def collection_call(name)
|
129
|
-
call :collection_method, [[:lit, Util.paramify(name).pluralize.to_sym]]
|
117
|
+
call :attributes, [literal_hash(attrs)]
|
130
118
|
end
|
131
119
|
|
132
120
|
def literal_hash(hash)
|
@@ -1,10 +1,23 @@
|
|
1
1
|
module Watir
|
2
2
|
class ButtonLocator < ElementLocator
|
3
3
|
|
4
|
+
VALID_TYPES = %w[button reset submit image]
|
5
|
+
|
4
6
|
def locate_all
|
5
7
|
find_all_by_multiple
|
6
8
|
end
|
7
9
|
|
10
|
+
private
|
11
|
+
|
12
|
+
def wd_find_first_by(how, what)
|
13
|
+
if how == :tag_name
|
14
|
+
how = :xpath
|
15
|
+
what = ".//button | .//input[#{attribute_expression :type => VALID_TYPES}]"
|
16
|
+
end
|
17
|
+
|
18
|
+
super
|
19
|
+
end
|
20
|
+
|
8
21
|
def build_xpath(selectors)
|
9
22
|
return if selectors.values.any? { |e| e.kind_of? Regexp }
|
10
23
|
|
@@ -14,7 +27,7 @@ module Watir
|
|
14
27
|
button_attr_exp = attribute_expression(selectors)
|
15
28
|
|
16
29
|
@building = :input
|
17
|
-
selectors[:type] =
|
30
|
+
selectors[:type] = VALID_TYPES
|
18
31
|
input_attr_exp = attribute_expression(selectors)
|
19
32
|
|
20
33
|
xpath = ".//button"
|
@@ -37,7 +50,7 @@ module Watir
|
|
37
50
|
end
|
38
51
|
end
|
39
52
|
|
40
|
-
def matches_selector?(
|
53
|
+
def matches_selector?(element, rx_selector)
|
41
54
|
rx_selector = rx_selector.dup
|
42
55
|
|
43
56
|
[:value, :caption].each do |key|
|
@@ -53,5 +66,11 @@ module Watir
|
|
53
66
|
def tag_name_matches?(element, _)
|
54
67
|
!!(/^(input|button)$/ === element.tag_name)
|
55
68
|
end
|
69
|
+
|
70
|
+
def validate_element(element)
|
71
|
+
return if element.tag_name == "input" && !VALID_TYPES.include?(element.attribute(:type))
|
72
|
+
super
|
73
|
+
end
|
74
|
+
|
56
75
|
end # ButtonLocator
|
57
|
-
end # Watir
|
76
|
+
end # Watir
|
@@ -30,10 +30,14 @@ module Watir
|
|
30
30
|
end
|
31
31
|
|
32
32
|
if @selector.size == 1
|
33
|
-
find_first_by_one
|
33
|
+
element = find_first_by_one
|
34
34
|
else
|
35
|
-
find_first_by_multiple
|
35
|
+
element = find_first_by_multiple
|
36
36
|
end
|
37
|
+
|
38
|
+
# this actually only applies when finding by xpath - browser.text_field(:xpath, "//input[@type='radio']")
|
39
|
+
# we don't need to validate the element if we built the xpath ourselves.
|
40
|
+
validate_element(element) if element
|
37
41
|
rescue WebDriver::Error::NoSuchElementError => wde
|
38
42
|
nil
|
39
43
|
end
|
@@ -46,25 +50,27 @@ module Watir
|
|
46
50
|
end
|
47
51
|
end
|
48
52
|
|
53
|
+
private
|
54
|
+
|
49
55
|
def find_first_by_one
|
50
|
-
how, what = @selector.
|
56
|
+
how, what = @selector.to_a.first
|
51
57
|
check_type how, what
|
52
58
|
|
53
59
|
if WD_FINDERS.include?(how)
|
54
60
|
wd_find_first_by(how, what)
|
55
61
|
else
|
56
|
-
|
62
|
+
find_first_by_multiple
|
57
63
|
end
|
58
64
|
end
|
59
65
|
|
60
66
|
def find_all_by_one
|
61
|
-
how, what = @selector.
|
67
|
+
how, what = @selector.to_a.first
|
62
68
|
check_type how, what
|
63
69
|
|
64
70
|
if WD_FINDERS.include?(how)
|
65
71
|
wd_find_all_by(how, what)
|
66
72
|
else
|
67
|
-
|
73
|
+
find_all_by_multiple
|
68
74
|
end
|
69
75
|
end
|
70
76
|
|
@@ -95,7 +101,7 @@ module Watir
|
|
95
101
|
selector = normalized_selector
|
96
102
|
|
97
103
|
if selector.has_key? :index
|
98
|
-
raise
|
104
|
+
raise ArgumentError, "can't locate all elements by :index"
|
99
105
|
end
|
100
106
|
|
101
107
|
xpath = selector[:xpath] || build_xpath(selector)
|
@@ -110,7 +116,7 @@ module Watir
|
|
110
116
|
if what.kind_of? String
|
111
117
|
@wd.find_element(how, what)
|
112
118
|
else
|
113
|
-
all_elements.find { |
|
119
|
+
all_elements.find { |element| fetch_value(element, how) =~ what }
|
114
120
|
end
|
115
121
|
end
|
116
122
|
|
@@ -118,7 +124,7 @@ module Watir
|
|
118
124
|
if what.kind_of? String
|
119
125
|
@wd.find_elements(how, what)
|
120
126
|
else
|
121
|
-
all_elements.select { |
|
127
|
+
all_elements.select { |element| fetch_value(element, how) =~ what }
|
122
128
|
end
|
123
129
|
end
|
124
130
|
|
@@ -126,45 +132,55 @@ module Watir
|
|
126
132
|
rx_selector = delete_regexps_from(selector)
|
127
133
|
|
128
134
|
if rx_selector.has_key?(:label) && should_use_label_element?
|
129
|
-
|
130
|
-
label = @wd.find_elements(:tag_name, 'label').find { |e| matches_selector?({:text => label_exp}, e) } || return
|
131
|
-
|
132
|
-
selector[:id] = label.attribute(:for)
|
135
|
+
selector[:id] = id_from_label(rx_selector.delete(:label)) || return
|
133
136
|
end
|
134
137
|
|
135
|
-
xpath = build_xpath(selector) || raise("internal error: unable to build xpath from #{
|
138
|
+
xpath = build_xpath(selector) || raise("internal error: unable to build xpath from #{selector.inspect}")
|
136
139
|
|
137
140
|
elements = @wd.find_elements(:xpath, xpath)
|
138
|
-
elements.
|
141
|
+
elements.__send__(method) { |el| matches_selector?(el, rx_selector) }
|
139
142
|
end
|
140
143
|
|
144
|
+
VALID_WHATS = [String, Regexp]
|
145
|
+
|
141
146
|
def check_type(how, what)
|
142
147
|
case how
|
143
148
|
when :index
|
144
|
-
|
149
|
+
unless what.kind_of?(Fixnum)
|
150
|
+
raise TypeError, "expected Fixnum, got #{what.inspect}:#{what.class}"
|
151
|
+
end
|
145
152
|
else
|
146
|
-
unless
|
147
|
-
raise TypeError, "expected
|
153
|
+
unless VALID_WHATS.any? { |t| what.kind_of? t }
|
154
|
+
raise TypeError, "expected one of #{VALID_WHATS.inspect}, got #{what.inspect}:#{what.class}"
|
148
155
|
end
|
149
156
|
end
|
150
157
|
end
|
151
158
|
|
152
|
-
def
|
159
|
+
def id_from_label(label_exp)
|
160
|
+
# TODO: this won't work correctly if @wd is a sub-element
|
161
|
+
label = @wd.find_elements(:tag_name, 'label').find do |el|
|
162
|
+
matches_selector?(el, :text => label_exp)
|
163
|
+
end
|
164
|
+
|
165
|
+
label.attribute(:for) if label
|
166
|
+
end
|
167
|
+
|
168
|
+
def fetch_value(element, how)
|
153
169
|
case how
|
154
170
|
when :text
|
155
171
|
element.text
|
156
172
|
when :tag_name
|
157
173
|
element.tag_name
|
174
|
+
when :href
|
175
|
+
(href = element.attribute(:href)) && href.strip
|
158
176
|
else
|
159
177
|
element.attribute(how)
|
160
178
|
end
|
161
179
|
end
|
162
180
|
|
163
|
-
def matches_selector?(
|
164
|
-
# p :start => selector
|
181
|
+
def matches_selector?(element, selector)
|
165
182
|
selector.all? do |how, what|
|
166
|
-
|
167
|
-
what === fetch_value(how, element)
|
183
|
+
what === fetch_value(element, how)
|
168
184
|
end
|
169
185
|
end
|
170
186
|
|
@@ -183,13 +199,12 @@ module Watir
|
|
183
199
|
|
184
200
|
def normalize_selector(how, what)
|
185
201
|
case how
|
186
|
-
when :url
|
187
|
-
[:href, what]
|
188
202
|
when :caption
|
189
203
|
[:text, what]
|
190
204
|
when :class_name
|
191
205
|
[:class, what]
|
192
|
-
when :tag_name, :text, :xpath, :index, :class
|
206
|
+
when :tag_name, :text, :xpath, :index, :class
|
207
|
+
# include class since the valid attribute is 'class_name'
|
193
208
|
[how, what]
|
194
209
|
else
|
195
210
|
assert_valid_as_attribute how
|
@@ -210,7 +225,7 @@ module Watir
|
|
210
225
|
end
|
211
226
|
|
212
227
|
def assert_valid_as_attribute(attribute)
|
213
|
-
unless valid_attribute? attribute
|
228
|
+
unless valid_attribute? attribute or attribute.to_s =~ /^data_.+$/
|
214
229
|
raise MissingWayOfFindingObjectException, "invalid attribute: #{attribute.inspect}"
|
215
230
|
end
|
216
231
|
end
|
@@ -272,7 +287,7 @@ module Watir
|
|
272
287
|
def attribute_expression(selectors)
|
273
288
|
selectors.map do |key, val|
|
274
289
|
if val.kind_of?(Array)
|
275
|
-
"(
|
290
|
+
"(" + val.map { |v| equal_pair(key, v) }.join(" or ") + ")"
|
276
291
|
else
|
277
292
|
equal_pair(key, val)
|
278
293
|
end
|
@@ -300,5 +315,16 @@ module Watir
|
|
300
315
|
end
|
301
316
|
end
|
302
317
|
|
318
|
+
def validate_element(element)
|
319
|
+
tn = @selector[:tag_name]
|
320
|
+
return if tn && !tag_name_matches?(element, tn)
|
321
|
+
|
322
|
+
if element.tag_name == 'input'
|
323
|
+
return if @selector[:type] && @selector[:type] != element.attribute(:type)
|
324
|
+
end
|
325
|
+
|
326
|
+
element
|
327
|
+
end
|
328
|
+
|
303
329
|
end # ElementLocator
|
304
330
|
end # Watir
|