Sha256: d716eec224f119dffa0e9f3946962260879694ee26fe3a63a1854d0a0b550bba

Contents?: true

Size: 1.95 KB

Versions: 13

Compression:

Stored size: 1.95 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)
          return xp if conditions.nil?

          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).reject { |c| c.is_a? Regexp }.map do |klass|
            if klass.match?(/^!(?!!!)/)
              !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

13 entries across 8 versions & 2 rubygems

Version Path
tdiary-5.2.0 vendor/bundle/ruby/2.7.0/gems/capybara-3.35.3/lib/capybara/selector/builders/xpath_builder.rb
tdiary-5.1.7 vendor/bundle/ruby/2.7.0/gems/capybara-3.35.3/lib/capybara/selector/builders/xpath_builder.rb
tdiary-5.1.7 vendor/bundle/ruby/3.0.0/gems/capybara-3.35.3/lib/capybara/selector/builders/xpath_builder.rb
tdiary-5.1.6 vendor/bundle/ruby/2.7.0/gems/capybara-3.35.3/lib/capybara/selector/builders/xpath_builder.rb
tdiary-5.1.6 vendor/bundle/ruby/2.7.0/gems/tdiary-5.1.5/vendor/bundle/ruby/2.7.0/gems/capybara-3.35.3/lib/capybara/selector/builders/xpath_builder.rb
tdiary-5.1.6 vendor/bundle/ruby/2.7.0/gems/tdiary-5.1.5/vendor/bundle/ruby/3.0.0/gems/capybara-3.35.3/lib/capybara/selector/builders/xpath_builder.rb
tdiary-5.1.6 vendor/bundle/ruby/3.0.0/gems/capybara-3.35.3/lib/capybara/selector/builders/xpath_builder.rb
tdiary-5.1.5 vendor/bundle/ruby/2.7.0/gems/capybara-3.35.3/lib/capybara/selector/builders/xpath_builder.rb
tdiary-5.1.5 vendor/bundle/ruby/3.0.0/gems/capybara-3.35.3/lib/capybara/selector/builders/xpath_builder.rb
capybara-3.35.3 lib/capybara/selector/builders/xpath_builder.rb
capybara-3.35.2 lib/capybara/selector/builders/xpath_builder.rb
capybara-3.35.1 lib/capybara/selector/builders/xpath_builder.rb
capybara-3.35.0 lib/capybara/selector/builders/xpath_builder.rb