lib/rails/dom/testing/assertions/selector_assertions/html_selector.rb in rails-dom-testing-2.1.1 vs lib/rails/dom/testing/assertions/selector_assertions/html_selector.rb in rails-dom-testing-2.2.0

- old
+ new

@@ -1,122 +1,132 @@ -require 'minitest' -require 'active_support' -require 'active_support/core_ext/module/attribute_accessors' -require_relative 'substitution_context' +# frozen_string_literal: true -class HTMLSelector #:nodoc: - attr_reader :css_selector, :tests, :message +require "minitest" - include Minitest::Assertions +require_relative "substitution_context" - def initialize(values, previous_selection = nil, &root_fallback) - @values = values - @root = extract_root(previous_selection, root_fallback) - extract_selectors - @tests = extract_equality_tests - @message = @values.shift +module Rails + module Dom + module Testing + module Assertions + module SelectorAssertions + class HTMLSelector # :nodoc: + attr_reader :css_selector, :tests, :message - if @message.is_a?(Hash) - raise ArgumentError, "Last argument was a Hash, which would be used for the assertion message. You probably want this to be a String, or you have the wrong type of arguments." - end + include Minitest::Assertions - if @values.shift - raise ArgumentError, "Not expecting that last argument, you either have too many arguments, or they're the wrong type" - end - end + def initialize(values, previous_selection = nil, &root_fallback) + @values = values + @root = extract_root(previous_selection, root_fallback) + extract_selectors + @tests = extract_equality_tests + @message = @values.shift - def selecting_no_body? #:nodoc: - # Nokogiri gives the document a body element. Which means we can't - # run an assertion expecting there to not be a body. - @selector == 'body' && @tests[:count] == 0 - end + if @message.is_a?(Hash) + raise ArgumentError, "Last argument was a Hash, which would be used for the assertion message. You probably want this to be a String, or you have the wrong type of arguments." + end - def select - filter @root.css(@selector, context) - end + if @values.shift + raise ArgumentError, "Not expecting that last argument, you either have too many arguments, or they're the wrong type" + end + end - private + def selecting_no_body? # :nodoc: + # Nokogiri gives the document a body element. Which means we can't + # run an assertion expecting there to not be a body. + @selector == "body" && @tests[:count] == 0 + end - NO_STRIP = %w{pre script style textarea} + def select + filter @root.css(@selector, context) + end - mattr_reader(:context) { SubstitutionContext.new } + private + NO_STRIP = %w{pre script style textarea} - def filter(matches) - match_with = tests[:text] || tests[:html] - return matches if matches.empty? || !match_with + mattr_reader(:context) { SubstitutionContext.new } - content_mismatch = nil - text_matches = tests.has_key?(:text) - regex_matching = match_with.is_a?(Regexp) + def filter(matches) + match_with = tests[:text] || tests[:html] + return matches if matches.empty? || !match_with - remaining = matches.reject do |match| - # Preserve markup with to_s for html elements - content = text_matches ? match.text : match.children.to_s + content_mismatch = nil + text_matches = tests.has_key?(:text) + regex_matching = match_with.is_a?(Regexp) - content.strip! unless NO_STRIP.include?(match.name) - content.sub!(/\A\n/, '') if text_matches && match.name == "textarea" + remaining = matches.reject do |match| + # Preserve markup with to_s for html elements + content = text_matches ? match.text : match.children.to_s - next if regex_matching ? (content =~ match_with) : (content == match_with) - content_mismatch ||= diff(match_with, content) - true - end + content.strip! unless NO_STRIP.include?(match.name) + content.delete_prefix!("\n") if text_matches && match.name == "textarea" - @message ||= content_mismatch if remaining.empty? - Nokogiri::XML::NodeSet.new(matches.document, remaining) - end + next if regex_matching ? (content =~ match_with) : (content == match_with) + content_mismatch ||= diff(match_with, content) + true + end - def extract_root(previous_selection, root_fallback) - possible_root = @values.first + @message ||= content_mismatch if remaining.empty? + Nokogiri::XML::NodeSet.new(matches.document, remaining) + end - if possible_root == nil - raise ArgumentError, 'First argument is either selector or element ' \ - 'to select, but nil found. Perhaps you called assert_dom with ' \ - 'an element that does not exist?' - elsif possible_root.respond_to?(:css) - @values.shift # remove the root, so selector is the first argument - possible_root - elsif previous_selection - previous_selection - else - root_fallback.call - end - end + def extract_root(previous_selection, root_fallback) + possible_root = @values.first - def extract_selectors - selector = @values.shift + if possible_root == nil + raise ArgumentError, "First argument is either selector or element " \ + "to select, but nil found. Perhaps you called assert_dom with " \ + "an element that does not exist?" + elsif possible_root.respond_to?(:css) + @values.shift # remove the root, so selector is the first argument + possible_root + elsif previous_selection + previous_selection + else + root_fallback.call + end + end - unless selector.is_a? String - raise ArgumentError, "Expecting a selector as the first argument" - end + def extract_selectors + selector = @values.shift - @css_selector = context.substitute!(selector, @values.dup, true) - @selector = context.substitute!(selector, @values) - end + unless selector.is_a? String + raise ArgumentError, "Expecting a selector as the first argument" + end - def extract_equality_tests - comparisons = {} - case comparator = @values.shift - when Hash - comparisons = comparator - when String, Regexp - comparisons[:text] = comparator - when Integer - comparisons[:count] = comparator - when Range - comparisons[:minimum] = comparator.begin - comparisons[:maximum] = comparator.end - when FalseClass - comparisons[:count] = 0 - when NilClass, TrueClass - comparisons[:minimum] = 1 - else raise ArgumentError, "I don't understand what you're trying to match" - end + @css_selector = context.substitute!(selector, @values.dup, true) + @selector = context.substitute!(selector, @values) + end - # By default we're looking for at least one match. - if comparisons[:count] - comparisons[:minimum] = comparisons[:maximum] = comparisons[:count] - else - comparisons[:minimum] ||= 1 + def extract_equality_tests + comparisons = {} + case comparator = @values.shift + when Hash + comparisons = comparator + when String, Regexp + comparisons[:text] = comparator + when Integer + comparisons[:count] = comparator + when Range + comparisons[:minimum] = comparator.begin + comparisons[:maximum] = comparator.end + when FalseClass + comparisons[:count] = 0 + when NilClass, TrueClass + comparisons[:minimum] = 1 + else raise ArgumentError, "I don't understand what you're trying to match" + end + + # By default we're looking for at least one match. + if comparisons[:count] + comparisons[:minimum] = comparisons[:maximum] = comparisons[:count] + else + comparisons[:minimum] ||= 1 + end + comparisons + end + end + end + end end - comparisons end end