Created
October 21, 2010 03:37
-
-
Save cjheath/637887 to your computer and use it in GitHub Desktop.
RSpec differ_from matcher (calls other matchers)
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
module RSpec | |
module Matchers | |
class ArrayMatcher < Matcher | |
def initialize expected | |
super(:be_different_array_from, expected) do |*_expected| | |
match_for_should do |actual| | |
perform_match(actual, _expected[0]) | |
@extra + @missing != [] | |
end | |
match_for_should_not do |actual| | |
perform_match(actual, _expected[0]) | |
@extra + @missing == [] | |
end | |
def perform_match(actual, expected) | |
@extra = actual - expected | |
@missing = expected - actual | |
end | |
def failure_message_for_should | |
"expected a difference in the two lists, but got none" | |
end | |
failure_message_for_should_not do |actual| | |
"expected no difference, but result #{ | |
[ (@missing.empty? ? nil : 'lacks '+@missing.sort.inspect), | |
(@extra.empty? ? nil : 'has extra '+@extra.sort.inspect) | |
].compact * ' and ' | |
}" | |
end | |
end | |
end | |
end | |
def be_different_array_from(expected) | |
ArrayMatcher.new(expected) | |
end | |
end | |
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
require 'pathname' | |
module RSpec | |
module Matchers | |
def differ_from(expected) | |
case expected | |
when Pathname | |
FileMatcher.new(expected) | |
when Array | |
ArrayMatcher.new(expected) | |
when String | |
FileMatcher.new(expected) | |
else | |
raise "DiffMatcher doesn't know how to match a #{expected.class}" | |
end | |
end | |
end | |
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
require 'diff/lcs' | |
module RSpec | |
module Matchers | |
class FileMatcher < Matcher | |
def initialize expected | |
super(:have_different_contents, expected) do |*_expected| | |
match_for_should do |actual| | |
perform_match(actual, _expected[0]) | |
end | |
match_for_should_not do |actual| | |
!perform_match(actual, _expected[0]) | |
end | |
def perform_match(actual, expected) | |
expected = File.open(expected).read if expected.is_a?(Pathname) | |
expected = expected.scan(/[^\n]+/) unless expected.is_a?(Array) | |
actual = File.open(actual).read if actual.is_a?(Pathname) | |
actual = actual.scan(/[^\n]+/) unless actual.is_a?(Array) | |
differences = Diff::LCS::diff(expected, actual) | |
@diff = differences.map do |chunk| | |
added_at = (add = chunk.detect{|d| d.action == '+'}) && add.position+1 | |
removed_at = (remove = chunk.detect{|d| d.action == '-'}) && remove.position+1 | |
"Line #{added_at}/#{removed_at}:\n"+ | |
chunk.map do |change| | |
"#{change.action} #{change.element}" | |
end*"\n" | |
end*"\n" | |
@diff != '' | |
end | |
def failure_message_for_should | |
"expected a difference, but got none" | |
end | |
failure_message_for_should_not do |actual| | |
"expected no difference, but got:\n#{@diff}" | |
end | |
end | |
end | |
end | |
def have_different_contents(expected) | |
FileMatcher.new(expected) | |
end | |
end | |
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
require 'diff/lcs' | |
module RSpec | |
module Matchers | |
def have_different_contents(expected) | |
Matcher.new :have_different_contents, expected do |*_expected| | |
match_for_should do |actual| | |
perform_match(actual, _expected) | |
end | |
match_for_should_not do |actual| | |
!perform_match(actual, _expected) | |
end | |
def perform_match(actual, expected) | |
expected_lines = expected.scan(/[^\n]+/) | |
actual_lines = actual.scan(/[^\n]+/) | |
differences = Diff::LCS::diff(expected_lines, actual_lines) | |
@diff = differences.map do |chunk| | |
added_at = (add = chunk.detect{|d| d.action == '+'}) && add.position+1 | |
removed_at = (remove = chunk.detect{|d| d.action == '-'}) && remove.position+1 | |
"Line #{added_at}/#{removed_at}:\n"+ | |
chunk.map do |change| | |
"#{change.action} #{change.element}" | |
end*"\n" | |
end*"\n" | |
@diff != '' | |
end | |
def failure_message_for_should | |
"expected a difference, but got none" | |
end | |
failure_message_for_should_not do |actual| | |
"expected no difference, but got:\n#{@diff}" | |
end | |
end | |
end | |
end | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment