rspec-expectations 2.0.0.a1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (55) hide show
  1. data/.document +5 -0
  2. data/.gitignore +5 -0
  3. data/License.txt +22 -0
  4. data/README.markdown +8 -0
  5. data/Rakefile +43 -0
  6. data/VERSION +1 -0
  7. data/VERSION.yml +5 -0
  8. data/lib/rspec/expectations.rb +36 -0
  9. data/lib/rspec/expectations/differs/default.rb +62 -0
  10. data/lib/rspec/expectations/differs/load-diff-lcs.rb +12 -0
  11. data/lib/rspec/expectations/errors.rb +12 -0
  12. data/lib/rspec/expectations/extensions.rb +1 -0
  13. data/lib/rspec/expectations/extensions/kernel.rb +52 -0
  14. data/lib/rspec/expectations/fail_with.rb +43 -0
  15. data/lib/rspec/expectations/handler.rb +50 -0
  16. data/lib/rspec/matchers.rb +195 -0
  17. data/lib/rspec/matchers/be.rb +210 -0
  18. data/lib/rspec/matchers/be_close.rb +32 -0
  19. data/lib/rspec/matchers/be_instance_of.rb +26 -0
  20. data/lib/rspec/matchers/be_kind_of.rb +26 -0
  21. data/lib/rspec/matchers/change.rb +151 -0
  22. data/lib/rspec/matchers/compatibility.rb +14 -0
  23. data/lib/rspec/matchers/dsl.rb +14 -0
  24. data/lib/rspec/matchers/eql.rb +42 -0
  25. data/lib/rspec/matchers/equal.rb +53 -0
  26. data/lib/rspec/matchers/errors.rb +5 -0
  27. data/lib/rspec/matchers/exist.rb +16 -0
  28. data/lib/rspec/matchers/extensions/instance_exec.rb +23 -0
  29. data/lib/rspec/matchers/generated_descriptions.rb +36 -0
  30. data/lib/rspec/matchers/has.rb +35 -0
  31. data/lib/rspec/matchers/have.rb +151 -0
  32. data/lib/rspec/matchers/include.rb +44 -0
  33. data/lib/rspec/matchers/match.rb +21 -0
  34. data/lib/rspec/matchers/match_array.rb +71 -0
  35. data/lib/rspec/matchers/matcher.rb +86 -0
  36. data/lib/rspec/matchers/method_missing.rb +9 -0
  37. data/lib/rspec/matchers/operator_matcher.rb +78 -0
  38. data/lib/rspec/matchers/pretty.rb +37 -0
  39. data/lib/rspec/matchers/raise_error.rb +129 -0
  40. data/lib/rspec/matchers/respond_to.rb +71 -0
  41. data/lib/rspec/matchers/satisfy.rb +47 -0
  42. data/lib/rspec/matchers/simple_matcher.rb +133 -0
  43. data/lib/rspec/matchers/throw_symbol.rb +104 -0
  44. data/lib/rspec/matchers/wrap_expectation.rb +55 -0
  45. data/rspec-expectations.gemspec +104 -0
  46. data/spec/rspec/expectations/differs/default_spec.rb +128 -0
  47. data/spec/rspec/expectations/extensions/kernel_spec.rb +45 -0
  48. data/spec/rspec/expectations/fail_with_spec.rb +88 -0
  49. data/spec/rspec/expectations/handler_spec.rb +206 -0
  50. data/spec/rspec/expectations/wrap_expectation_spec.rb +30 -0
  51. data/spec/spec.opts +6 -0
  52. data/spec/spec_helper.rb +31 -0
  53. data/spec/suite.rb +1 -0
  54. data/spec/support/macros.rb +29 -0
  55. metadata +135 -0
