lib/watir/locators/element/locator.rb in watir-6.11.0 vs lib/watir/locators/element/locator.rb in watir-6.12.0
- old
+ new
@@ -67,12 +67,21 @@
raise Error, "internal error: unable to build Selenium selector from #{@normalized_selector.inspect}"
end
what = add_regexp_predicates(what) if how == :xpath
if filter == :all || !@filter_selector.empty?
- elements = locate_elements(how, what, @driver_scope) || []
- filter_elements(elements, filter: filter)
+ retries = 0
+ begin
+ elements = locate_elements(how, what, @driver_scope) || []
+ filter_elements(elements, filter: filter)
+ rescue Selenium::WebDriver::Error::StaleElementReferenceError
+ retries += 1
+ sleep 0.5
+ retry unless retries > 2
+ target = filter == :all ? "element collection" : "element"
+ raise StandardError, "Unable to locate #{target} from #{@selector} due to changing page"
+ end
else
locate_element(how, what, @driver_scope)
end
end
@@ -81,16 +90,11 @@
end
def fetch_value(element, how)
case how
when :text
- vis = element.text
- all = Watir::Element.new(@query_scope, element: element).send(:execute_js, :getTextContent, element).strip
- unless all == vis.strip
- Watir.logger.deprecate(':text locator with RegExp values to find elements based on only visible text', ":visible_text")
- end
- vis
+ element.text
when :visible
element.displayed?
when :visible_text
element.text
when :tag_name
@@ -123,12 +127,18 @@
return @normalized_selector if @normalized_selector
@driver_scope = ensure_scope_context
@normalized_selector = selector_builder.normalized_selector
- if @normalized_selector[:label]
- process_label
+ if @normalized_selector.key?(:label)
+ label_key = :label
+ elsif @normalized_selector.key?(:visible_label)
+ label_key = :visible_label
+ end
+
+ if label_key
+ process_label(label_key)
return if @normalized_selector.nil?
end
if @normalized_selector.key?(:index) && filter == :all
raise ArgumentError, "can't locate all elements by :index"
@@ -168,14 +178,15 @@
end
@filter_selector
end
- def process_label
- return unless @normalized_selector[:label].kind_of?(Regexp) && selector_builder.should_use_label_element?
+ def process_label(label_key)
+ regexp = @normalized_selector[label_key].kind_of?(Regexp)
+ return unless (regexp || label_key == :visible_label) && selector_builder.should_use_label_element?
- label = label_from_text
+ label = label_from_text(label_key)
unless label # label not found, stop looking for element
@normalized_selector = nil
return
end
@@ -184,27 +195,40 @@
else
@driver_scope = label
end
end
- def label_from_text
+ def label_from_text(label_key)
# TODO: this won't work correctly if @wd is a sub-element, write spec
# TODO: Figure out how to do this with find_element
- label_text = @normalized_selector.delete(:label)
+ label_text = @normalized_selector.delete(label_key)
+ locator_key = label_key.to_s.gsub('label', 'text').to_sym
locate_elements(:tag_name, 'label', @driver_scope).find do |el|
- matches_selector?(el, text: label_text)
+ matches_selector?(el, locator_key => label_text)
end
end
def matches_selector?(element, selector)
- selector.all? do |how, what|
+ matches = selector.all? do |how, what|
if how == :tag_name && what.is_a?(String)
element_validator.validate(element, {tag_name: what})
else
what === fetch_value(element, how)
end
end
+
+ if selector[:text]
+ text_content = Watir::Element.new(@query_scope, element: element).send(:execute_js, :getTextContent, element).strip
+ text_content_matches = selector[:text] === text_content
+ unless matches == text_content_matches
+ key = @selector.key?(:text) ? "text" : "label"
+ Watir.logger.deprecate("Using :#{key} locator with RegExp #{selector[:text].inspect} to match an element that includes hidden text", ":visible_#{key}",
+ ids: [:text_regexp])
+ end
+ end
+
+ matches
end
def can_convert_regexp_to_contains?
true
end
@@ -253,10 +277,10 @@
def wd_supported?(how, what, tag)
return false unless W3C_FINDERS.include? how
return false unless what.kind_of?(String)
if %i[partial_link_text link_text link].include?(how)
- Watir.logger.deprecate(":#{how} locator", ':visible_text')
+ Watir.logger.deprecate(":#{how} locator", ':visible_text', ids: [:visible_text])
return true if [:a, :link, nil].include?(tag)
raise StandardError, "Can not use #{how} locator to find a #{what} element"
elsif how == :tag_name
return true
else