diff options
Diffstat (limited to 'vendor/plugins/rspec/lib/spec/matchers')
16 files changed, 592 insertions, 473 deletions
diff --git a/vendor/plugins/rspec/lib/spec/matchers/be.rb b/vendor/plugins/rspec/lib/spec/matchers/be.rb index 2b25b11f4..242f7c5c9 100644 --- a/vendor/plugins/rspec/lib/spec/matchers/be.rb +++ b/vendor/plugins/rspec/lib/spec/matchers/be.rb @@ -2,142 +2,130 @@ module Spec module Matchers class Be #:nodoc: + include Spec::Matchers::Pretty + def initialize(*args) - if args.empty? - @expected = :satisfy_if - else - @expected = parse_expected(args.shift) - end + @expected = args.empty? ? true : set_expected(args.shift) @args = args - @comparison = "" + @comparison_method = nil end def matches?(actual) @actual = actual - if handling_predicate? - begin - return @result = actual.__send__(predicate, *@args) - rescue => predicate_error - # This clause should be empty, but rcov will not report it as covered - # unless something (anything) is executed within the clause - rcov_error_report = "http://eigenclass.org/hiki.rb?rcov-0.8.0" - end - - # This supports should_exist > target.exists? in the old world. - # We should consider deprecating that ability as in the new world - # you can't write "should exist" unless you have your own custom matcher. - begin - return @result = actual.__send__(present_tense_predicate, *@args) - rescue - raise predicate_error - end - else - return match_or_compare - end - end - - def failure_message - return "expected #{@comparison}#{expected}, got #{@actual.inspect}" unless handling_predicate? - return "expected #{predicate}#{args_to_s} to return true, got #{@result.inspect}" + handling_predicate? ? run_predicate_on(actual) : match_or_compare(actual) end - def negative_failure_message - return "expected not #{expected}, got #{@actual.inspect}" unless handling_predicate? - return "expected #{predicate}#{args_to_s} to return false, got #{@result.inspect}" + def run_predicate_on(actual) + begin + return @result = actual.__send__(predicate, *@args) + rescue NameError => predicate_missing_error + "this needs to be here or rcov will not count this branch even though it's executed in a code example" + end + + begin + return @result = actual.__send__(present_tense_predicate, *@args) + rescue NameError + raise predicate_missing_error + end end - def expected - return "if to be satisfied" if @expected == :satisfy_if - return true if @expected == :true - return false if @expected == :false - return "nil" if @expected == :nil - return @expected.inspect + def failure_message_for_should + if handling_predicate? + if predicate == :nil? + "expected nil, got #{@actual.inspect}" + else + "expected #{predicate}#{args_to_s} to return true, got #{@result.inspect}" + end + else + "expected #{@comparison_method} #{expected}, got #{@actual.inspect}".gsub(' ',' ') + end end - def match_or_compare - return @actual ? true : false if @expected == :satisfy_if - return @actual == true if @expected == :true - return @actual == false if @expected == :false - return @actual.nil? if @expected == :nil - return @actual < @expected if @less_than - return @actual <= @expected if @less_than_or_equal - return @actual >= @expected if @greater_than_or_equal - return @actual > @expected if @greater_than - return @actual == @expected if @double_equal - return @actual === @expected if @triple_equal - return @actual.equal?(@expected) + def failure_message_for_should_not + if handling_predicate? + if predicate == :nil? + "expected not nil, got nil" + else + "expected #{predicate}#{args_to_s} to return false, got #{@result.inspect}" + end + else + message = <<-MESSAGE +'should_not be #{@comparison_method} #{expected}' not only FAILED, +it is a bit confusing. + MESSAGE + + raise message << ([:===,:==].include?(@comparison_method) ? + "It might be more clearly expressed without the \"be\"?" : + "It might be more clearly expressed in the positive?") + end end - def ==(expected) - @prefix = "be " - @double_equal = true - @comparison = "== " - @expected = expected - self - end - - def ===(expected) - @prefix = "be " - @triple_equal = true - @comparison = "=== " - @expected = expected - self - end - - def <(expected) - @prefix = "be " - @less_than = true - @comparison = "< " - @expected = expected - self - end - - def <=(expected) - @prefix = "be " - @less_than_or_equal = true - @comparison = "<= " - @expected = expected - self + def description + "#{prefix_to_sentence}#{comparison} #{expected_to_sentence}#{args_to_sentence}".gsub(/\s+/,' ') end - def >=(expected) - @prefix = "be " - @greater_than_or_equal = true - @comparison = ">= " - @expected = expected - self + [:==, :<, :<=, :>=, :>, :===].each do |method| + define_method method do |expected| + compare_to(expected, :using => method) + self + end end - def >(expected) - @prefix = "be " - @greater_than = true - @comparison = "> " - @expected = expected - self - end + private + def match_or_compare(actual) + TrueClass === @expected ? @actual : @actual.__send__(comparison_method, @expected) + end - def description - "#{prefix_to_sentence}#{comparison}#{expected_to_sentence}#{args_to_sentence}" - end + def comparison_method + @comparison_method || :equal? + end + + def expected + @expected + end - private + def compare_to(expected, opts) + @expected, @comparison_method = expected, opts[:using] + end + + def set_expected(expected) + Symbol === expected ? parse_expected(expected) : expected + end + def parse_expected(expected) - if Symbol === expected - @handling_predicate = true - ["be_an_","be_a_","be_"].each do |prefix| - if expected.starts_with?(prefix) - @prefix = prefix - return "#{expected.to_s.sub(@prefix,"")}".to_sym + ["be_an_","be_a_","be_"].each do |prefix| + handling_predicate! + if expected.to_s =~ /^#{prefix}/ + set_prefix(prefix) + expected = expected.to_s.sub(prefix,"") + [true, false, nil].each do |val| + return val if val.to_s == expected end + return expected.to_sym end end - @prefix = "" - return expected + end + + def set_prefix(prefix) + @prefix = prefix + end + + def prefix + # FIXME - this is a bit goofy - but we get failures + # if just defining @prefix = nil in initialize + @prefix = nil unless defined?(@prefix) + @prefix + end + + def handling_predicate! + @handling_predicate = true end def handling_predicate? - return false if [:true, :false, :nil].include?(@expected) - return @handling_predicate + return false if [true, false, nil].include?(expected) + # FIXME - this is a bit goofy - but we get failures + # if just defining @handling_predicate = nil or false in initialize + return defined?(@handling_predicate) ? @handling_predicate : nil end def predicate @@ -149,50 +137,44 @@ module Spec end def args_to_s - return "" if @args.empty? - inspected_args = @args.collect{|a| a.inspect} - return "(#{inspected_args.join(', ')})" + @args.empty? ? "" : parenthesize(inspected_args.join(', ')) + end + + def parenthesize(string) + return "(#{string})" + end + + def inspected_args + @args.collect{|a| a.inspect} end def comparison - @comparison + @comparison_method.nil? ? " " : "be #{@comparison_method.to_s} " end def expected_to_sentence - split_words(@expected) + split_words(expected) end def prefix_to_sentence - split_words(@prefix) - end - - def split_words(sym) - sym.to_s.gsub(/_/,' ') + split_words(prefix) end def args_to_sentence - case @args.length - when 0 - "" - when 1 - " #{@args[0]}" - else - " #{@args[0...-1].join(', ')} and #{@args[-1]}" - end + to_sentence(@args) end end # :call-seq: - # should be # should be_true # should be_false # should be_nil - # should be_arbitrary_predicate(*args) + # should be_[arbitrary_predicate](*args) # should_not be_nil - # should_not be_arbitrary_predicate(*args) + # should_not be_[arbitrary_predicate](*args) # - # Given true, false, or nil, will pass if actual is + # Given true, false, or nil, will pass if actual value is # true, false or nil (respectively). Given no args means # the caller should satisfy an if condition (to be or not to be). # @@ -206,19 +188,23 @@ module Spec # # == Examples # - # target.should be # target.should be_true # target.should be_false # target.should be_nil # target.should_not be_nil # # collection.should be_empty #passes if target.empty? - # "this string".should be_an_intance_of(String) - # # target.should_not be_empty #passes unless target.empty? # target.should_not be_old_enough(16) #passes unless target.old_enough?(16) def be(*args) Matchers::Be.new(*args) end + + # passes if target.kind_of?(klass) + def be_a(klass) + be_a_kind_of(klass) + end + + alias_method :be_an, :be_a end end diff --git a/vendor/plugins/rspec/lib/spec/matchers/be_close.rb b/vendor/plugins/rspec/lib/spec/matchers/be_close.rb index 7763eb97e..28015f5fb 100644 --- a/vendor/plugins/rspec/lib/spec/matchers/be_close.rb +++ b/vendor/plugins/rspec/lib/spec/matchers/be_close.rb @@ -1,26 +1,5 @@ module Spec module Matchers - - class BeClose #:nodoc: - def initialize(expected, delta) - @expected = expected - @delta = delta - end - - def matches?(actual) - @actual = actual - (@actual - @expected).abs < @delta - end - - def failure_message - "expected #{@expected} +/- (< #{@delta}), got #{@actual}" - end - - def description - "be close to #{@expected} (within +- #{@delta})" - end - end - # :call-seq: # should be_close(expected, delta) # should_not be_close(expected, delta) @@ -31,7 +10,23 @@ module Spec # # result.should be_close(3.0, 0.5) def be_close(expected, delta) - Matchers::BeClose.new(expected, delta) + Matcher.new :be_close, expected, delta do |_expected_, _delta_| + match do |actual| + (actual - _expected_).abs < _delta_ + end + + failure_message_for_should do |actual| + "expected #{_expected_} +/- (< #{_delta_}), got #{actual}" + end + + failure_message_for_should_not do |actual| + "expected #{_expected_} +/- (< #{_delta_}), got #{actual}" + end + + description do + "be close to #{_expected_} (within +- #{_delta_})" + end + end end end end diff --git a/vendor/plugins/rspec/lib/spec/matchers/change.rb b/vendor/plugins/rspec/lib/spec/matchers/change.rb index 8f4ecc187..c8ab9e5cf 100644 --- a/vendor/plugins/rspec/lib/spec/matchers/change.rb +++ b/vendor/plugins/rspec/lib/spec/matchers/change.rb @@ -4,60 +4,59 @@ module Spec #Based on patch from Wilson Bilkovich class Change #:nodoc: def initialize(receiver=nil, message=nil, &block) - @receiver = receiver - @message = message - @block = block + @message = message || "result" + @value_proc = block || lambda {receiver.__send__(message)} + @to = @from = @minimum = @maximum = @amount = nil end - def matches?(target, &block) - if block - raise MatcherError.new(<<-EOF -block passed to should or should_not change must use {} instead of do/end -EOF -) - end - @target = target - execute_change - return false if @from && (@from != @before) - return false if @to && (@to != @after) + def matches?(event_proc) + raise_block_syntax_error if block_given? + + @before = evaluate_value_proc + event_proc.call + @after = evaluate_value_proc + + return (@to = false) if @from unless @from == @before + return false if @to unless @to == @after return (@before + @amount == @after) if @amount return ((@after - @before) >= @minimum) if @minimum return ((@after - @before) <= @maximum) if @maximum return @before != @after end - def execute_change - @before = @block.nil? ? @receiver.send(@message) : @block.call - @target.call - @after = @block.nil? ? @receiver.send(@message) : @block.call + def raise_block_syntax_error + raise MatcherError.new(<<-MESSAGE +block passed to should or should_not change must use {} instead of do/end +MESSAGE + ) + end + + def evaluate_value_proc + @value_proc.call end - def failure_message + def failure_message_for_should if @to - "#{result} should have been changed to #{@to.inspect}, but is now #{@after.inspect}" + "#{@message} should have been changed to #{@to.inspect}, but is now #{@after.inspect}" elsif @from - "#{result} should have initially been #{@from.inspect}, but was #{@before.inspect}" + "#{@message} should have initially been #{@from.inspect}, but was #{@before.inspect}" elsif @amount - "#{result} should have been changed by #{@amount.inspect}, but was changed by #{actual_delta.inspect}" + "#{@message} should have been changed by #{@amount.inspect}, but was changed by #{actual_delta.inspect}" elsif @minimum - "#{result} should have been changed by at least #{@minimum.inspect}, but was changed by #{actual_delta.inspect}" + "#{@message} should have been changed by at least #{@minimum.inspect}, but was changed by #{actual_delta.inspect}" elsif @maximum - "#{result} should have been changed by at most #{@maximum.inspect}, but was changed by #{actual_delta.inspect}" + "#{@message} should have been changed by at most #{@maximum.inspect}, but was changed by #{actual_delta.inspect}" else - "#{result} should have changed, but is still #{@before.inspect}" + "#{@message} should have changed, but is still #{@before.inspect}" end end - def result - @message || "result" - end - def actual_delta @after - @before end - def negative_failure_message - "#{result} should not have changed, but did change from #{@before.inspect} to #{@after.inspect}" + def failure_message_for_should_not + "#{@message} should not have changed, but did change from #{@before.inspect} to #{@after.inspect}" end def by(amount) @@ -84,6 +83,10 @@ EOF @from = from self end + + def description + "change ##{@message}" + end end # :call-seq: @@ -125,20 +128,24 @@ EOF # employee.develop_great_new_social_networking_app # }.should change(employee, :title).from("Mail Clerk").to("CEO") # - # Evaluates +receiver.message+ or +block+ before and - # after it evaluates the c object (generated by the lambdas in the examples above). + # Evaluates <tt>receiver.message</tt> or <tt>block</tt> before and after + # it evaluates the c object (generated by the lambdas in the examples + # above). + # + # Then compares the values before and after the <tt>receiver.message</tt> + # and evaluates the difference compared to the expected difference. # - # Then compares the values before and after the +receiver.message+ and - # evaluates the difference compared to the expected difference. + # == WARNING + # <tt>should_not change</tt> only supports the form with no + # subsequent calls to <tt>by</tt>, <tt>by_at_least</tt>, + # <tt>by_at_most</tt>, <tt>to</tt> or <tt>from</tt>. # - # == Warning - # +should_not+ +change+ only supports the form with no subsequent calls to - # +by+, +by_at_least+, +by_at_most+, +to+ or +from+. + # blocks passed to <tt>should</tt> <tt>change</tt> and <tt>should_not</tt> + # <tt>change</tt> must use the <tt>{}</tt> form (<tt>do/end</tt> is not + # supported). # - # blocks passed to +should+ +change+ and +should_not+ +change+ - # must use the <tt>{}</tt> form (<tt>do/end</tt> is not supported) - def change(target=nil, message=nil, &block) - Matchers::Change.new(target, message, &block) + def change(receiver=nil, message=nil, &block) + Matchers::Change.new(receiver, message, &block) end end end diff --git a/vendor/plugins/rspec/lib/spec/matchers/eql.rb b/vendor/plugins/rspec/lib/spec/matchers/eql.rb index 280ca5454..98ab198d9 100644 --- a/vendor/plugins/rspec/lib/spec/matchers/eql.rb +++ b/vendor/plugins/rspec/lib/spec/matchers/eql.rb @@ -1,29 +1,5 @@ module Spec module Matchers - - class Eql #:nodoc: - def initialize(expected) - @expected = expected - end - - def matches?(actual) - @actual = actual - @actual.eql?(@expected) - end - - def failure_message - return "expected #{@expected.inspect}, got #{@actual.inspect} (using .eql?)", @expected, @actual - end - - def negative_failure_message - return "expected #{@actual.inspect} not to equal #{@expected.inspect} (using .eql?)", @expected, @actual - end - - def description - "eql #{@expected.inspect}" - end - end - # :call-seq: # should eql(expected) # should_not eql(expected) @@ -37,7 +13,30 @@ module Spec # 5.should eql(5) # 5.should_not eql(3) def eql(expected) - Matchers::Eql.new(expected) + Matcher.new :eql, expected do |_expected_| + match do |actual| + actual.eql?(_expected_) + end + + failure_message_for_should do |actual| + <<-MESSAGE + +expected #{_expected_.inspect} + got #{actual.inspect} + +(compared using eql?) +MESSAGE + end + + failure_message_for_should_not do |actual| + <<-MESSAGE + +expected #{actual.inspect} not to equal #{_expected_.inspect} + +(compared using eql?) +MESSAGE + end + end end end end diff --git a/vendor/plugins/rspec/lib/spec/matchers/equal.rb b/vendor/plugins/rspec/lib/spec/matchers/equal.rb index 4bfc74951..3580a95af 100644 --- a/vendor/plugins/rspec/lib/spec/matchers/equal.rb +++ b/vendor/plugins/rspec/lib/spec/matchers/equal.rb @@ -1,29 +1,6 @@ module Spec module Matchers - - class Equal #:nodoc: - def initialize(expected) - @expected = expected - end - - def matches?(actual) - @actual = actual - @actual.equal?(@expected) - end - - def failure_message - return "expected #{@expected.inspect}, got #{@actual.inspect} (using .equal?)", @expected, @actual - end - def negative_failure_message - return "expected #{@actual.inspect} not to equal #{@expected.inspect} (using .equal?)", @expected, @actual - end - - def description - "equal #{@expected.inspect}" - end - end - # :call-seq: # should equal(expected) # should_not equal(expected) @@ -37,7 +14,40 @@ module Spec # 5.should equal(5) #Fixnums are equal # "5".should_not equal("5") #Strings that look the same are not the same object def equal(expected) - Matchers::Equal.new(expected) + Matcher.new :equal, expected do |_expected_| + match do |actual| + actual.equal?(_expected_) + end + + def inspect_object(o) + "#<#{o.class}:#{o.object_id}> => #{o.inspect}" + end + + failure_message_for_should do |actual| + <<-MESSAGE + +expected #{inspect_object(_expected_)} + got #{inspect_object(actual)} + +Compared using equal?, which compares object identity, +but expected and actual are not the same object. Use +'actual.should == expected' if you don't care about +object identity in this example. + +MESSAGE + end + + failure_message_for_should_not do |actual| + <<-MESSAGE + +expected not #{inspect_object(actual)} + got #{inspect_object(_expected_)} + +Compared using equal?, which compares object identity. + +MESSAGE + end + end end end end diff --git a/vendor/plugins/rspec/lib/spec/matchers/exist.rb b/vendor/plugins/rspec/lib/spec/matchers/exist.rb index a5a911132..dc69c683d 100644 --- a/vendor/plugins/rspec/lib/spec/matchers/exist.rb +++ b/vendor/plugins/rspec/lib/spec/matchers/exist.rb @@ -1,17 +1,16 @@ module Spec module Matchers - class Exist - def matches? actual - @actual = actual - @actual.exist? - end - def failure_message - "expected #{@actual.inspect} to exist, but it doesn't." - end - def negative_failure_message - "expected #{@actual.inspect} to not exist, but it does." + # :call-seq: + # should exist + # should_not exist + # + # Passes if actual.exist? + def exist(arg=nil) + Matcher.new :exist do + match do |actual| + arg ? actual.exist?(arg) : actual.exist? + end end end - def exist; Exist.new; end end end diff --git a/vendor/plugins/rspec/lib/spec/matchers/has.rb b/vendor/plugins/rspec/lib/spec/matchers/has.rb index 60199f54d..7073e0a86 100644 --- a/vendor/plugins/rspec/lib/spec/matchers/has.rb +++ b/vendor/plugins/rspec/lib/spec/matchers/has.rb @@ -1,34 +1,35 @@ module Spec module Matchers - class Has #:nodoc: - def initialize(sym, *args) - @sym = sym - @args = args + class Has + + def initialize(expected, *args) + @expected, @args = expected, args end - def matches?(target) - target.send(predicate, *@args) + def matches?(actual) + actual.__send__(predicate(@expected), *@args) end - def failure_message - "expected ##{predicate}(#{@args[0].inspect}) to return true, got false" + def failure_message_for_should + "expected ##{predicate(@expected)}(#{@args[0].inspect}) to return true, got false" end - def negative_failure_message - "expected ##{predicate}(#{@args[0].inspect}) to return false, got true" + def failure_message_for_should_not + "expected ##{predicate(@expected)}(#{@args[0].inspect}) to return false, got true" end def description "have key #{@args[0].inspect}" end + + private + + def predicate(sym) + "#{sym.to_s.sub("have_","has_")}?".to_sym + end - private - def predicate - "#{@sym.to_s.sub("have_","has_")}?".to_sym - end - end - + end end diff --git a/vendor/plugins/rspec/lib/spec/matchers/have.rb b/vendor/plugins/rspec/lib/spec/matchers/have.rb index 47454e3be..2975ee129 100644 --- a/vendor/plugins/rspec/lib/spec/matchers/have.rb +++ b/vendor/plugins/rspec/lib/spec/matchers/have.rb @@ -1,10 +1,10 @@ module Spec module Matchers - class Have #:nodoc: def initialize(expected, relativity=:exactly) @expected = (expected == :no ? 0 : expected) @relativity = relativity + @actual = nil end def relativities @@ -15,23 +15,15 @@ module Spec } end - def method_missing(sym, *args, &block) - @collection_name = sym - @plural_collection_name = Inflector.pluralize(sym.to_s) if Object.const_defined?(:Inflector) - @args = args - @block = block - self - end - def matches?(collection_owner) if collection_owner.respond_to?(@collection_name) - collection = collection_owner.send(@collection_name, *@args, &@block) + collection = collection_owner.__send__(@collection_name, *@args, &@block) elsif (@plural_collection_name && collection_owner.respond_to?(@plural_collection_name)) - collection = collection_owner.send(@plural_collection_name, *@args, &@block) + collection = collection_owner.__send__(@plural_collection_name, *@args, &@block) elsif (collection_owner.respond_to?(:length) || collection_owner.respond_to?(:size)) collection = collection_owner else - collection_owner.send(@collection_name, *@args, &@block) + collection_owner.__send__(@collection_name, *@args, &@block) end @actual = collection.size if collection.respond_to?(:size) @actual = collection.length if collection.respond_to?(:length) @@ -45,11 +37,11 @@ module Spec "expected #{@collection_name} to be a collection but it does not respond to #length or #size" end - def failure_message + def failure_message_for_should "expected #{relative_expectation} #{@collection_name}, got #{@actual}" end - def negative_failure_message + def failure_message_for_should_not if @relativity == :exactly return "expected target not to have #{@expected} #{@collection_name}, got #{@actual}" elsif @relativity == :at_most @@ -75,8 +67,22 @@ EOF "have #{relative_expectation} #{@collection_name}" end + def respond_to?(sym) + @expected.respond_to?(sym) || super + end + private + def method_missing(sym, *args, &block) + @collection_name = sym + if inflector = (defined?(ActiveSupport::Inflector) ? ActiveSupport::Inflector : (defined?(Inflector) ? Inflector : nil)) + @plural_collection_name = inflector.pluralize(sym.to_s) + end + @args = args + @block = block + self + end + def relative_expectation "#{relativities[@relativity]}#{@expected}" end diff --git a/vendor/plugins/rspec/lib/spec/matchers/include.rb b/vendor/plugins/rspec/lib/spec/matchers/include.rb index 5476f97d8..a2a7fe3db 100644 --- a/vendor/plugins/rspec/lib/spec/matchers/include.rb +++ b/vendor/plugins/rspec/lib/spec/matchers/include.rb @@ -1,52 +1,5 @@ module Spec module Matchers - - class Include #:nodoc: - - def initialize(*expecteds) - @expecteds = expecteds - end - - def matches?(actual) - @actual = actual - @expecteds.each do |expected| - return false unless actual.include?(expected) - end - true - end - - def failure_message - _message - end - - def negative_failure_message - _message("not ") - end - - def description - "include #{_pretty_print(@expecteds)}" - end - - private - def _message(maybe_not="") - "expected #{@actual.inspect} #{maybe_not}to include #{_pretty_print(@expecteds)}" - end - - def _pretty_print(array) - result = "" - array.each_with_index do |item, index| - if index < (array.length - 2) - result << "#{item.inspect}, " - elsif index < (array.length - 1) - result << "#{item.inspect} and " - else - result << "#{item.inspect}" - end - end - result - end - end - # :call-seq: # should include(expected) # should_not include(expected) @@ -64,7 +17,28 @@ module Spec # "spread".should include("read") # "spread".should_not include("red") def include(*expected) - Matchers::Include.new(*expected) + Matcher.new :include, *expected do |*_expected_| + match do |actual| + helper(actual, *_expected_) + end + + def helper(actual, *_expected_) + _expected_.each do |expected| + if actual.is_a?(Hash) + if expected.is_a?(Hash) + expected.each_pair do |k,v| + return false unless actual[k] == v + end + else + return false unless actual.has_key?(expected) + end + else + return false unless actual.include?(expected) + end + end + true + end + end end end end diff --git a/vendor/plugins/rspec/lib/spec/matchers/match.rb b/vendor/plugins/rspec/lib/spec/matchers/match.rb index 61ab52429..b4b9ea864 100644 --- a/vendor/plugins/rspec/lib/spec/matchers/match.rb +++ b/vendor/plugins/rspec/lib/spec/matchers/match.rb @@ -1,41 +1,21 @@ module Spec module Matchers - - class Match #:nodoc: - def initialize(expected) - @expected = expected - end - - def matches?(actual) - @actual = actual - return true if actual =~ @expected - return false - end - - def failure_message - return "expected #{@actual.inspect} to match #{@expected.inspect}", @expected, @actual - end - - def negative_failure_message - return "expected #{@actual.inspect} not to match #{@expected.inspect}", @expected, @actual - end - - def description - "match #{@expected.inspect}" - end - end - # :call-seq: - # should match(regexp) - # should_not match(regexp) + # should match(pattern) + # should_not match(pattern) # - # Given a Regexp, passes if actual =~ regexp + # Given a Regexp or String, passes if actual.match(pattern) # # == Examples # - # email.should match(/^([^@\s]+)@((?:[-a-z0-9]+\.)+[a-z]{2,})$/i) - def match(regexp) - Matchers::Match.new(regexp) + # email.should match(/^([^\s]+)((?:[-a-z0-9]+\.)+[a-z]{2,})$/i) + # email.should match("@example.com") + def match(expected) + Matcher.new :match, expected do |_expected_| + match do |actual| + actual.match(_expected_) + end + end end end end diff --git a/vendor/plugins/rspec/lib/spec/matchers/operator_matcher.rb b/vendor/plugins/rspec/lib/spec/matchers/operator_matcher.rb index dd23a0994..30295be01 100755..100644 --- a/vendor/plugins/rspec/lib/spec/matchers/operator_matcher.rb +++ b/vendor/plugins/rspec/lib/spec/matchers/operator_matcher.rb @@ -1,70 +1,75 @@ module Spec module Matchers - class BaseOperatorMatcher - attr_reader :generated_description - - def initialize(target) - @target = target - end - def ==(expected) - @expected = expected - __delegate_method_missing_to_target("==", expected) - end + class OperatorMatcher + class << self + def registry + @registry ||= {} + end - def ===(expected) - @expected = expected - __delegate_method_missing_to_target("===", expected) - end + def register(klass, operator, matcher) + registry[klass] ||= {} + registry[klass][operator] = matcher + end - def =~(expected) - @expected = expected - __delegate_method_missing_to_target("=~", expected) + def get(klass, operator) + registry[klass] && registry[klass][operator] + end end - def >(expected) - @expected = expected - __delegate_method_missing_to_target(">", expected) + def initialize(actual) + @actual = actual end - def >=(expected) - @expected = expected - __delegate_method_missing_to_target(">=", expected) + def self.use_custom_matcher_or_delegate(operator) + define_method(operator) do |expected| + if matcher = OperatorMatcher.get(@actual.class, operator) + @actual.send(::Spec::Matchers.last_should, matcher.new(expected)) + else + eval_match(@actual, operator, expected) + end + end end - def <(expected) - @expected = expected - __delegate_method_missing_to_target("<", expected) + ['==', '===', '=~', '>', '>=', '<', '<='].each do |operator| + use_custom_matcher_or_delegate operator end - def <=(expected) - @expected = expected - __delegate_method_missing_to_target("<=", expected) + def fail_with_message(message) + Spec::Expectations.fail_with(message, @expected, @actual) end - def fail_with_message(message) - Spec::Expectations.fail_with(message, @expected, @target) + def description + "#{@operator} #{@expected.inspect}" + end + + private + + def eval_match(actual, operator, expected) + ::Spec::Matchers.last_matcher = self + @operator, @expected = operator, expected + __delegate_operator(actual, operator, expected) end end - class PositiveOperatorMatcher < BaseOperatorMatcher #:nodoc: - - def __delegate_method_missing_to_target(operator, expected) - ::Spec::Matchers.generated_description = "should #{operator} #{expected.inspect}" - return if @target.send(operator, expected) - return fail_with_message("expected: #{expected.inspect},\n got: #{@target.inspect} (using #{operator})") if ['==','===', '=~'].include?(operator) - return fail_with_message("expected: #{operator} #{expected.inspect},\n got: #{operator.gsub(/./, ' ')} #{@target.inspect}") + class PositiveOperatorMatcher < OperatorMatcher #:nodoc: + def __delegate_operator(actual, operator, expected) + if actual.__send__(operator, expected) + true + elsif ['==','===', '=~'].include?(operator) + fail_with_message("expected: #{expected.inspect},\n got: #{actual.inspect} (using #{operator})") + else + fail_with_message("expected: #{operator} #{expected.inspect},\n got: #{operator.gsub(/./, ' ')} #{actual.inspect}") + end end end - class NegativeOperatorMatcher < BaseOperatorMatcher #:nodoc: - - def __delegate_method_missing_to_target(operator, expected) - ::Spec::Matchers.generated_description = "should not #{operator} #{expected.inspect}" - return unless @target.send(operator, expected) - return fail_with_message("expected not: #{operator} #{expected.inspect},\n got: #{operator.gsub(/./, ' ')} #{@target.inspect}") + class NegativeOperatorMatcher < OperatorMatcher #:nodoc: + def __delegate_operator(actual, operator, expected) + return false unless actual.__send__(operator, expected) + return fail_with_message("expected not: #{operator} #{expected.inspect},\n got: #{operator.gsub(/./, ' ')} #{actual.inspect}") end end diff --git a/vendor/plugins/rspec/lib/spec/matchers/raise_error.rb b/vendor/plugins/rspec/lib/spec/matchers/raise_error.rb index c003849b6..65bdf2370 100644 --- a/vendor/plugins/rspec/lib/spec/matchers/raise_error.rb +++ b/vendor/plugins/rspec/lib/spec/matchers/raise_error.rb @@ -1,23 +1,24 @@ module Spec module Matchers class RaiseError #:nodoc: - def initialize(error_or_message=Exception, message=nil, &block) + def initialize(expected_error_or_message=Exception, expected_message=nil, &block) @block = block - case error_or_message + @actual_error = nil + case expected_error_or_message when String, Regexp - @expected_error, @expected_message = Exception, error_or_message + @expected_error, @expected_message = Exception, expected_error_or_message else - @expected_error, @expected_message = error_or_message, message + @expected_error, @expected_message = expected_error_or_message, expected_message end end - def matches?(proc) + def matches?(given_proc) @raised_expected_error = false @with_expected_message = false @eval_block = false @eval_block_passed = false begin - proc.call + given_proc.call rescue @expected_error => @actual_error @raised_expected_error = true @with_expected_message = verify_message @@ -31,7 +32,7 @@ module Spec eval_block if @raised_expected_error && @with_expected_message && @block end ensure - return (@raised_expected_error && @with_expected_message) ? (@eval_block ? @eval_block_passed : true) : false + return (@raised_expected_error & @with_expected_message) ? (@eval_block ? @eval_block_passed : true) : false end def eval_block @@ -47,24 +48,20 @@ module Spec def verify_message case @expected_message when nil - return true + true when Regexp - return @expected_message =~ @actual_error.message + @expected_message =~ @actual_error.message else - return @expected_message == @actual_error.message + @expected_message == @actual_error.message end end - def failure_message - if @eval_block - return @actual_error.message - else - return "expected #{expected_error}#{actual_error}" - end + def failure_message_for_should + @eval_block ? @actual_error.message : "expected #{expected_error}#{given_error}" end - def negative_failure_message - "expected no #{expected_error}#{actual_error}" + def failure_message_for_should_not + "expected no #{expected_error}#{given_error}" end def description @@ -83,7 +80,7 @@ module Spec end end - def actual_error + def given_error @actual_error.nil? ? " but nothing was raised" : ", got #{@actual_error.inspect}" end diff --git a/vendor/plugins/rspec/lib/spec/matchers/respond_to.rb b/vendor/plugins/rspec/lib/spec/matchers/respond_to.rb index 3d23422aa..9161cb94e 100644 --- a/vendor/plugins/rspec/lib/spec/matchers/respond_to.rb +++ b/vendor/plugins/rspec/lib/spec/matchers/respond_to.rb @@ -4,28 +4,54 @@ module Spec class RespondTo #:nodoc: def initialize(*names) @names = names + @expected_arity = nil @names_not_responded_to = [] end - def matches?(target) + def matches?(actual) + @actual = actual @names.each do |name| - unless target.respond_to?(name) - @names_not_responded_to << name - end + @names_not_responded_to << name unless actual.respond_to?(name) && matches_arity?(actual, name) end return @names_not_responded_to.empty? end - def failure_message - "expected target to respond to #{@names_not_responded_to.collect {|name| name.inspect }.join(', ')}" + def failure_message_for_should + "expected #{@actual.inspect} to respond to #{@names_not_responded_to.collect {|name| name.inspect }.join(', ')}#{with_arity}" end - def negative_failure_message - "expected target not to respond to #{@names.collect {|name| name.inspect }.join(', ')}" + def failure_message_for_should_not + "expected #{@actual.inspect} not to respond to #{@names.collect {|name| name.inspect }.join(', ')}" end def description - "respond to ##{@names.to_s}" + "respond to #{pp_names}#{with_arity}" + end + + def with(n) + @expected_arity = n + self + end + + def argument + self + end + alias :arguments :argument + + private + + def matches_arity?(actual, name) + @expected_arity.nil?? true : @expected_arity == actual.method(name).arity + end + + def with_arity + @expected_arity.nil?? "" : + " with #{@expected_arity} argument#{@expected_arity == 1 ? '' : 's'}" + end + + def pp_names + # Ruby 1.9 returns the same thing for array.to_s as array.inspect, so just use array.inspect here + @names.length == 1 ? "##{@names.first}" : @names.inspect end end diff --git a/vendor/plugins/rspec/lib/spec/matchers/satisfy.rb b/vendor/plugins/rspec/lib/spec/matchers/satisfy.rb index 6c0ca95bc..58e3f56aa 100644 --- a/vendor/plugins/rspec/lib/spec/matchers/satisfy.rb +++ b/vendor/plugins/rspec/lib/spec/matchers/satisfy.rb @@ -12,11 +12,11 @@ module Spec @block.call(actual) end - def failure_message + def failure_message_for_should "expected #{@actual} to satisfy block" end - def negative_failure_message + def failure_message_for_should_not "expected #{@actual} not to satisfy block" end end diff --git a/vendor/plugins/rspec/lib/spec/matchers/simple_matcher.rb b/vendor/plugins/rspec/lib/spec/matchers/simple_matcher.rb index ac547d06a..5ab7f3068 100644 --- a/vendor/plugins/rspec/lib/spec/matchers/simple_matcher.rb +++ b/vendor/plugins/rspec/lib/spec/matchers/simple_matcher.rb @@ -1,29 +1,133 @@ module Spec module Matchers class SimpleMatcher - attr_reader :description + attr_writer :failure_message, :negative_failure_message, :description def initialize(description, &match_block) @description = description @match_block = match_block + @failure_message = @negative_failure_message = nil end - def matches?(actual) - @actual = actual - return @match_block.call(@actual) + def matches?(given) + @given = given + case @match_block.arity + when 2 + @match_block.call(@given, self) + else + @match_block.call(@given) + end + end + + def description + @description || explanation end - def failure_message() - return %[expected #{@description.inspect} but got #{@actual.inspect}] + def failure_message_for_should + @failure_message || (@description.nil? ? explanation : %[expected #{@description.inspect} but got #{@given.inspect}]) end - - def negative_failure_message() - return %[expected not to get #{@description.inspect}, but got #{@actual.inspect}] + + def failure_message_for_should_not + @negative_failure_message || (@description.nil? ? explanation : %[expected not to get #{@description.inspect}, but got #{@given.inspect}]) + end + + def explanation + "No description provided. See RDoc for simple_matcher()" end end - - def simple_matcher(message, &match_block) - SimpleMatcher.new(message, &match_block) + + # simple_matcher makes it easy for you to create your own custom matchers + # in just a few lines of code when you don't need all the power of a + # completely custom matcher object. + # + # The <tt>description</tt> argument will appear as part of any failure + # message, and is also the source for auto-generated descriptions. + # + # The <tt>match_block</tt> can have an arity of 1 or 2. The first block + # argument will be the given value. The second, if the block accepts it + # will be the matcher itself, giving you access to set custom failure + # messages in favor of the defaults. + # + # The <tt>match_block</tt> should return a boolean: <tt>true</tt> + # indicates a match, which will pass if you use <tt>should</tt> and fail + # if you use <tt>should_not</tt>. false (or nil) indicates no match, + # which will do the reverse: fail if you use <tt>should</tt> and pass if + # you use <tt>should_not</tt>. + # + # An error in the <tt>match_block</tt> will bubble up, resulting in a + # failure. + # + # == Example with default messages + # + # def be_even + # simple_matcher("an even number") { |given| given % 2 == 0 } + # end + # + # describe 2 do + # it "should be even" do + # 2.should be_even + # end + # end + # + # Given an odd number, this example would produce an error message stating: + # expected "an even number", got 3. + # + # Unfortunately, if you're a fan of auto-generated descriptions, this will + # produce "should an even number." Not the most desirable result. You can + # control that using custom messages: + # + # == Example with custom messages + # + # def rhyme_with(expected) + # simple_matcher("rhyme with #{expected.inspect}") do |given, matcher| + # matcher.failure_message = "expected #{given.inspect} to rhyme with #{expected.inspect}" + # matcher.negative_failure_message = "expected #{given.inspect} not to rhyme with #{expected.inspect}" + # given.rhymes_with? expected + # end + # end + # + # # OR + # + # def rhyme_with(expected) + # simple_matcher do |given, matcher| + # matcher.description = "rhyme with #{expected.inspect}" + # matcher.failure_message = "expected #{given.inspect} to rhyme with #{expected.inspect}" + # matcher.negative_failure_message = "expected #{given.inspect} not to rhyme with #{expected.inspect}" + # given.rhymes_with? expected + # end + # end + # + # describe "pecan" do + # it "should rhyme with 'be gone'" do + # nut = "pecan" + # nut.extend Rhymer + # nut.should rhyme_with("be gone") + # end + # end + # + # The resulting messages would be: + # description: rhyme with "be gone" + # failure_message: expected "pecan" to rhyme with "be gone" + # negative failure_message: expected "pecan" not to rhyme with "be gone" + # + # == Wrapped Expectations + # + # Because errors will bubble up, it is possible to wrap other expectations + # in a SimpleMatcher. + # + # def be_even + # simple_matcher("an even number") { |given| (given % 2).should == 0 } + # end + # + # BE VERY CAREFUL when you do this. Only use wrapped expectations for + # matchers that will always be used in only the positive + # (<tt>should</tt>) or negative (<tt>should_not</tt>), but not both. + # The reason is that is you wrap a <tt>should</tt> and call the wrapper + # with <tt>should_not</tt>, the correct result (the <tt>should</tt> + # failing), will fail when you want it to pass. + # + def simple_matcher(description=nil, &match_block) + SimpleMatcher.new(description, &match_block) end end end
\ No newline at end of file diff --git a/vendor/plugins/rspec/lib/spec/matchers/throw_symbol.rb b/vendor/plugins/rspec/lib/spec/matchers/throw_symbol.rb index c74d84436..da16bb654 100644 --- a/vendor/plugins/rspec/lib/spec/matchers/throw_symbol.rb +++ b/vendor/plugins/rspec/lib/spec/matchers/throw_symbol.rb @@ -2,39 +2,58 @@ module Spec module Matchers class ThrowSymbol #:nodoc: - def initialize(expected=nil) - @expected = expected - @actual = nil + def initialize(expected_symbol = nil, expected_arg=nil) + @expected_symbol = expected_symbol + @expected_arg = expected_arg + @caught_symbol = @caught_arg = nil end - def matches?(proc) + def matches?(given_proc) begin - proc.call - rescue NameError => e - raise e unless e.message =~ /uncaught throw/ - @actual = e.name.to_sym + if @expected_symbol.nil? + given_proc.call + else + @caught_arg = catch :proc_did_not_throw_anything do + catch @expected_symbol do + given_proc.call + throw :proc_did_not_throw_anything, :nothing_thrown + end + end + @caught_symbol = @expected_symbol unless @caught_arg == :nothing_thrown + end + + # Ruby 1.8 uses NameError with `symbol' + # Ruby 1.9 uses ArgumentError with :symbol + rescue NameError, ArgumentError => e + raise e unless e.message =~ /uncaught throw (`|\:)([a-zA-Z0-9_]*)(')?/ + @caught_symbol = $2.to_sym + ensure - if @expected.nil? - return @actual.nil? ? false : true + if @expected_symbol.nil? + return !@caught_symbol.nil? else - return @actual == @expected + if @expected_arg.nil? + return @caught_symbol == @expected_symbol + else + return (@caught_symbol == @expected_symbol) & (@caught_arg == @expected_arg) + end end end end - def failure_message - if @actual - "expected #{expected}, got #{@actual.inspect}" + def failure_message_for_should + if @caught_symbol + "expected #{expected}, got #{@caught_symbol.inspect}" else "expected #{expected} but nothing was thrown" end end - def negative_failure_message - if @expected + def failure_message_for_should_not + if @expected_symbol "expected #{expected} not to be thrown" else - "expected no Symbol, got :#{@actual}" + "expected no Symbol, got :#{@caught_symbol}" end end @@ -45,7 +64,11 @@ module Spec private def expected - @expected.nil? ? "a Symbol" : @expected.inspect + @expected_symbol.nil? ? "a Symbol" : "#{@expected_symbol.inspect}#{args}" + end + + def args + @expected_arg.nil? ? "" : " with #{@expected_arg.inspect}" end end @@ -53,20 +76,27 @@ module Spec # :call-seq: # should throw_symbol() # should throw_symbol(:sym) + # should throw_symbol(:sym, arg) # should_not throw_symbol() # should_not throw_symbol(:sym) - # - # Given a Symbol argument, matches if a proc throws the specified Symbol. + # should_not throw_symbol(:sym, arg) # # Given no argument, matches if a proc throws any Symbol. # + # Given a Symbol, matches if the given proc throws the specified Symbol. + # + # Given a Symbol and an arg, matches if the given proc throws the + # specified Symbol with the specified arg. + # # == Examples # # lambda { do_something_risky }.should throw_symbol # lambda { do_something_risky }.should throw_symbol(:that_was_risky) + # lambda { do_something_risky }.should throw_symbol(:that_was_risky, culprit) # # lambda { do_something_risky }.should_not throw_symbol # lambda { do_something_risky }.should_not throw_symbol(:that_was_risky) + # lambda { do_something_risky }.should_not throw_symbol(:that_was_risky, culprit) def throw_symbol(sym=nil) Matchers::ThrowSymbol.new(sym) end |