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