123456789_123456789_123456789_123456789_123456789_

Class: Capybara::Queries::SelectorQuery Private

Relationships & Source Files
Namespace Children
Classes:
Extension / Inclusion / Inheritance Descendants
Subclasses:
Super Chains via Extension / Inclusion / Inheritance
Class Chain:
self, BaseQuery
Instance Chain:
self, BaseQuery
Inherits: Capybara::Queries::BaseQuery
Defined in: lib/capybara/queries/selector_query.rb

Constant Summary

BaseQuery - Inherited

COUNT_KEYS

Class Method Summary

Instance Attribute Summary

BaseQuery - Inherited

#expects_none?

Checks if a count of 0 is valid for the query Returns false if query does not have any count options specified.

#options, #session_options, #session_options=, #count_specified?

Instance Method Summary

BaseQuery - Inherited

#failure_message

Generates a failure message from the query description and count options.

#matches_count?

Checks if the given count matches the query count options.

#negative_failure_message, #wait, #assert_valid_keys, #count_message, #occurrences

Constructor Details

.new(*args, session_options:, enable_aria_label: session_options.enable_aria_label, enable_aria_role: session_options.enable_aria_role, test_id: session_options.test_id, selector_format: nil, order: nil, **options, &filter_block) ⇒ SelectorQuery

Raises:

  • (ArgumentError)
[ GitHub ]

  
# File 'lib/capybara/queries/selector_query.rb', line 15

def initialize(*args,
               session_options:,
               enable_aria_label: session_options.enable_aria_label,
               enable_aria_role: session_options.enable_aria_role,
               test_id: session_options.test_id,
               selector_format: nil,
               order: nil,
               **options,
               &filter_block)
  @resolved_node = nil
  @resolved_count = 0
  @options = options.dup
  @order = order
  @filter_cache = Hash.new { |hsh, key| hsh[key] = {} }

  if @options[:text].is_a?(Regexp) && [true, false].include?(@options[:exact_text])
    Capybara::Helpers.warn(
      "Boolean 'exact_text' option is not supported when 'text' option is a Regexp - ignoring"
    )
  end

  super(@options)
  self.session_options = session_options

  @selector = Selector.new(
    find_selector(args[0].is_a?(Symbol) ? args.shift : args[0]),
    config: {
      enable_aria_label: enable_aria_label,
      enable_aria_role: enable_aria_role,
      test_id: test_id
    },
    format: selector_format
  )

  @locator = args.shift
  @filter_block = filter_block

  raise ArgumentError, "Unused parameters passed to #{self.class.name} : #{args}" unless args.empty?

  @expression = selector.call(@locator, **@options)

  warn_exact_usage

  assert_valid_keys
end

Instance Attribute Details

#describe_within?Boolean (readonly, private)

[ GitHub ]

  
# File 'lib/capybara/queries/selector_query.rb', line 422

def describe_within?
  @resolved_node && !document?(@resolved_node) && !simple_root?(@resolved_node)
end

#exact?Boolean (readonly)

[ GitHub ]

  
# File 'lib/capybara/queries/selector_query.rb', line 138

def exact?
  supports_exact? ? options.fetch(:exact, session_options.exact) : false
end

#expression (readonly)

[ GitHub ]

  
# File 'lib/capybara/queries/selector_query.rb', line 8

attr_reader :expression, :selector, :locator, :options

#first_try?Boolean (readonly, private)

[ GitHub ]

  
# File 'lib/capybara/queries/selector_query.rb', line 221

def first_try?
  @resolved_count == 1
end

#locator (readonly)

[ GitHub ]

  
# File 'lib/capybara/queries/selector_query.rb', line 8

attr_reader :expression, :selector, :locator, :options

#need_to_process_classes?Boolean (readonly, private)

[ GitHub ]

  
# File 'lib/capybara/queries/selector_query.rb', line 517

def need_to_process_classes?
  case options[:class]
  when Regexp then true
  when Array then options[:class].any?(Regexp)
  else
    false
  end
