lib/watir/locators/element/selector_builder.rb in watir-6.15.0 vs lib/watir/locators/element/selector_builder.rb in watir-6.15.1

- old
+ new

@@ -3,12 +3,20 @@ class Element class SelectorBuilder include Exception attr_reader :custom_attributes - VALID_WHATS = [String, Regexp, TrueClass, FalseClass].freeze - WILDCARD_ATTRIBUTE = /^(aria|data)_(.+)$/ + WILDCARD_ATTRIBUTE = /^(aria|data)_(.+)$/.freeze + INTEGER_CLASS = Gem::Version.new(RUBY_VERSION) < Gem::Version.new('2.4') ? Fixnum : Integer + VALID_WHATS = Hash.new([String, Regexp, TrueClass, FalseClass]).merge(adjacent: [::Symbol], + xpath: [String], + css: [String], + index: [INTEGER_CLASS], + visible: [TrueClass, FalseClass], + tag_name: [String, Regexp, ::Symbol], + visible_text: [String, Regexp], + text: [String, Regexp]).freeze def initialize(valid_attributes) @valid_attributes = valid_attributes @custom_attributes = [] end @@ -16,25 +24,20 @@ def build(selector) inspected = selector.inspect @selector = selector normalize_selector - xpath_css = (@selector.keys & %i[xpath css]).each_with_object({}) do |key, hash| - hash[key] = @selector.delete(key) - end + xpath_css = @selector.select { |key, _value| %i[xpath css].include? key } - built = if xpath_css.empty? - build_wd_selector(@selector) - else - process_xpath_css(xpath_css) - xpath_css - end + raise LocatorException, ":xpath and :css cannot be combined (#{xpath_css})" if xpath_css.size > 1 - @selector.delete(:index) if @selector[:index]&.zero? + built = xpath_css.empty? ? build_wd_selector(@selector) : @selector + built.delete(:index) if built[:index]&.zero? + Watir.logger.debug "Converted #{inspected} to #{built}, with #{@selector.inspect} to match" - [built, @selector] + built end def normalize_selector if @selector.key?(:class) && @selector.key?(:class_name) raise LocatorException, 'Can not use both :class and :class_name locators' @@ -51,37 +54,18 @@ @selector[how] = what end end def check_type(how, what) - case how - when :adjacent - return raise_unless(what, ::Symbol) - when :xpath, :css - return raise_unless(what, String) - when :index - return raise_unless(what, Integer) - when :visible - return raise_unless(what, :boolean) - when :tag_name - return raise_unless(what, :string_or_regexp_or_symbol) - when :visible_text, :text - return raise_unless(what, :string_or_regexp) - when :class, :class_name - if what.is_a?(Array) - raise LocatorException, 'Can not locate elements with an empty Array for :class' if what.empty? + if %i[class class_name].include?(how) + classes = [what].flatten + raise LocatorException, "Can not locate elements with an empty Array for :#{how}" if classes.empty? - what.each do |klass| - raise_unless(klass, :string_or_regexp) - end - return - end + classes.each { |value| raise_unless(value, VALID_WHATS[how]) } + else + raise_unless(what, VALID_WHATS[how]) end - - return if VALID_WHATS.any? { |t| what.is_a? t } - - raise TypeError, "expected one of #{VALID_WHATS.inspect}, got #{what.inspect}:#{what.class}" end def should_use_label_element? !valid_attribute?(:label) end @@ -89,18 +73,18 @@ private def normalize_locator(how, what) case how when 'text' - Watir.logger.deprecate "String 'text' as a locator", 'Symbol :text', ids: ['text_string'] + Watir.logger.deprecate "String 'text' as a locator", 'Symbol :text', ids: [:text_string] [:text, what] when :tag_name what = what.to_s if what.is_a?(::Symbol) [how, what] when :text, :xpath, :index, :class, :css, :visible, :visible_text, :adjacent [how, what] - when :label + when :label, :visible_label if should_use_label_element? ["#{how}_element".to_sym, what] else [how, what] end @@ -120,19 +104,10 @@ return if valid_attribute?(attribute) || attribute.to_s =~ WILDCARD_ATTRIBUTE @custom_attributes << attribute.to_s end - def process_xpath_css(xpath_css) - raise LocatorException, ":xpath and :css cannot be combined (#{xpath_css})" if xpath_css.size > 1 - - return if combine_with_xpath_or_css?(@selector) - - msg = "#{xpath_css.keys.first} cannot be combined with all of these locators (#{@selector.inspect})" - raise LocatorException, msg - end - # Implement this method when creating a different selector builder def build_wd_selector(selector) Kernel.const_get("#{self.class.name}::XPath").new.build(selector) end @@ -150,22 +125,13 @@ else false end end - def raise_unless(what, type) - valid = if type == :boolean - [TrueClass, FalseClass].include?(what.class) - elsif type == :string_or_regexp - [String, Regexp].include?(what.class) - elsif type == :string_or_regexp_or_symbol - [String, Regexp, ::Symbol].include?(what.class) - else - what.is_a?(type) - end - return if valid + def raise_unless(what, types) + return if types.include?(what.class) - raise TypeError, "expected #{type}, got #{what.inspect}:#{what.class}" + raise TypeError, "expected one of #{types}, got #{what.inspect}:#{what.class}" end end end end end