class RSpecHtmlMatchers::HaveTag
@private
@api
def classes_to_selector(classes)
def classes_to_selector(classes) case classes when Array classes.join('.') when String classes.gsub(/\s+/, '.') end end
def count_right?
def count_right? case @options[:count] when Integer ((@failure_message_when_negated=MESSAGES[:unexpected_count] % [@document,@count,@tag]) && @count == @options[:count]) || (@failure_message=MESSAGES[:expected_count] % [@document,@options[:count],@tag,@count]; false) when Range ((@failure_message_when_negated=MESSAGES[:unexpected_btw_count] % [@document,@options[:count].min,@options[:count].max,@tag,@count]) && @options[:count].member?(@count)) || (@failure_message=MESSAGES[:expected_btw_count] % [@document,@options[:count].min,@options[:count].max,@tag,@count]; false) when nil if @options[:maximum] ((@failure_message_when_negated=MESSAGES[:unexpected_at_most] % [@document,@options[:maximum],@tag,@count]) && @count <= @options[:maximum]) || (@failure_message=MESSAGES[:expected_at_most] % [@document,@options[:maximum],@tag,@count]; false) elsif @options[:minimum] ((@failure_message_when_negated=MESSAGES[:unexpected_at_least] % [@document,@options[:minimum],@tag,@count]) && @count >= @options[:minimum]) || (@failure_message=MESSAGES[:expected_at_least] % [@document,@options[:minimum],@tag,@count]; false) else true end end end
def description
def description # TODO should it be more complicated? if @options.has_key?(:count) DESCRIPTIONS[:have_n] % [@options[:count],@tag] else DESCRIPTIONS[:have_at_least_1] % @tag end end
def initialize tag, options={}, &block
def initialize tag, options={}, &block @tag, @options, @block = tag.to_s, options, block if with_attrs = @options.delete(:with) if classes = with_attrs.delete(:class) @tag << '.' + classes_to_selector(classes) end selector = with_attrs.inject('') do |html_attrs_string, (k, v)| html_attrs_string << "[#{k}='#{v}']" html_attrs_string end @tag << selector end if without_attrs = @options.delete(:without) if classes = without_attrs.delete(:class) @tag << ":not(.#{classes_to_selector(classes)})" end end validate_options! end
def matches? document, &block
def matches? document, &block @block = block if block document = document.html if defined?(Capybara::Session) && document.is_a?(Capybara::Session) case document when String @parent_scope = @current_scope = Nokogiri::HTML(document).css(@tag) @document = document else @parent_scope = document.current_scope @current_scope = begin document.parent_scope.css(@tag) # on jruby this produce exception if css was not found: # undefined method `decorate' for nil:NilClass rescue NoMethodError Nokogiri::XML::NodeSet.new(Nokogiri::XML::Document.new) end @document = @parent_scope.to_html end if tag_presents? and text_right? and count_right? @current_scope = @parent_scope @block.call if @block true else false end end
def tag_presents?
def tag_presents? if @current_scope.first @count = @current_scope.count @failure_message_when_negated = MESSAGES[:unexpected_tag] % [@document, @tag, @count] true else @failure_message = MESSAGES[:expected_tag] % [@document, @tag] false end end
def text_right?
def text_right? return true unless @options[:text] case text=@options[:text] when Regexp new_scope = @current_scope.css(':regexp()',NokogiriRegexpHelper.new(text)) unless new_scope.empty? @count = new_scope.count @failure_message_when_negated = MESSAGES[:unexpected_regexp] % [text.inspect,@tag,@document] true else @failure_message = MESSAGES[:expected_regexp] % [text.inspect,@tag,@document] false end else new_scope = @current_scope.css(':content()',NokogiriTextHelper.new(text)) unless new_scope.empty? @count = new_scope.count @failure_message_when_negated = MESSAGES[:unexpected_text] % [text,@tag,@document] true else @failure_message = MESSAGES[:expected_text] % [text,@tag,@document] false end end end
def validate_options!
def validate_options! raise 'wrong :count specified' unless [Range, NilClass].include?(@options[:count].class) or @options[:count].is_a?(Integer) [:min, :minimum, :max, :maximum].each do |key| raise MESSAGES[:wrong_count_error] if @options.has_key?(key) and @options.has_key?(:count) end begin raise MESSAGES[:min_max_error] if @options[:minimum] > @options[:maximum] rescue NoMethodError # nil > 4 rescue ArgumentError # 2 < nil end begin begin raise MESSAGES[:bad_range_error] % [@options[:count].to_s] if @options[:count] && @options[:count].is_a?(Range) && (@options[:count].min.nil? or @options[:count].min < 0) rescue ArgumentError, "comparison of String with" # if @options[:count] == 'a'..'z' raise MESSAGES[:bad_range_error] % [@options[:count].to_s] end rescue TypeError # fix for 1.8.7 for 'rescue ArgumentError, "comparison of String with"' stroke raise MESSAGES[:bad_range_error] % [@options[:count].to_s] end @options[:minimum] ||= @options.delete(:min) @options[:maximum] ||= @options.delete(:max) @options[:text] = @options[:text].to_s if @options.has_key?(:text) && !@options[:text].is_a?(Regexp) end