jasonkarns
7/29/2015 - 3:26 PM

Custom Matcher that extends RSpec::Matchers::BuiltIn::Match to also enable specifying capture groups.

Custom Matcher that extends RSpec::Matchers::BuiltIn::Match to also enable specifying capture groups.

module CustomMatchers
  class Match < RSpec::Matchers::BuiltIn::Match
    def matches?(actual)
      # first ensure the regex matched
      return false unless result = super
      # only continue if specifying captures
      return result unless expected_captures = @captures

      actual_captures = to_hash result

      RSpec::Matchers::BuiltIn::Include.new(expected_captures).matches?(actual_captures).tap do |captures_matched|
        # replace expected/actual regex with the matchdata
        # if the matchdata didn't match. this way we get a diff of the matchdata hashes
        # otherwise, leave untouched so the description is per normal
        unless captures_matched
          @expected = expected_captures
          @actual = actual_captures
        end
      end
    end

    def capturing(captures)
      @captures = captures
      self
    end

    private

    def to_hash(matchdata)
      Hash[matchdata.names.map(&:to_sym).zip matchdata.captures]
    end
  end

  def matchy(expected)
    Match.new expected
  end
end