end

#options (readonly)

[ GitHub ]

  
# File 'lib/capybara/queries/selector_query.rb', line 8

attr_reader :expression, :selector, :locator, :options

#selector (readonly)

[ GitHub ]

  
# File 'lib/capybara/queries/selector_query.rb', line 8

attr_reader :expression, :selector, :locator, :options

#supports_exact?Boolean (readonly)

This method is for internal use only.
[ GitHub ]

  
# File 'lib/capybara/queries/selector_query.rb', line 173

def supports_exact?
  return @expression.respond_to? :to_xpath if @selector.supports_exact?.nil?

  @selector.supports_exact?
end

#try_text_match_in_expression?Boolean (readonly, private)

[ GitHub ]

  
# File 'lib/capybara/queries/selector_query.rb', line 214

def try_text_match_in_expression?
  first_try? &&
    matching_text &&
    @resolved_node.is_a?(Capybara::Node::Base) &&
    @resolved_node.session&.driver&.wait?
end

#use_default_class_filter?Boolean (readonly, private)

[ GitHub ]

  
# File 'lib/capybara/queries/selector_query.rb', line 375

def use_default_class_filter?
  options.key?(:class) && !custom_keys.include?(:class)
end

#use_default_focused_filter?Boolean (readonly, private)

[ GitHub ]

  
# File 'lib/capybara/queries/selector_query.rb', line 383

def use_default_focused_filter?
  options.key?(:focused) && !custom_keys.include?(:focused)
end

#use_default_id_filter?Boolean (readonly, private)

[ GitHub ]

  
# File 'lib/capybara/queries/selector_query.rb', line 371

def use_default_id_filter?
  options.key?(:id) && !custom_keys.include?(:id)
end

#use_default_style_filter?Boolean (readonly, private)

[ GitHub ]

  
# File 'lib/capybara/queries/selector_query.rb', line 379

def use_default_style_filter?
  options.key?(:style) && !custom_keys.include?(:style)
end

#use_spatial_filter?Boolean (readonly, private)

[ GitHub ]

  
# File 'lib/capybara/queries/selector_query.rb', line 387

def use_spatial_filter?
  options.values_at(*SPATIAL_KEYS).compact.any?
end

Instance Method Details

#applied_description

[ GitHub ]

  
# File 'lib/capybara/queries/selector_query.rb', line 114

def applied_description
  description(true)
end

#applied_filters (private)

[ GitHub ]

  
# File 'lib/capybara/queries/selector_query.rb', line 231

def applied_filters
  @applied_filters ||= []
end

#apply_expression_filters(expression) (private)

[ GitHub ]

  
# File 'lib/capybara/queries/selector_query.rb', line 391

def apply_expression_filters(expression)
  unapplied_options = options.keys - valid_keys
  expression_filters.inject(expression) do |expr, (name, ef)|
    next expr unless apply_filter?(ef)

    if ef.matcher?
      unapplied_options.select(&ef.method(:handles_option?)).inject(expr) do |memo, option_name|
        unapplied_options.delete(option_name)
        ef.apply_filter(memo, option_name, options[option_name], @selector)
      end
    elsif options.key?(name)
      unapplied_options.delete(name)
      ef.apply_filter(expr, name, options[name], @selector)
    elsif ef.default?
      ef.apply_filter(expr, name, ef.default, @selector)
    else
      expr
    end
  end
end

#apply_filter?(filter) ⇒ Boolean (private)

[ GitHub ]

  
# File 'lib/capybara/queries/selector_query.rb', line 434

def apply_filter?(filter)
  filter.format.nil? || (filter.format == selector_format)
end

#assert_valid_keys (private)

Raises:

  • (ArgumentError)
[ GitHub ]

  
# File 'lib/capybara/queries/selector_query.rb', line 345

