aboutsummaryrefslogtreecommitdiffstats
path: root/spec/mspec/lib/mspec/matchers/equal_element.rb
blob: 8da2567fcf83d6561ef13debf3d28517cd7212b2 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
class EqualElementMatcher
  def initialize(element, attributes = nil, content = nil, options = {})
    @element = element
    @attributes = attributes
    @content = content
    @options = options
  end

  def matches?(actual)
    @actual = actual

    matched = true

    if @options[:not_closed]
      matched &&= actual =~ /^#{Regexp.quote("<" + @element)}.*#{Regexp.quote(">" + (@content || ''))}$/
    else
      matched &&= actual =~ /^#{Regexp.quote("<" + @element)}/
      matched &&= actual =~ /#{Regexp.quote("</" + @element + ">")}$/
      matched &&= actual =~ /#{Regexp.quote(">" + @content + "</")}/ if @content
    end

    if @attributes
      if @attributes.empty?
        matched &&= actual.scan(/\w+\=\"(.*)\"/).size == 0
      else
        @attributes.each do |key, value|
          if value == true
            matched &&= (actual.scan(/#{Regexp.quote(key)}(\s|>)/).size == 1)
          else
            matched &&= (actual.scan(%Q{ #{key}="#{value}"}).size == 1)
          end
        end
      end
    end

    !!matched
  end

  def failure_message
    ["Expected #{MSpec.format(@actual)}",
     "to be a '#{@element}' element with #{attributes_for_failure_message} and #{content_for_failure_message}"]
  end

  def negative_failure_message
    ["Expected #{MSpec.format(@actual)}",
      "not to be a '#{@element}' element with #{attributes_for_failure_message} and #{content_for_failure_message}"]
  end

  def attributes_for_failure_message
    if @attributes
      if @attributes.empty?
        "no attributes"
      else
        @attributes.inject([]) { |memo, n| memo << %Q{#{n[0]}="#{n[1]}"} }.join(" ")
      end
    else
      "any attributes"
    end
  end

  def content_for_failure_message
    if @content
      if @content.empty?
        "no content"
      else
        "#{@content.inspect} as content"
      end
    else
      "any content"
    end
  end
end

module MSpecMatchers
  private def equal_element(*args)
    EqualElementMatcher.new(*args)
  end
end