watir 6.15.0 → 6.15.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.rubocop.yml +4 -0
- data/.travis.yml +3 -3
- data/CHANGES.md +8 -0
- data/lib/watir/elements/element.rb +1 -2
- data/lib/watir/elements/select.rb +7 -3
- data/lib/watir/locators/button/selector_builder/xpath.rb +3 -3
- data/lib/watir/locators/element/locator.rb +31 -56
- data/lib/watir/locators/element/selector_builder.rb +29 -63
- data/lib/watir/locators/element/selector_builder/xpath.rb +40 -22
- data/lib/watir/locators/row/selector_builder/xpath.rb +5 -7
- data/lib/watir/locators/text_area/selector_builder/xpath.rb +1 -1
- data/lib/watir/locators/text_field/selector_builder/xpath.rb +1 -1
- data/lib/watir/version.rb +1 -1
- data/lib/watir/wait.rb +5 -5
- data/spec/unit/element_locator_spec.rb +10 -9
- data/spec/watirspec/element_hidden_spec.rb +1 -1
- data/spec/watirspec/elements/dl_spec.rb +3 -3
- data/spec/watirspec/elements/element_spec.rb +1 -13
- data/spec/watirspec/elements/link_spec.rb +1 -1
- data/spec/watirspec/elements/select_list_spec.rb +3 -2
- data/spec/watirspec/elements/text_field_spec.rb +1 -1
- data/spec/watirspec/html/forms_with_input_elements.html +3 -3
- data/spec/watirspec/selector_builder/button_spec.rb +30 -34
- data/spec/watirspec/selector_builder/cell_spec.rb +10 -11
- data/spec/watirspec/selector_builder/element_spec.rb +84 -95
- data/spec/watirspec/selector_builder/row_spec.rb +15 -17
- data/spec/watirspec/selector_builder/text_spec.rb +52 -23
- metadata +2 -2
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA1:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 8c5ac0f3aeeeec1422ef300b30ffc292113a053e
|
|
4
|
+
data.tar.gz: a12b41e42257e86152ffb7e8b3c4e5777e657acf
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 057b9175188bef9121cb6bd5970db44ef90119e57e0c910c4fcec06762f66b9a8f8eebccc627826da31ba40bba0cf999fcf4110d07273b120879f3e93a3f7112
|
|
7
|
+
data.tar.gz: c7e93f0e181b4c11d3b20d7bd91e5a9f3fb4bb0fe8c0a98ad49a8daee676cf8fa35cb41c5d622714c6ee4c5dfc991b6dfbf010bd885b132e55d25d4d7df8c276
|
data/.rubocop.yml
CHANGED
|
@@ -35,6 +35,10 @@ Lint/HandleExceptions:
|
|
|
35
35
|
Exclude:
|
|
36
36
|
- 'lib/watirspec.rb'
|
|
37
37
|
|
|
38
|
+
Lint/UnifiedInteger:
|
|
39
|
+
Exclude:
|
|
40
|
+
- 'lib/watir/locators/element/selector_builder.rb'
|
|
41
|
+
|
|
38
42
|
# Configuration parameters: CountComments, ExcludedMethods.
|
|
39
43
|
# ExcludedMethods: refine
|
|
40
44
|
Metrics/BlockLength:
|
data/.travis.yml
CHANGED
|
@@ -20,13 +20,13 @@ script: bundle exec rake $RAKE_TASK
|
|
|
20
20
|
_version:
|
|
21
21
|
three: &three
|
|
22
22
|
language: ruby
|
|
23
|
-
rvm: 2.3.
|
|
23
|
+
rvm: 2.3.8
|
|
24
24
|
four: &four
|
|
25
25
|
language: ruby
|
|
26
|
-
rvm: 2.4.
|
|
26
|
+
rvm: 2.4.5
|
|
27
27
|
five: &five
|
|
28
28
|
language: ruby
|
|
29
|
-
rvm: 2.5.
|
|
29
|
+
rvm: 2.5.3
|
|
30
30
|
|
|
31
31
|
_browsers:
|
|
32
32
|
firefox: &firefox-latest
|
data/CHANGES.md
CHANGED
|
@@ -1,3 +1,11 @@
|
|
|
1
|
+
### 6.15.1 (2018-12-04)
|
|
2
|
+
|
|
3
|
+
* Locator value type check error message now returns array of allowed class types
|
|
4
|
+
* Wire calls for `:label` locator happen after Selector is built
|
|
5
|
+
* Improve error message for `Watir::Option` element when not found (#823)
|
|
6
|
+
* Wrap `#wd` with `#element_call` to wait for element to exist (#813)
|
|
7
|
+
* Remove automatic element reset in wait loop (#819)
|
|
8
|
+
|
|
1
9
|
### 6.15.0 (2018-11-07)
|
|
2
10
|
|
|
3
11
|
* Add `Element#selected_text`
|
|
@@ -159,7 +159,7 @@ module Watir
|
|
|
159
159
|
return selected_options.first.text if matching_option?(approach.downcase, str_or_rx)
|
|
160
160
|
end
|
|
161
161
|
|
|
162
|
-
|
|
162
|
+
raise_no_value_found(str_or_rx)
|
|
163
163
|
end
|
|
164
164
|
|
|
165
165
|
def process_str_or_rx(str_or_rx)
|
|
@@ -213,9 +213,13 @@ module Watir
|
|
|
213
213
|
# TODO: Remove conditional when remove relaxed_locate toggle
|
|
214
214
|
return @found unless @found.empty?
|
|
215
215
|
|
|
216
|
-
|
|
216
|
+
raise_no_value_found(str_or_rx)
|
|
217
217
|
rescue Wait::TimeoutError
|
|
218
|
-
|
|
218
|
+
raise_no_value_found(str_or_rx)
|
|
219
|
+
end
|
|
220
|
+
|
|
221
|
+
def raise_no_value_found(str_or_rx)
|
|
222
|
+
raise NoValueFoundException, "#{str_or_rx.inspect} not found in #{inspect}"
|
|
219
223
|
end
|
|
220
224
|
|
|
221
225
|
def select_matching(elements)
|
|
@@ -32,7 +32,7 @@ module Watir
|
|
|
32
32
|
string << " and (#{input_types(type)})"
|
|
33
33
|
if text
|
|
34
34
|
string << " and #{process_attribute(:value, text)}"
|
|
35
|
-
@
|
|
35
|
+
@built.delete(:value)
|
|
36
36
|
end
|
|
37
37
|
string
|
|
38
38
|
end
|
|
@@ -49,7 +49,7 @@ module Watir
|
|
|
49
49
|
''
|
|
50
50
|
when Regexp
|
|
51
51
|
res = "[#{predicate_conversion(:text, value)} or #{predicate_conversion(:value, value)}]"
|
|
52
|
-
@
|
|
52
|
+
@built.delete(:text)
|
|
53
53
|
res
|
|
54
54
|
else
|
|
55
55
|
"[#{predicate_expression(:text, value)} or #{predicate_expression(:value, value)}]"
|
|
@@ -58,7 +58,7 @@ module Watir
|
|
|
58
58
|
|
|
59
59
|
def predicate_conversion(key, regexp)
|
|
60
60
|
res = key == :text ? super(:contains_text, regexp) : super
|
|
61
|
-
@
|
|
61
|
+
@built[key] = @built.delete(:contains_text) if @built.key?(:contains_text)
|
|
62
62
|
res
|
|
63
63
|
end
|
|
64
64
|
|
|
@@ -51,33 +51,30 @@ module Watir
|
|
|
51
51
|
end
|
|
52
52
|
|
|
53
53
|
def using_watir(filter = :first)
|
|
54
|
-
|
|
54
|
+
selector = @selector.dup
|
|
55
|
+
raise ArgumentError, "can't locate all elements by :index" if selector.key?(:index) && filter == :all
|
|
55
56
|
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
return nil
|
|
60
|
-
end
|
|
57
|
+
@driver_scope ||= @query_scope.wd
|
|
58
|
+
|
|
59
|
+
built = selector_builder.build(selector)
|
|
61
60
|
|
|
62
|
-
|
|
61
|
+
validate_built_selector(built)
|
|
63
62
|
|
|
64
|
-
|
|
63
|
+
wd_locator = built.select { |key, _value| %i[css xpath link_text partial_link_text].include? key }
|
|
64
|
+
values_to_match = built.reject { |key, _value| %i[css xpath link_text partial_link_text].include? key }
|
|
65
65
|
|
|
66
66
|
if filter == :all || values_to_match.any?
|
|
67
|
-
locate_matching_elements(
|
|
67
|
+
locate_matching_elements(wd_locator, values_to_match, filter)
|
|
68
68
|
else
|
|
69
|
-
locate_element(
|
|
69
|
+
locate_element(wd_locator.keys.first, wd_locator.values.first, @driver_scope)
|
|
70
70
|
end
|
|
71
71
|
end
|
|
72
72
|
|
|
73
|
-
def validate_built_selector(
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
msg = "#{selector_builder.class}#build is not returning expected responses for the current version of Watir"
|
|
79
|
-
raise LocatorException, msg
|
|
80
|
-
end
|
|
73
|
+
def validate_built_selector(built)
|
|
74
|
+
return unless built.nil? || built.empty?
|
|
75
|
+
|
|
76
|
+
msg = "#{selector_builder.class} was unable to build selector from #{@selector.inspect}"
|
|
77
|
+
raise LocatorException, msg
|
|
81
78
|
end
|
|
82
79
|
|
|
83
80
|
def fetch_value(element, how)
|
|
@@ -98,6 +95,19 @@ module Watir
|
|
|
98
95
|
end
|
|
99
96
|
end
|
|
100
97
|
|
|
98
|
+
def matching_labels(elements, values_to_match, scope)
|
|
99
|
+
label_key = values_to_match.key?(:label_element) ? :label_element : :visible_label_element
|
|
100
|
+
label_value = values_to_match.delete(:label_element) || values_to_match.delete(:visible_label_element)
|
|
101
|
+
locator_key = label_key.to_s.gsub('label', 'text').gsub('_element', '').to_sym
|
|
102
|
+
|
|
103
|
+
Watir::LabelCollection.new(scope, tag_name: 'label').map { |label|
|
|
104
|
+
next unless matches_values?(label.wd, locator_key => label_value)
|
|
105
|
+
|
|
106
|
+
input = label.for.empty? ? label.input : Watir::Input.new(scope, id: label.for)
|
|
107
|
+
input.wd if elements.include?(input.wd)
|
|
108
|
+
}.compact
|
|
109
|
+
end
|
|
110
|
+
|
|
101
111
|
def matching_elements(elements, values_to_match, filter: :first)
|
|
102
112
|
if filter == :first
|
|
103
113
|
idx = element_index(elements, values_to_match)
|
|
@@ -124,44 +134,6 @@ module Watir
|
|
|
124
134
|
idx.abs - 1
|
|
125
135
|
end
|
|
126
136
|
|
|
127
|
-
def generate_scope
|
|
128
|
-
return @driver_scope if @driver_scope
|
|
129
|
-
|
|
130
|
-
@driver_scope = @query_scope.wd
|
|
131
|
-
|
|
132
|
-
if @selector.key?(:label)
|
|
133
|
-
process_label :label
|
|
134
|
-
elsif @selector.key?(:visible_label)
|
|
135
|
-
process_label :visible_label
|
|
136
|
-
end
|
|
137
|
-
end
|
|
138
|
-
|
|
139
|
-
def process_label(label_key)
|
|
140
|
-
regexp = @selector[label_key].is_a?(Regexp)
|
|
141
|
-
return unless (regexp || label_key == :visible_label) && selector_builder.should_use_label_element?
|
|
142
|
-
|
|
143
|
-
label = label_from_text(label_key)
|
|
144
|
-
msg = "Unable to locate element with label #{label_key}: #{@selector[label_key]}"
|
|
145
|
-
raise LocatorException, msg unless label
|
|
146
|
-
|
|
147
|
-
id = label.attribute('for')
|
|
148
|
-
if id
|
|
149
|
-
@selector[:id] = id
|
|
150
|
-
else
|
|
151
|
-
@driver_scope = label
|
|
152
|
-
end
|
|
153
|
-
end
|
|
154
|
-
|
|
155
|
-
def label_from_text(label_key)
|
|
156
|
-
# TODO: this won't work correctly if @wd is a sub-element, write spec
|
|
157
|
-
# TODO: Figure out how to do this with find_element
|
|
158
|
-
label_text = @selector.delete(label_key)
|
|
159
|
-
locator_key = label_key.to_s.gsub('label', 'text').gsub('_element', '').to_sym
|
|
160
|
-
locate_elements(:tag_name, 'label', @driver_scope).find do |el|
|
|
161
|
-
matches_values?(el, locator_key => label_text)
|
|
162
|
-
end
|
|
163
|
-
end
|
|
164
|
-
|
|
165
137
|
def matches_values?(element, values_to_match)
|
|
166
138
|
matches = values_to_match.all? do |how, what|
|
|
167
139
|
if how == :tag_name && what.is_a?(String)
|
|
@@ -201,6 +173,9 @@ module Watir
|
|
|
201
173
|
retries = 0
|
|
202
174
|
begin
|
|
203
175
|
elements = locate_elements(selector.keys.first, selector.values.first, @driver_scope) || []
|
|
176
|
+
if values_to_match.key?(:label_element) || values_to_match.key?(:visible_label_element)
|
|
177
|
+
elements = matching_labels(elements, values_to_match, @query_scope)
|
|
178
|
+
end
|
|
204
179
|
matching_elements(elements, values_to_match, filter: filter)
|
|
205
180
|
rescue Selenium::WebDriver::Error::StaleElementReferenceError
|
|
206
181
|
retries += 1
|
|
@@ -5,8 +5,16 @@ module Watir
|
|
|
5
5
|
include Exception
|
|
6
6
|
attr_reader :custom_attributes
|
|
7
7
|
|
|
8
|
-
|
|
9
|
-
|
|
8
|
+
WILDCARD_ATTRIBUTE = /^(aria|data)_(.+)$/.freeze
|
|
9
|
+
INTEGER_CLASS = Gem::Version.new(RUBY_VERSION) < Gem::Version.new('2.4') ? Fixnum : Integer
|
|
10
|
+
VALID_WHATS = Hash.new([String, Regexp, TrueClass, FalseClass]).merge(adjacent: [::Symbol],
|
|
11
|
+
xpath: [String],
|
|
12
|
+
css: [String],
|
|
13
|
+
index: [INTEGER_CLASS],
|
|
14
|
+
visible: [TrueClass, FalseClass],
|
|
15
|
+
tag_name: [String, Regexp, ::Symbol],
|
|
16
|
+
visible_text: [String, Regexp],
|
|
17
|
+
text: [String, Regexp]).freeze
|
|
10
18
|
|
|
11
19
|
def initialize(valid_attributes)
|
|
12
20
|
@valid_attributes = valid_attributes
|
|
@@ -18,21 +26,16 @@ module Watir
|
|
|
18
26
|
@selector = selector
|
|
19
27
|
normalize_selector
|
|
20
28
|
|
|
21
|
-
xpath_css =
|
|
22
|
-
|
|
23
|
-
|
|
29
|
+
xpath_css = @selector.select { |key, _value| %i[xpath css].include? key }
|
|
30
|
+
|
|
31
|
+
raise LocatorException, ":xpath and :css cannot be combined (#{xpath_css})" if xpath_css.size > 1
|
|
24
32
|
|
|
25
|
-
built =
|
|
26
|
-
build_wd_selector(@selector)
|
|
27
|
-
else
|
|
28
|
-
process_xpath_css(xpath_css)
|
|
29
|
-
xpath_css
|
|
30
|
-
end
|
|
33
|
+
built = xpath_css.empty? ? build_wd_selector(@selector) : @selector
|
|
31
34
|
|
|
32
|
-
|
|
35
|
+
built.delete(:index) if built[:index]&.zero?
|
|
33
36
|
|
|
34
37
|
Watir.logger.debug "Converted #{inspected} to #{built}, with #{@selector.inspect} to match"
|
|
35
|
-
|
|
38
|
+
built
|
|
36
39
|
end
|
|
37
40
|
|
|
38
41
|
def normalize_selector
|
|
@@ -53,33 +56,14 @@ module Watir
|
|
|
53
56
|
end
|
|
54
57
|
|
|
55
58
|
def check_type(how, what)
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
when :xpath, :css
|
|
60
|
-
return raise_unless(what, String)
|
|
61
|
-
when :index
|
|
62
|
-
return raise_unless(what, Integer)
|
|
63
|
-
when :visible
|
|
64
|
-
return raise_unless(what, :boolean)
|
|
65
|
-
when :tag_name
|
|
66
|
-
return raise_unless(what, :string_or_regexp_or_symbol)
|
|
67
|
-
when :visible_text, :text
|
|
68
|
-
return raise_unless(what, :string_or_regexp)
|
|
69
|
-
when :class, :class_name
|
|
70
|
-
if what.is_a?(Array)
|
|
71
|
-
raise LocatorException, 'Can not locate elements with an empty Array for :class' if what.empty?
|
|
72
|
-
|
|
73
|
-
what.each do |klass|
|
|
74
|
-
raise_unless(klass, :string_or_regexp)
|
|
75
|
-
end
|
|
76
|
-
return
|
|
77
|
-
end
|
|
78
|
-
end
|
|
79
|
-
|
|
80
|
-
return if VALID_WHATS.any? { |t| what.is_a? t }
|
|
59
|
+
if %i[class class_name].include?(how)
|
|
60
|
+
classes = [what].flatten
|
|
61
|
+
raise LocatorException, "Can not locate elements with an empty Array for :#{how}" if classes.empty?
|
|
81
62
|
|
|
82
|
-
|
|
63
|
+
classes.each { |value| raise_unless(value, VALID_WHATS[how]) }
|
|
64
|
+
else
|
|
65
|
+
raise_unless(what, VALID_WHATS[how])
|
|
66
|
+
end
|
|
83
67
|
end
|
|
84
68
|
|
|
85
69
|
def should_use_label_element?
|
|
@@ -91,14 +75,14 @@ module Watir
|
|
|
91
75
|
def normalize_locator(how, what)
|
|
92
76
|
case how
|
|
93
77
|
when 'text'
|
|
94
|
-
Watir.logger.deprecate "String 'text' as a locator", 'Symbol :text', ids: [
|
|
78
|
+
Watir.logger.deprecate "String 'text' as a locator", 'Symbol :text', ids: [:text_string]
|
|
95
79
|
[:text, what]
|
|
96
80
|
when :tag_name
|
|
97
81
|
what = what.to_s if what.is_a?(::Symbol)
|
|
98
82
|
[how, what]
|
|
99
83
|
when :text, :xpath, :index, :class, :css, :visible, :visible_text, :adjacent
|
|
100
84
|
[how, what]
|
|
101
|
-
when :label
|
|
85
|
+
when :label, :visible_label
|
|
102
86
|
if should_use_label_element?
|
|
103
87
|
["#{how}_element".to_sym, what]
|
|
104
88
|
else
|
|
@@ -122,15 +106,6 @@ module Watir
|
|
|
122
106
|
@custom_attributes << attribute.to_s
|
|
123
107
|
end
|
|
124
108
|
|
|
125
|
-
def process_xpath_css(xpath_css)
|
|
126
|
-
raise LocatorException, ":xpath and :css cannot be combined (#{xpath_css})" if xpath_css.size > 1
|
|
127
|
-
|
|
128
|
-
return if combine_with_xpath_or_css?(@selector)
|
|
129
|
-
|
|
130
|
-
msg = "#{xpath_css.keys.first} cannot be combined with all of these locators (#{@selector.inspect})"
|
|
131
|
-
raise LocatorException, msg
|
|
132
|
-
end
|
|
133
|
-
|
|
134
109
|
# Implement this method when creating a different selector builder
|
|
135
110
|
def build_wd_selector(selector)
|
|
136
111
|
Kernel.const_get("#{self.class.name}::XPath").new.build(selector)
|
|
@@ -152,19 +127,10 @@ module Watir
|
|
|
152
127
|
end
|
|
153
128
|
end
|
|
154
129
|
|
|
155
|
-
def raise_unless(what,
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
[String, Regexp].include?(what.class)
|
|
160
|
-
elsif type == :string_or_regexp_or_symbol
|
|
161
|
-
[String, Regexp, ::Symbol].include?(what.class)
|
|
162
|
-
else
|
|
163
|
-
what.is_a?(type)
|
|
164
|
-
end
|
|
165
|
-
return if valid
|
|
166
|
-
|
|
167
|
-
raise TypeError, "expected #{type}, got #{what.inspect}:#{what.class}"
|
|
130
|
+
def raise_unless(what, types)
|
|
131
|
+
return if types.include?(what.class)
|
|
132
|
+
|
|
133
|
+
raise TypeError, "expected one of #{types}, got #{what.inspect}:#{what.class}"
|
|
168
134
|
end
|
|
169
135
|
end
|
|
170
136
|
end
|
|
@@ -6,12 +6,12 @@ module Watir
|
|
|
6
6
|
include Exception
|
|
7
7
|
include XpathSupport
|
|
8
8
|
|
|
9
|
-
CAN_NOT_BUILD = %i[visible visible_text].freeze
|
|
9
|
+
CAN_NOT_BUILD = %i[visible visible_text visible_label_element].freeze
|
|
10
10
|
|
|
11
11
|
def build(selector)
|
|
12
12
|
@selector = selector
|
|
13
13
|
|
|
14
|
-
@
|
|
14
|
+
@built = (@selector.keys & CAN_NOT_BUILD).each_with_object({}) do |key, hash|
|
|
15
15
|
hash[key] = @selector.delete(key)
|
|
16
16
|
end
|
|
17
17
|
|
|
@@ -24,13 +24,11 @@ module Watir
|
|
|
24
24
|
xpath << class_string
|
|
25
25
|
xpath << text_string
|
|
26
26
|
xpath << additional_string
|
|
27
|
+
xpath << label_element_string
|
|
27
28
|
xpath << attribute_string
|
|
28
29
|
|
|
29
|
-
xpath = index ? add_index(xpath, index) : xpath
|
|
30
|
-
|
|
31
|
-
@selector.merge! @requires_matches
|
|
32
|
-
|
|
33
|
-
{xpath: xpath}
|
|
30
|
+
@built[:xpath] = index ? add_index(xpath, index) : xpath
|
|
31
|
+
@built
|
|
34
32
|
end
|
|
35
33
|
|
|
36
34
|
private
|
|
@@ -108,11 +106,11 @@ module Watir
|
|
|
108
106
|
|
|
109
107
|
deprecate_class_array(class_name) if class_name.is_a?(String) && class_name.strip.include?(' ')
|
|
110
108
|
|
|
111
|
-
@
|
|
109
|
+
@built[:class] = []
|
|
112
110
|
|
|
113
111
|
predicates = [class_name].flatten.map { |value| process_attribute(:class, value) }.compact
|
|
114
112
|
|
|
115
|
-
@
|
|
113
|
+
@built.delete(:class) if @built[:class].empty?
|
|
116
114
|
|
|
117
115
|
predicates.empty? ? '' : "[#{predicates.join(' and ')}]"
|
|
118
116
|
end
|
|
@@ -124,13 +122,38 @@ module Watir
|
|
|
124
122
|
when nil
|
|
125
123
|
''
|
|
126
124
|
when Regexp
|
|
127
|
-
@
|
|
125
|
+
@built[:text] = text
|
|
128
126
|
''
|
|
129
127
|
else
|
|
130
128
|
"[#{predicate_expression(:text, text)}]"
|
|
131
129
|
end
|
|
132
130
|
end
|
|
133
131
|
|
|
132
|
+
def label_element_string
|
|
133
|
+
label = @selector.delete :label_element
|
|
134
|
+
|
|
135
|
+
return '' if label.nil?
|
|
136
|
+
|
|
137
|
+
key = label.is_a?(Regexp) ? :contains_text : :text
|
|
138
|
+
|
|
139
|
+
value = process_attribute(key, label)
|
|
140
|
+
|
|
141
|
+
@built[:label_element] = @built.delete :contains_text if @built.key?(:contains_text)
|
|
142
|
+
|
|
143
|
+
# TODO: This conditional can be removed when we remove this deprecation
|
|
144
|
+
if label.is_a?(Regexp)
|
|
145
|
+
if @built.key?(:label_element)
|
|
146
|
+
dep = "Using :label locator with RegExp #{label} to match an element that includes hidden text"
|
|
147
|
+
Watir.logger.deprecate(dep, ":visible_#{key}", ids: [:text_regexp])
|
|
148
|
+
end
|
|
149
|
+
|
|
150
|
+
@built[:label_element] = label
|
|
151
|
+
''
|
|
152
|
+
else
|
|
153
|
+
"[@id=//label[#{value}]/@for or parent::label[#{value}]]"
|
|
154
|
+
end
|
|
155
|
+
end
|
|
156
|
+
|
|
134
157
|
def attribute_string
|
|
135
158
|
attributes = @selector.keys.map { |key|
|
|
136
159
|
process_attribute(key, @selector.delete(key))
|
|
@@ -143,18 +166,17 @@ module Watir
|
|
|
143
166
|
''
|
|
144
167
|
end
|
|
145
168
|
|
|
146
|
-
# TODO: Remove this on refactor of index
|
|
147
169
|
def add_index(xpath, index)
|
|
148
170
|
if @adjacent
|
|
149
171
|
"#{xpath}[#{index + 1}]"
|
|
150
|
-
elsif index&.positive? && @
|
|
172
|
+
elsif index&.positive? && @built.empty?
|
|
151
173
|
"(#{xpath})[#{index + 1}]"
|
|
152
|
-
elsif index&.negative? && @
|
|
174
|
+
elsif index&.negative? && @built.empty?
|
|
153
175
|
last_value = 'last()'
|
|
154
176
|
last_value << (index + 1).to_s if index < -1
|
|
155
177
|
"(#{xpath})[#{last_value}]"
|
|
156
178
|
else
|
|
157
|
-
@
|
|
179
|
+
@built[:index] = index
|
|
158
180
|
xpath
|
|
159
181
|
end
|
|
160
182
|
end
|
|
@@ -167,7 +189,7 @@ module Watir
|
|
|
167
189
|
end
|
|
168
190
|
|
|
169
191
|
def visible?
|
|
170
|
-
!(@
|
|
192
|
+
!(@built.keys & CAN_NOT_BUILD).empty?
|
|
171
193
|
end
|
|
172
194
|
|
|
173
195
|
def starts_with?(results, regexp)
|
|
@@ -178,9 +200,9 @@ module Watir
|
|
|
178
200
|
return unless results.nil? || requires_matching?(results, regexp)
|
|
179
201
|
|
|
180
202
|
if key == :class
|
|
181
|
-
@
|
|
203
|
+
@built[key] << regexp
|
|
182
204
|
else
|
|
183
|
-
@
|
|
205
|
+
@built[key] = regexp
|
|
184
206
|
end
|
|
185
207
|
end
|
|
186
208
|
|
|
@@ -218,11 +240,7 @@ module Watir
|
|
|
218
240
|
end
|
|
219
241
|
|
|
220
242
|
def equal_pair(key, value)
|
|
221
|
-
if key == :
|
|
222
|
-
# we assume :label means a corresponding label element, not the attribute
|
|
223
|
-
text = "#{lhs_for(:text)}=#{XpathSupport.escape value}"
|
|
224
|
-
"(@id=//label[#{text}]/@for or parent::label[#{text}])"
|
|
225
|
-
elsif key == :class
|
|
243
|
+
if key == :class
|
|
226
244
|
negate_xpath = value =~ /^!/ && value.slice!(0)
|
|
227
245
|
expression = "contains(concat(' ', @class, ' '), #{XpathSupport.escape " #{value} "})"
|
|
228
246
|
|