def assert_valid_keys
  unless VALID_MATCH.include?(match)
    raise ArgumentError, "Invalid option #{match.inspect} for :match, should be one of #{VALID_MATCH.map(&:inspect).join(', ')}"
  end

  unhandled_options = @options.keys.reject do |option_name|
    valid_keys.include?(option_name) ||
      expression_filters.any? { |_name, ef| ef.handles_option? option_name } ||
      node_filters.any? { |_name, nf| nf.handles_option? option_name }
  end

  return if unhandled_options.empty?

  invalid_names = unhandled_options.map(&:inspect).join(', ')
  valid_names = (valid_keys - [:allow_self]).map(&:inspect).join(', ')
  raise ArgumentError, "Invalid option(s) #{invalid_names}, should be one of #{valid_names}"
end

#builder(expr) (private)

[ GitHub ]

  
# File 'lib/capybara/queries/selector_query.rb', line 614

def builder(expr)
  selector.builder(expr)
end

#css

[ GitHub ]

  
# File 'lib/capybara/queries/selector_query.rb', line 155

def css
  filtered_expression(apply_expression_filters(@expression))
end

#custom_keys (private)

[ GitHub ]

  
# File 'lib/capybara/queries/selector_query.rb', line 341

def custom_keys
  @custom_keys ||= node_filters.keys + expression_filters.keys
end

#default_visibility (private)

[ GitHub ]

  
# File 'lib/capybara/queries/selector_query.rb', line 610

def default_visibility
  @selector.default_visibility(session_options.ignore_hidden_elements, options)
end

#description(only_applied = false)

[ GitHub ]

  
# File 'lib/capybara/queries/selector_query.rb', line 64

def description(only_applied = false) # rubocop:disable Style/OptionalBooleanParameter
  desc = +''
  show_for = show_for_stage(only_applied)

  if show_for[:any]
    desc << 'visible ' if visible == :visible
    desc << 'non-visible ' if visible == :hidden
  end

  desc << label.to_s
  desc << " #{locator.inspect}" unless locator.nil?

  if show_for[:any]
    desc << " with#{' exact' if exact_text == true} text #{options[:text].inspect}" if options[:text]
    desc << " with exact text #{exact_text}" if exact_text.is_a?(String)
  end

  desc << " with id #{options[:id]}" if options[:id]
  desc << " with classes [#{Array(options[:class]).join(',')}]" if options[:class]
  desc << ' that is focused' if options[:focused]
  desc << ' that is not focused' if options[:focused] == false

  desc << case options[:style]
  when String
    " with style attribute #{options[:style].inspect}"
  when Regexp
    " with style attribute matching #{options[:style].inspect}"
  when Hash
    " with styles #{options[:style].inspect}"
  else ''
  end

  %i[above below left_of right_of near].each do |spatial_filter|
    if options[spatial_filter] && show_for[:spatial]
      desc << " #{spatial_filter} #{options[spatial_filter] rescue '<ERROR>'}" # rubocop:disable Style/RescueModifier
    end
  end

  desc << selector.description(node_filters: show_for[:node], **options)

  desc << ' that also matches the custom filter block' if @filter_block && show_for[:node]

  desc << " within #{@resolved_node.inspect}" if describe_within?
  if locator.is_a?(String) && locator.start_with?('#', './/', '//') && !selector.raw_locator?
    desc << "\nNote: It appears you may be passing a CSS selector or XPath expression rather than a locator. " \
            "Please see the documentation for acceptable locator values.\n\n"
  end
  desc
end

#document?(node) ⇒ Boolean (private)

[ GitHub ]

  
# File 'lib/capybara/queries/selector_query.rb', line 426

def document?(node)
  node.is_a?(::Capybara::Node::Document)
end

#exact_text (private)

[ GitHub ]

  
# File 'lib/capybara/queries/selector_query.rb', line 418

def exact_text
  options.fetch(:exact_text, session_options.exact_text)
end

#expression_filters (private)

[ GitHub ]

  
# File 'lib/capybara/queries/selector_query.rb', line 326

def expression_filters
  filters = @selector.expression_filters
  filters.merge filter_set(options[:filter_set]).expression_filters if options.key?(:filter_set)
  filters
end

