class Capybara::Selector

def add(name, &block)

def add(name, &block)
  all[name.to_sym] = Capybara::Selector.new(name.to_sym, &block)
end

def all

def all
  @selectors ||= {} # rubocop:disable Naming/MemoizedInstanceVariableName
end

def builder

Other tags:
    Api: - private
def builder
  case format
  when :css
    Capybara::Selector::CSSBuilder
  when :xpath
    Capybara::Selector::XPathBuilder
  else
    raise NotImplementedError, "No builder exists for selector of type #{format}"
  end
end

def call(locator, selector_config: {}, **options)

def call(locator, selector_config: {}, **options)
  @config.merge! selector_config
  if format
    @expression.call(locator, options)
  else
    warn 'Selector has no format'
  end
end

def css(*allowed_filters, &block)

Returns:
  • (#call) - The block that will be called to generate the CSS selector

Overloads:
  • css()
  • css(*expression_filters, &block)

Other tags:
    Yieldreturn: - An object that can produce a CSS selector

Other tags:
    Yieldparam: options - The options hash passed to the query
    Yieldparam: locator - The locator string passed to the query

Other tags:
    Yield: - The block to use to generate the CSS selector

Parameters:
  • expression_filters (Array) -- ([]) Names of filters that can be implemented via this CSS selector
def css(*allowed_filters, &block)
  if block
    @format, @expression = :css, block
    allowed_filters.flatten.each { |ef| expression_filters[ef] = nil }
  end
  format == :css ? @expression : nil
end

def custom_filters

def custom_filters
  warn "Deprecated: Selector#custom_filters is not valid when same named expression and node filter exist - don't use"
  node_filters.merge(expression_filters).freeze
end

def default_visibility(fallback = Capybara.ignore_hidden_elements, options = {})

def default_visibility(fallback = Capybara.ignore_hidden_elements, options = {})
  vis = if @default_visibility&.respond_to?(:call)
    @default_visibility.call(options)
  else
    @default_visibility
  end
  vis.nil? ? fallback : vis
end

def describe_all_expression_filters(**opts)

def describe_all_expression_filters(**opts)
  expression_filters.map do |ef_name, ef|
    if ef.matcher?
      opts.keys.map do |key|
        " with #{ef_name}[#{key} => #{opts[key]}]" if ef.handles_option?(key) && !::Capybara::Queries::SelectorQuery::VALID_KEYS.include?(key)
      end.join
    elsif opts.key?(ef_name)
      " with #{ef_name} #{opts[ef_name]}"
    end
  end.join
end

def describe_expression_filters(&block)

def describe_expression_filters(&block)
  if block_given?
    describe(:expression_filters, &block)
  else
    describe(:expression_filters) do |**options|
      describe_all_expression_filters(options)
    end
  end
end

def describe_node_filters(&block)

def describe_node_filters(&block)
  describe(:node_filters, &block)
end

def enable_aria_label

def enable_aria_label
  @config[:enable_aria_label]
end

def expression_filters

def expression_filters
  @filter_set.expression_filters
end

def filter_set(name, filters_to_use = nil)

def filter_set(name, filters_to_use = nil)
  @filter_set.import(name, filters_to_use)
end

def find_by_attr(attribute, value)

def find_by_attr(attribute, value)
  finder_name = "find_by_#{attribute}_attr"
  if respond_to?(finder_name, true)
    send(finder_name, value)
  else
    value ? XPath.attr(attribute) == value : nil
  end
end

def find_by_class_attr(classes)

def find_by_class_attr(classes)
  Array(classes).map { |klass| XPath.attr(:class).contains_word(klass) }.reduce(:&)
end

def initialize(name, &block)

def initialize(name, &block)
  @name = name
  @filter_set = FilterSet.add(name) {}
  @match = nil
  @label = nil
  @failure_message = nil
  @format = nil
  @expression = nil
  @expression_filters = {}
  @default_visibility = nil
  @config = {
    enable_aria_label: false,
    test_id: nil
  }
  instance_eval(&block)
end

def label(label = nil)

Returns:
  • (String) - The currently set label

Overloads:
  • label()
  • label(label)

Parameters:
  • label (String) -- A descriptive label for this selector - used in error messages
def label(label = nil)
  @label = label if label
  @label
end

def locate_field(xpath, locator, **_options)

def locate_field(xpath, locator, **_options)
  return xpath if locator.nil?
  locate_xpath = xpath # Need to save original xpath for the label wrap
  locator = locator.to_s
  attr_matchers = [XPath.attr(:id) == locator,
                   XPath.attr(:name) == locator,
                   XPath.attr(:placeholder) == locator,
                   XPath.attr(:id) == XPath.anywhere(:label)[XPath.string.n.is(locator)].attr(:for)].reduce(:|)
  attr_matchers |= XPath.attr(:'aria-label').is(locator) if enable_aria_label
  attr_matchers |= XPath.attr(test_id) == locator if test_id
  locate_xpath = locate_xpath[attr_matchers]
  locate_xpath + XPath.descendant(:label)[XPath.string.n.is(locator)].descendant(xpath)
end

def match(&block)

Returns:
  • (#call) - The block that will be used to detect selector match

Other tags:
    Yieldreturn: - Whether this selector matches the locator string

Other tags:
    Yieldparam: , - locator The locator string used to determin if it matches the selector

Other tags:
    Yield: - This block takes the passed in locator string and returns whether or not it matches the selector
def match(&block)
  @match = block if block
  @match
end

def match?(locator)

Returns:
  • (Boolean) - Whether or not to use this selector

Parameters:
  • locator (String) -- The locator passed to the query
def match?(locator)
  @match&.call(locator)
end

def node_filters

def node_filters
  @filter_set.node_filters
end

def remove(name)

def remove(name)
  all.delete(name.to_sym)
end

def test_id

def test_id
  @config[:test_id]
end

def update(name, &block)

def update(name, &block)
  all[name.to_sym].instance_eval(&block)
end

def visible(default_visibility = nil, &block)

Parameters:
  • default_visibility (Symbol) -- Only find elements with the specified visibility:
def visible(default_visibility = nil, &block)
  @default_visibility = block || default_visibility
end

def xpath(*allowed_filters, &block)

Returns:
  • (#call) - The block that will be called to generate the XPath expression

Overloads:
  • xpath()
  • xpath(*expression_filters, &block)

Other tags:
    Yieldreturn: - An object that can produce an xpath expression

Other tags:
    Yieldparam: options - The options hash passed to the query
    Yieldparam: locator - The locator string passed to the query

Other tags:
    Yield: - The block to use to generate the XPath expression

Parameters:
  • expression_filters (Array) -- ([]) Names of filters that can be implemented via this expression
def xpath(*allowed_filters, &block)
  if block
    @format, @expression = :xpath, block
    allowed_filters.flatten.each { |ef| expression_filters[ef] = Filters::IdentityExpressionFilter.new(ef) }
  end
  format == :xpath ? @expression : nil
end