@@ -0,0 +1,14 @@
1
+ Rspec::Matchers.constants.each do |c|
2
+ if Class === (klass = Rspec::Matchers.const_get(c))
3
+ if klass.public_instance_methods.any? {|m| ['failure_message_for_should',:failure_message_for_should].include?(m)}
4
+ klass.class_eval do
5
+ alias_method :failure_message, :failure_message_for_should
6
+ end
7
+ end
8
+ if klass.public_instance_methods.any? {|m| ['failure_message_for_should_not',:failure_message_for_should_not].include?(m)}
9
+ klass.class_eval do
10
+ alias_method :negative_failure_message, :failure_message_for_should_not
11
+ end
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,14 @@
1
+ module Rspec
2
+ module Matchers
3
+ module DSL
4
+ # See Rspec::Matchers
5
+ def define(name, &declarations)
6
+ define_method name do |*expected|
7
+ Rspec::Matchers::Matcher.new name, *expected, &declarations
8
+ end
9
+ end
10
+ end
11
+ end
12
+ end
13
+
14
+ Rspec::Matchers.extend Rspec::Matchers::DSL
@@ -0,0 +1,42 @@
1
+ module Rspec
2
+ module Matchers
3
+ # :call-seq:
4
+ # should eql(expected)
5
+ # should_not eql(expected)
6
+ #
7
+ # Passes if actual and expected are of equal value, but not necessarily the same object.
8
+ #
9
+ # See http://www.ruby-doc.org/core/classes/Object.html#M001057 for more information about equality in Ruby.
10
+ #
11
+ # == Examples
12
+ #
13
+ # 5.should eql(5)
14
+ # 5.should_not eql(3)
15
+ def eql(expected)
16
+ Matcher.new :eql, expected do |_expected_|
17
+ match do |actual|
18
+ actual.eql?(_expected_)
19
+ end
20
+
21
+ failure_message_for_should do |actual|
22
+ <<-MESSAGE
23
+
24
+ expected #{_expected_.inspect}
25
+ got #{actual.inspect}
26
+
27
+ (compared using eql?)
28
+ MESSAGE
29
+ end
30
+
31
+ failure_message_for_should_not do |actual|
32
+ <<-MESSAGE
33
+
34
+ expected #{actual.inspect} not to equal #{_expected_.inspect}
35
+
36
+ (compared using eql?)
37
+ MESSAGE
38
+ end
39
+ end
40
+ end
41
+ end
42
+ end
@@ -0,0 +1,53 @@
1
+ module Rspec
2
+ module Matchers
3
+
4
+ # :call-seq:
5
+ # should equal(expected)
6
+ # should_not equal(expected)
7
+ #
8
+ # Passes if actual and expected are the same object (object identity).
9
+ #
10
+ # See http://www.ruby-doc.org/core/classes/Object.html#M001057 for more information about equality in Ruby.
11
+ #
12
+ # == Examples
13
+ #
14
+ # 5.should equal(5) #Fixnums are equal
15
+ # "5".should_not equal("5") #Strings that look the same are not the same object
16
+ def equal(expected)
17
+ Matcher.new :equal, expected do |_expected_|
18
+ match do |actual|
19
+ actual.equal?(_expected_)
20
+ end
21
+
22
+ def inspect_object(o)
23
+ "#<#{o.class}:#{o.object_id}> => #{o.inspect}"
24
+ end
25
+
26
+ failure_message_for_should do |actual|
27
+ <<-MESSAGE
28
+
29
+ expected #{inspect_object(_expected_)}
30
+ got #{inspect_object(actual)}
31
+
32
+ Compared using equal?, which compares object identity,
33
+ but expected and actual are not the same object. Use
34
+ 'actual.should == expected' if you don't care about
35
+ object identity in this example.
36
+
37
+ MESSAGE
38
+ end
39
+
40
+ failure_message_for_should_not do |actual|
41
+ <<-MESSAGE
42
+
43
+ expected not #{inspect_object(actual)}
44
+ got #{inspect_object(_expected_)}
45
+
46
+ Compared using equal?, which compares object identity.
47
+
48
+ MESSAGE
49
+ end
50
+ end
51
+ end
52
+ end
53
+ end
@@ -0,0 +1,5 @@
1
+ module Rspec
2
+ module Matchers
3
+ class MatcherError < StandardError; end
4
+ end
5
+ end
@@ -0,0 +1,16 @@
1
+ module Rspec
2
+ module Matchers
3
+ # :call-seq:
4
+ # should exist
5
+ # should_not exist
6
+ #
7
+ # Passes if actual.exist?
8
+ def exist
9
+ Matcher.new :exist do
10
+ match do |actual|
11
+ actual.exist?
12
+ end
13
+ end
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,23 @@
1
+ unless respond_to?(:instance_exec)
2
+ # based on Bounded Spec InstanceExec (Mauricio Fernandez)
3
+ # http://eigenclass.org/hiki/bounded+space+instance_exec
4
+ class Object
5
+ module InstanceExecHelper; end
6
+ include InstanceExecHelper
7
+ def instance_exec(*args, &block)
8
+ begin
9
+ orig_critical, Thread.critical = Thread.critical, true
10
+ n = 0
11
+ n += 1 while respond_to?(method_name="__instance_exec#{n}")
12
+ InstanceExecHelper.module_eval{ define_method(method_name, &block) }
13
+ ensure
14
+ Thread.critical = orig_critical
15
+ end
16
+ begin
17
+ return send(method_name, *args)
18
+ ensure
19
+ InstanceExecHelper.module_eval{ remove_method(method_name) } rescue nil
20
+ end
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,36 @@
1
+ module Rspec
2
+ module Matchers
3
+ class << self
4
+ attr_accessor :last_matcher, :last_should # :nodoc:
5
+ end
6
+
7
+ def self.clear_generated_description
8
+ self.last_matcher = nil
9
+ self.last_should = nil
10
+ end
11
+
12
+ def self.generated_description
13
+ return nil if last_should.nil?
14
+ "#{last_should.to_s.gsub('_',' ')} #{last_description}"
15
+ end
16
+
17
+ private
18
+
19
+ def self.last_description
20
+ last_matcher.respond_to?(:description) ? last_matcher.description : <<-MESSAGE
21
+ When you call a matcher in an example without a String, like this:
22
+
23
+ specify { object.should matcher }
24
+
25
+ or this:
26
+
27
+ it { should matcher }
28
+
29
+ RSpec expects the matcher to have a #description method. You should either
30
+ add a String to the example this matcher is being used in, or give it a
31
+ description method. Then you won't have to suffer this lengthy warning again.
32
+ MESSAGE
33
+ end
34
+ end
35
+ end
36
+
@@ -0,0 +1,35 @@
1
+ module Rspec
2
+ module Matchers
3
+
4
+ class Has
5
+
6
+ def initialize(expected, *args)
7
+ @expected, @args = expected, args
8
+ end
9
+
10
+ def matches?(actual)
11
+ actual.__send__(predicate(@expected), *@args)
12
+ end
13
+
14
+ def failure_message_for_should
15
+ "expected ##{predicate(@expected)}(#{@args[0].inspect}) to return true, got false"
16
+ end
17
+
18
+ def failure_message_for_should_not
19
+ "expected ##{predicate(@expected)}(#{@args[0].inspect}) to return false, got true"
20
+ end
21
+
22
+ def description
23
+ "have key #{@args[0].inspect}"
24
+ end
25
+
26
+ private
27
+
28
+ def predicate(sym)
29
+ "#{sym.to_s.sub("have_","has_")}?".to_sym
30
+ end
31
+
32
+ end
33
+
34
+ end
35
+ end
@@ -0,0 +1,151 @@
1
+ module Rspec
2
+ module Matchers
3
+ class Have #:nodoc:
4
+ def initialize(expected, relativity=:exactly)
5
+ @expected = (expected == :no ? 0 : expected)
6
+ @relativity = relativity
7
+ @actual = nil
8
+ end
9
+
10
+ def relativities
11
+ @relativities ||= {
12
+ :exactly => "",
13
+ :at_least => "at least ",
14
+ :at_most => "at most "
15
+ }
16
+ end
17
+
18
+ def matches?(collection_owner)
19
+ if collection_owner.respond_to?(@collection_name)
20
+ collection = collection_owner.__send__(@collection_name, *@args, &@block)
21
+ elsif (@plural_collection_name && collection_owner.respond_to?(@plural_collection_name))
22
+ collection = collection_owner.__send__(@plural_collection_name, *@args, &@block)
23
+ elsif (collection_owner.respond_to?(:length) || collection_owner.respond_to?(:size))
24
+ collection = collection_owner
25
+ else
26
+ collection_owner.__send__(@collection_name, *@args, &@block)
27
+ end
28
+ @actual = collection.size if collection.respond_to?(:size)
29
+ @actual = collection.length if collection.respond_to?(:length)
30
+ raise not_a_collection if @actual.nil?
31
+ return @actual >= @expected if @relativity == :at_least
32
+ return @actual <= @expected if @relativity == :at_most
33
+ return @actual == @expected
34
+ end
35
+
36
+ def not_a_collection
37
+ "expected #{@collection_name} to be a collection but it does not respond to #length or #size"
38
+ end
39
+
40
+ def failure_message_for_should
41
+ "expected #{relative_expectation} #{@collection_name}, got #{@actual}"
42
+ end
43
+
44
+ def failure_message_for_should_not
45
+ if @relativity == :exactly
46
+ return "expected target not to have #{@expected} #{@collection_name}, got #{@actual}"
47
+ elsif @relativity == :at_most
48
+ return <<-EOF
49
+ Isn't life confusing enough?
50
+ Instead of having to figure out the meaning of this:
51
+ should_not have_at_most(#{@expected}).#{@collection_name}
52
+ We recommend that you use this instead:
53
+ should have_at_least(#{@expected + 1}).#{@collection_name}
54
+ EOF
55
+ elsif @relativity == :at_least
56
+ return <<-EOF
57
+ Isn't life confusing enough?
58
+ Instead of having to figure out the meaning of this:
59
+ should_not have_at_least(#{@expected}).#{@collection_name}
60
+ We recommend that you use this instead:
61
+ should have_at_most(#{@expected - 1}).#{@collection_name}
62
+ EOF
63
+ end
64
+ end
65
+
66
+ def description
67
+ "have #{relative_expectation} #{@collection_name}"
68
+ end
69
+
70
+ def respond_to?(sym)
71
+ @expected.respond_to?(sym) || super
72
+ end
73
+
74
+ private
75
+
76
+ def method_missing(sym, *args, &block)
77
+ @collection_name = sym
78
+ if inflector = (defined?(ActiveSupport::Inflector) ? ActiveSupport::Inflector : (defined?(Inflector) ? Inflector : nil))
79
+ @plural_collection_name = inflector.pluralize(sym.to_s)
80
+ end
81
+ @args = args
82
+ @block = block
83
+ self
84
+ end
85
+
86
+ def relative_expectation
87
+ "#{relativities[@relativity]}#{@expected}"
88
+ end
89
+ end
90
+
91
+ # :call-seq:
92
+ # should have(number).named_collection__or__sugar
93
+ # should_not have(number).named_collection__or__sugar
94
+ #
95
+ # Passes if receiver is a collection with the submitted
96
+ # number of items OR if the receiver OWNS a collection
97
+ # with the submitted number of items.
98
+ #
99
+ # If the receiver OWNS the collection, you must use the name
100
+ # of the collection. So if a <tt>Team</tt> instance has a
101
+ # collection named <tt>#players</tt>, you must use that name
102
+ # to set the expectation.
103
+ #
104
+ # If the receiver IS the collection, you can use any name
105
+ # you like for <tt>named_collection</tt>. We'd recommend using
106
+ # either "elements", "members", or "items" as these are all
107
+ # standard ways of describing the things IN a collection.
108
+ #
109
+ # This also works for Strings, letting you set an expectation
110
+ # about its length
111
+ #
112
+ # == Examples
113
+ #
114
+ # # Passes if team.players.size == 11
115
+ # team.should have(11).players
116
+ #
117
+ # # Passes if [1,2,3].length == 3
118
+ # [1,2,3].should have(3).items #"items" is pure sugar
119
+ #
120
+ # # Passes if "this string".length == 11
121
+ # "this string".should have(11).characters #"characters" is pure sugar
122
+ def have(n)
123
+ Matchers::Have.new(n)
124
+ end
125
+ alias :have_exactly :have
126
+
127
+ # :call-seq:
128
+ # should have_at_least(number).items
129
+ #
130
+ # Exactly like have() with >=.
131
+ #
132
+ # == Warning
133
+ #
134
+ # +should_not+ +have_at_least+ is not supported
135
+ def have_at_least(n)
136
+ Matchers::Have.new(n, :at_least)
137
+ end
138
+
139
+ # :call-seq:
140
+ # should have_at_most(number).items
141
+ #
142
+ # Exactly like have() with <=.
143
+ #
144
+ # == Warning
145
+ #
146
+ # +should_not+ +have_at_most+ is not supported
147
+ def have_at_most(n)
148
+ Matchers::Have.new(n, :at_most)
149
+ end
150
+ end
151
+ end
@@ -0,0 +1,44 @@
1
+ module Rspec
2
+ module Matchers
3
+ # :call-seq:
4
+ # should include(expected)
5
+ # should_not include(expected)
6
+ #
7
+ # Passes if actual includes expected. This works for
8
+ # collections and Strings. You can also pass in multiple args
9
+ # and it will only pass if all args are found in collection.
10
+ #
11
+ # == Examples
12
+ #
13
+ # [1,2,3].should include(3)
14
+ # [1,2,3].should include(2,3) #would pass
15
+ # [1,2,3].should include(2,3,4) #would fail
16
+ # [1,2,3].should_not include(4)
17
+ # "spread".should include("read")
18
+ # "spread".should_not include("red")
19
+ def include(*expected)
20
+ Matcher.new :include, *expected do |*_expected_|
21
+ match do |actual|
22
+ helper(actual, *_expected_)
23
+ end
24
+
25
+ def helper(actual, *_expected_)
26
+ _expected_.each do |expected|
27
+ if actual.is_a?(Hash)
28
+ if expected.is_a?(Hash)
29
+ expected.each_pair do |k,v|
30
+ return false unless actual[k] == v
31
+ end
32
+ else
33
+ return false unless actual.has_key?(expected)
34
+ end
35
+ else
36
+ return false unless actual.include?(expected)
37
+ end
38
+ end
39
+ true
40
+ end
41
+ end
42
+ end
43
+ end
44
+ end