#failure_message

[ GitHub ]

  
# File 'lib/capybara/queries/selector_query.rb', line 179

def failure_message
  +"expected to find #{applied_description}" << count_message
end

#filter_set(name) (private)

[ GitHub ]

  
# File 'lib/capybara/queries/selector_query.rb', line 314

def filter_set(name)
  ::Capybara::Selector::FilterSet[name]
end

#filtered_expression(expr) (private)

[ GitHub ]

  
# File 'lib/capybara/queries/selector_query.rb', line 363

def filtered_expression(expr)
  conditions = {}
  conditions[:id] = options[:id] if use_default_id_filter?
  conditions[:class] = options[:class] if use_default_class_filter?
  conditions[:style] = options[:style] if use_default_style_filter? && !options[:style].is_a?(Hash)
  builder(expr).add_attribute_conditions(**conditions)
end

#find_nodes_by_selector_format(node, exact) (private)

[ GitHub ]

  
# File 'lib/capybara/queries/selector_query.rb', line 242

def find_nodes_by_selector_format(node, exact)
  hints = {}
  hints[:uses_visibility] = true unless visible == :all
  hints[:texts] = text_fragments unless selector_format == :xpath
  hints[:styles] = options[:style] if use_default_style_filter?
  hints[:position] = true if use_spatial_filter?

  case selector_format
  when :css
    if node.method(:find_css).arity == 1
      node.find_css(css)
    else
      node.find_css(css, **hints)
    end
  when :xpath
    if node.method(:find_xpath).arity == 1
      node.find_xpath(xpath(exact))
    else
      node.find_xpath(xpath(exact), **hints)
    end
  else
    raise ArgumentError, "Unknown format: #{selector_format}"
  end
end

#find_selector(locator) (private)

[ GitHub ]

  
# File 'lib/capybara/queries/selector_query.rb', line 235

def find_selector(locator)
  case locator
  when Symbol then Selector[locator]
  else Selector.for(locator)
  end || Selector[session_options.default_selector]
end

#label

[ GitHub ]

  
# File 'lib/capybara/queries/selector_query.rb', line 62

def label; selector.label || selector.name; end

#match

[ GitHub ]

  
# File 'lib/capybara/queries/selector_query.rb', line 142

def match
  options.fetch(:match, session_options.match)
end

#matches_class_filter?(node) ⇒ Boolean (private)

[ GitHub ]

  
# File 'lib/capybara/queries/selector_query.rb', line 498

def matches_class_filter?(node)
  return true unless use_default_class_filter? && need_to_process_classes?

  if options[:class].is_a? Regexp
    options[:class].match? node[:class]
  else
    classes = (node[:class] || '').split
    options[:class].select { |c| c.is_a? Regexp }.all? do |r|
      classes.any? { |cls| r.match? cls }
    end
  end
end

#matches_exact_text_filter?(node) ⇒ Boolean (private)

[ GitHub ]

  
# File 'lib/capybara/queries/selector_query.rb', line 557

def matches_exact_text_filter?(node)
  case exact_text
  when String, Regexp
    matches_text_exactly?(node, exact_text)
  else
    true
  end
end

#matches_filter_block?(node) ⇒ Boolean (private)

[ GitHub ]

  
# File 'lib/capybara/queries/selector_query.rb', line 304

def matches_filter_block?(node)
  return true unless @filter_block

  if node.respond_to?(:session)
    node.session.using_wait_time(0) { @filter_block.call(node) }
  else
    @filter_block.call(node)
  end
end

#matches_filters?(node, node_filter_errors = []) ⇒ Boolean

[ GitHub ]

  
# File 'lib/capybara/queries/selector_query.rb', line 118

def matches_filters?(node, node_filter_errors = [])
  return true if (@resolved_node&.== node) && options[:allow_self]

  matches_locator_filter?(node) &&
    matches_system_filters?(node) &&
    matches_spatial_filters?(node) &&
    matches_node_filters?(node, node_filter_errors) &&
    matches_filter_block?(node)
