Sha256: dc481e35ef87233d59342a651a751a862719c2b77d63bcc3ac1fe806bf81fc9e

Contents?: true

Size: 1.91 KB

Versions: 24

Compression:

Stored size: 1.91 KB

Contents

# frozen_string_literal: true

require 'xpath'

module Capybara
  class Selector
    # @api private
    class XPathBuilder
      def initialize(expression)
        @expression = expression || ''
      end

      attr_reader :expression

      def add_attribute_conditions(**conditions)
        @expression = conditions.inject(expression) do |xp, (name, value)|
          conditions = name == :class ? class_conditions(value) : attribute_conditions(name => value)
          if xp.is_a? XPath::Expression
            xp[conditions]
          else
            "(#{xp})[#{conditions}]"
          end
        end
      end

    private

      def attribute_conditions(attributes)
        attributes.map do |attribute, value|
          case value
          when XPath::Expression
            XPath.attr(attribute)[value]
          when Regexp
            XPath.attr(attribute)[regexp_to_xpath_conditions(value)]
          when true
            XPath.attr(attribute)
          when false, nil
            !XPath.attr(attribute)
          else
            XPath.attr(attribute) == value.to_s
          end
        end.reduce(:&)
      end

      def class_conditions(classes)
        case classes
        when XPath::Expression, Regexp
          attribute_conditions(class: classes)
        else
          Array(classes).map do |klass|
            if klass.start_with?('!') && !klass.start_with?('!!!')
              !XPath.attr(:class).contains_word(klass.slice(1..-1))
            else
              XPath.attr(:class).contains_word(klass.sub(/^!!/, ''))
            end
          end.reduce(:&)
        end
      end

      def regexp_to_xpath_conditions(regexp)
        condition = XPath.current
        condition = condition.uppercase if regexp.casefold?
        Selector::RegexpDisassembler.new(regexp).alternated_substrings.map do |strs|
          strs.map { |str| condition.contains(str) }.reduce(:&)
        end.reduce(:|)
      end
    end
  end
end

Version data entries

24 entries across 24 versions & 2 rubygems

Version Path
capybara-3.24.0 lib/capybara/selector/builders/xpath_builder.rb
capybara-3.23.0 lib/capybara/selector/builders/xpath_builder.rb
capybara-3.22.0 lib/capybara/selector/builders/xpath_builder.rb
capybara-3.21.0 lib/capybara/selector/builders/xpath_builder.rb
capybara-3.20.2 lib/capybara/selector/builders/xpath_builder.rb
capybara-3.20.1 lib/capybara/selector/builders/xpath_builder.rb
capybara-3.20.0 lib/capybara/selector/builders/xpath_builder.rb
capybara-3.19.1 lib/capybara/selector/builders/xpath_builder.rb
capybara-3.19.0 lib/capybara/selector/builders/xpath_builder.rb
capybara-3.18.0 lib/capybara/selector/builders/xpath_builder.rb
capybara-3.15.1 lib/capybara/selector/builders/xpath_builder.rb
capybara-3.17.0 lib/capybara/selector/builders/xpath_builder.rb
capybara-3.16.2 lib/capybara/selector/builders/xpath_builder.rb
tdiary-5.0.13 vendor/bundle/gems/capybara-3.15.0/lib/capybara/selector/builders/xpath_builder.rb
capybara-3.16.1 lib/capybara/selector/builders/xpath_builder.rb
tdiary-5.0.12.1 vendor/bundle/gems/capybara-3.15.0/lib/capybara/selector/builders/xpath_builder.rb
capybara-3.16.0 lib/capybara/selector/builders/xpath_builder.rb
capybara-3.15.0 lib/capybara/selector/builders/xpath_builder.rb
capybara-3.14.0 lib/capybara/selector/builders/xpath_builder.rb
capybara-3.13.2 lib/capybara/selector/builders/xpath_builder.rb