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