rescue *(node.respond_to?(:session) ? node.session.driver.invalid_element_errors : [])
  false
end

#matches_focused_filter?(node) ⇒ Boolean (private)

[ GitHub ]

  
# File 'lib/capybara/queries/selector_query.rb', line 511

def matches_focused_filter?(node)
  return true unless use_default_focused_filter?

  (node == node.session.active_element) == options[:focused]
end

#matches_id_filter?(node) ⇒ Boolean (private)

[ GitHub ]

  
# File 'lib/capybara/queries/selector_query.rb', line 492

def matches_id_filter?(node)
  return true unless use_default_id_filter? && options[:id].is_a?(Regexp)

  options[:id].match? node[:id]
end

#matches_locator_filter?(node) ⇒ Boolean (private)

[ GitHub ]

  
# File 'lib/capybara/queries/selector_query.rb', line 438

def matches_locator_filter?(node)
  return true unless @selector.locator_filter && apply_filter?(@selector.locator_filter)

  @selector.locator_filter.matches?(node, @locator, @selector, exact: exact?)
end

#matches_node_filters?(node, errors) ⇒ Boolean (private)

[ GitHub ]

  
# File 'lib/capybara/queries/selector_query.rb', line 279

def matches_node_filters?(node, errors)
  applied_filters << :node

  unapplied_options = options.keys - valid_keys
  @selector.with_filter_errors(errors) do
    node_filters.all? do |filter_name, filter|
      next true unless apply_filter?(filter)

      if filter.matcher?
        unapplied_options.select { |option_name| filter.handles_option?(option_name) }.all? do |option_name|
          unapplied_options.delete(option_name)
          filter.matches?(node, option_name, options[option_name], @selector)
        end
      elsif options.key?(filter_name)
        unapplied_options.delete(filter_name)
        filter.matches?(node, filter_name, options[filter_name], @selector)
      elsif filter.default?
        filter.matches?(node, filter_name, filter.default, @selector)
      else
        true
      end
    end
  end
end

#matches_spatial_filters?(node) ⇒ Boolean (private)

[ GitHub ]

  
# File 'lib/capybara/queries/selector_query.rb', line 456

def matches_spatial_filters?(node)
  applied_filters << :spatial
  return true unless use_spatial_filter?

  node_rect = Rectangle.new(node.initial_cache[:position] || node.rect)

  if options[:above]
    el_rect = rect_cache(options[:above])
    return false unless node_rect.above? el_rect
  end

  if options[:below]
    el_rect = rect_cache(options[:below])
    return false unless node_rect.below? el_rect
  end

  if options[:left_of]
    el_rect = rect_cache(options[:left_of])
    return false unless node_rect.left_of? el_rect
  end

  if options[:right_of]
    el_rect = rect_cache(options[:right_of])
    return false unless node_rect.right_of? el_rect
  end

  if options[:near]
    return false if node == options[:near]

    el_rect = rect_cache(options[:near])
    return false unless node_rect.near? el_rect
  end

  true
end

#matches_style?(node, styles) ⇒ Boolean (private)

[ GitHub ]

  
# File 'lib/capybara/queries/selector_query.rb', line 537

def matches_style?(node, styles)
  @actual_styles = node.initial_cache[:style] || node.style(*styles.keys)
  styles.all? do |style, value|
    if value.is_a? Regexp
      value.match? @actual_styles[style.to_s]
    else
      @actual_styles[style.to_s] == value
    end
  end
end

#matches_style_filter?(node) ⇒ Boolean (private)

[ GitHub ]

  
# File 'lib/capybara/queries/selector_query.rb', line 526

def matches_style_filter?(node)
  case options[:style]
  when String, nil
    true
  when Regexp
    options[:style].match? node[:style]
  when Hash
    matches_style?(node, options[:style])
  end
end

#matches_system_filters?(node) ⇒ Boolean (private)

[ GitHub ]

  
# File 'lib/capybara/queries/selector_query.rb', line 444

def matches_system_filters?(node)
  applied_filters << :system

  matches_visibility_filters?(node) &&
    matches_id_filter?(node) &&
    matches_class_filter?(node) &&
    matches_style_filter?(node) &&
    matches_focused_filter?(node) &&
    matches_text_filter?(node) &&
    matches_exact_text_filter?(node)
end

#matches_text_exactly?(node, value) ⇒ Boolean (private)

[ GitHub ]

  
# File 'lib/capybara/queries/selector_query.rb', line 591

def matches_text_exactly?(node, value)
  regexp = value.is_a?(Regexp) ? value : /\A#{Regexp.escape(value.to_s)}\z/
  matches_text_regexp(node, regexp).then { |m| m&.pre_match == '' && m&.post_match == '' }
end

#matches_text_filter?(node) ⇒ Boolean (private)

[ GitHub ]

  
# File 'lib/capybara/queries/selector_query.rb', line 548

def matches_text_filter?(node)
  value = options[:text]
  return true unless value
  return matches_text_exactly?(node, value) if exact_text == true && !value.is_a?(Regexp)

  regexp = value.is_a?(Regexp) ? value : Regexp.escape(value.to_s)
  matches_text_regexp?(node, regexp)
end

#matches_text_regexp(node, regexp) (private)

[ GitHub ]

  
# File 'lib/capybara/queries/selector_query.rb', line 600

def matches_text_regexp(node, regexp)
  text_visible = visible
  text_visible = :all if text_visible == :hidden
  node.text(text_visible, normalize_ws: normalize_ws).match(regexp)
end

#matches_text_regexp?(node, regexp) ⇒ Boolean (private)

[ GitHub ]

  
# File 'lib/capybara/queries/selector_query.rb', line 606

def matches_text_regexp?(node, regexp)
  !matches_text_regexp(node, regexp).nil?
end

#matches_visibility_filters?(node) ⇒ Boolean (private)

[ GitHub ]

  
# File 'lib/capybara/queries/selector_query.rb', line 566

def matches_visibility_filters?(node)
  obscured = options[:obscured]
  return (visible != :hidden) && (node.initial_cache[:visible] != false) && !node.obscured? if obscured == false

  vis = case visible
  when :visible
    node.initial_cache[:visible] || (node.initial_cache[:visible].nil? && node.visible?)
  when :hidden
    # TODO: check why the 'visbile' cache spelling mistake wasn't caught in a test
    # (node.initial_cache[:visible] == false) || (node.initial_cache[:visbile].nil? && !node.visible?)
    (node.initial_cache[:visible] == false) || (node.initial_cache[:visible].nil? && !node.visible?)
  else
    true
  end

  vis && case obscured
         when true
           node.obscured?
         when false
           !node.obscured?
         else
           true
         end
end

#matching_text (private)

[ GitHub ]

  
# File 'lib/capybara/queries/selector_query.rb', line 193

def matching_text
  options[:text] || options[:exact_text]
end

#name

[ GitHub ]

  
# File 'lib/capybara/queries/selector_query.rb', line 61

def name; selector.name; end

#negative_failure_message

[ GitHub ]

  
# File 'lib/capybara/queries/selector_query.rb', line 183

def negative_failure_message
  +"expected not to find #{applied_description}" << count_message
end

#node_filters (private)

[ GitHub ]

  
# File 'lib/capybara/queries/selector_query.rb', line 318

def node_filters
  if options.key?(:filter_set)
    filter_set(options[:filter_set])
  else
    @selector
  end.node_filters
end

#normalize_ws (private)

[ GitHub ]

  
# File 'lib/capybara/queries/selector_query.rb', line 596

def normalize_ws
  options.fetch(:normalize_ws, session_options.default_normalize_ws)
end

#ordered_results(results) (private)

[ GitHub ]

  
# File 'lib/capybara/queries/selector_query.rb', line 332

def ordered_results(results)
  case @order
  when :reverse
    results.reverse
  else
    results
  end
end

#position_cache(key) (private)

[ GitHub ]

  
# File 'lib/capybara/queries/selector_query.rb', line 618

def position_cache(key)
  @filter_cache[key][:position] ||= key.rect
end

#rect_cache(key) (private)

[ GitHub ]

  
# File 'lib/capybara/queries/selector_query.rb', line 622

def rect_cache(key)
  @filter_cache[key][:rect] ||= Rectangle.new(position_cache(key))
end

#resolve_for(node, exact = nil)

This method is for internal use only.
[ GitHub ]

  
# File 'lib/capybara/queries/selector_query.rb', line 160

def resolve_for(node, exact = nil)
  applied_filters.clear
  @filter_cache.clear
  @resolved_node = node
  @resolved_count += 1

  node.synchronize do
    children = find_nodes_by_selector_format(node, exact).map(&method(:to_element))
    Capybara::Result.new(ordered_results(children), self)
  end
end

#selector_format (private)

[ GitHub ]

  
# File 'lib/capybara/queries/selector_query.rb', line 189

def selector_format
  @selector.format
end

#show_for_stage(only_applied) (private)

[ GitHub ]

  
# File 'lib/capybara/queries/selector_query.rb', line 225

def show_for_stage(only_applied)
  lambda do |stage = :any|
    !only_applied || (stage == :any ? applied_filters.any? : applied_filters.include?(stage))
  end
end

#simple_root?(node) ⇒ Boolean (private)

[ GitHub ]

  
# File 'lib/capybara/queries/selector_query.rb', line 430

def simple_root?(node)
  node.is_a?(::Capybara::Node::Simple) && node.path == '/'
end

#text_fragments (private)

[ GitHub ]

  
# File 'lib/capybara/queries/selector_query.rb', line 197

def text_fragments
  (text = matching_text).is_a?(String) ? text.split : []
end

#to_element(node) (private)

[ GitHub ]

  
# File 'lib/capybara/queries/selector_query.rb', line 267

def to_element(node)
  if @resolved_node.is_a?(Capybara::Node::Base)
    Capybara::Node::Element.new(@resolved_node.session, node, @resolved_node, self)
  else
    Capybara::Node::Simple.new(node)
  end
end

#valid_keys (private)

[ GitHub ]

  
# File 'lib/capybara/queries/selector_query.rb', line 275

def valid_keys
  (VALID_KEYS + custom_keys).uniq
end

#visible

[ GitHub ]

  
# File 'lib/capybara/queries/selector_query.rb', line 130

def visible
  case (vis = options.fetch(:visible) { default_visibility })
  when true then :visible
  when false then :all
  else vis
  end
end

#warn_exact_usage (private)

[ GitHub ]

  
# File 'lib/capybara/queries/selector_query.rb', line 412

def warn_exact_usage
  return unless options.key?(:exact) && !supports_exact?

  warn "The :exact option only has an effect on queries using the XPath#is method. Using it with the query \"#{expression}\" has no effect."
end

#xpath(exact = nil)

[ GitHub ]

  
# File 'lib/capybara/queries/selector_query.rb', line 146

def xpath(exact = nil)
  exact = exact? if exact.nil?
  expr = apply_expression_filters(@expression)
  expr = exact ? expr.to_xpath(:exact) : expr.to_s if expr.respond_to?(:to_xpath)
  expr = filtered_expression(expr)
  expr = "(#{expr})[#{xpath_text_conditions}]" if try_text_match_in_expression?
  expr
end

#xpath_text_conditions (private)

[ GitHub ]

  
# File 'lib/capybara/queries/selector_query.rb', line 201

def xpath_text_conditions
  case (text = matching_text)
  when String
    text.split.map { |txt| XPath.contains(txt) }.reduce(&:&)
  when Regexp
    condition = XPath.current
    condition = condition.uppercase if text.casefold?
    Selector::RegexpDisassembler.new(text).alternated_substrings.map do |strs|
      strs.flat_map(&:split).map { |str| condition.contains(str) }.reduce(:&)
    end.reduce(:|)
  end
end