rspec-expectations 2.7.0 → 2.8.0.rc1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (38) hide show
  1. data/README.md +117 -9
  2. data/lib/rspec/expectations.rb +24 -16
  3. data/lib/rspec/expectations/handler.rb +1 -1
  4. data/lib/rspec/expectations/version.rb +1 -1
  5. data/lib/rspec/matchers.rb +91 -91
  6. data/lib/rspec/matchers/base_matcher.rb +41 -0
  7. data/lib/rspec/matchers/be.rb +31 -12
  8. data/lib/rspec/matchers/be_instance_of.rb +10 -12
  9. data/lib/rspec/matchers/be_kind_of.rb +10 -12
  10. data/lib/rspec/matchers/be_within.rb +36 -26
  11. data/lib/rspec/matchers/block_aliases.rb +2 -1
  12. data/lib/rspec/matchers/change.rb +1 -1
  13. data/lib/rspec/matchers/cover.rb +20 -19
  14. data/lib/rspec/matchers/eq.rb +22 -32
  15. data/lib/rspec/matchers/eql.rb +22 -28
  16. data/lib/rspec/matchers/equal.rb +37 -27
  17. data/lib/rspec/matchers/exist.rb +26 -18
  18. data/lib/rspec/matchers/have.rb +22 -28
  19. data/lib/rspec/matchers/include.rb +45 -37
  20. data/lib/rspec/matchers/match.rb +10 -10
  21. data/lib/rspec/matchers/match_array.rb +1 -7
  22. data/lib/rspec/matchers/matcher.rb +0 -8
  23. data/lib/rspec/matchers/operator_matcher.rb +0 -2
  24. data/lib/rspec/matchers/pretty.rb +25 -2
  25. data/lib/rspec/matchers/raise_error.rb +2 -16
  26. data/lib/rspec/matchers/respond_to.rb +1 -6
  27. data/lib/rspec/matchers/satisfy.rb +1 -6
  28. data/lib/rspec/matchers/throw_symbol.rb +2 -11
  29. data/spec/rspec/expectations/handler_spec.rb +1 -1
  30. data/spec/rspec/matchers/change_spec.rb +1 -1
  31. data/spec/rspec/matchers/description_generation_spec.rb +2 -2
  32. data/spec/rspec/matchers/eq_spec.rb +1 -1
  33. data/spec/rspec/matchers/eql_spec.rb +2 -2
  34. data/spec/rspec/matchers/equal_spec.rb +1 -1
  35. data/spec/rspec/matchers/include_spec.rb +4 -0
  36. data/spec/rspec/matchers/raise_error_spec.rb +2 -2
  37. data/spec/spec_helper.rb +1 -0
  38. metadata +15 -10
@@ -1,27 +1,16 @@
1
1
  module RSpec
2
2
  module Matchers
3
- # Passes if <tt>actual.equal?(expected)</tt> (object identity).
4
- #
5
- # See http://www.ruby-doc.org/core/classes/Object.html#M001057 for more information about equality in Ruby.
6
- #
7
- # == Examples
8
- #
9
- # 5.should equal(5) # Fixnums are equal
10
- # "5".should_not equal("5") # Strings that look the same are not the same object
11
- def equal(expected)
12
- Matcher.new :equal, expected do |_expected_|
13
- match do |actual|
14
- actual.equal?(_expected_)
15
- end
16
-
17
- def inspect_object(o)
18
- "#<#{o.class}:#{o.object_id}> => #{o.inspect}"
19
- end
20
-
21
- failure_message_for_should do |actual|
22
- <<-MESSAGE
23
-
24
- expected #{inspect_object(_expected_)}
3
+ class Equal
4
+ include BaseMatcher
5
+
6
+ def matches?(actual)
7
+ super(actual).equal?(expected)
8
+ end
9
+
10
+ def failure_message_for_should
11
+ return <<-MESSAGE
12
+
13
+ expected #{inspect_object(expected)}
25
14
  got #{inspect_object(actual)}
26
15
 
27
16
  Compared using equal?, which compares object identity,
@@ -30,19 +19,40 @@ but expected and actual are not the same object. Use
30
19
  object identity in this example.
31
20
 
32
21
  MESSAGE
33
- end
22
+ end
34
23
 
35
- failure_message_for_should_not do |actual|
36
- <<-MESSAGE
24
+ def failure_message_for_should_not
25
+ return <<-MESSAGE
37
26
 
38
27
  expected not #{inspect_object(actual)}
39
- got #{inspect_object(_expected_)}
28
+ got #{inspect_object(expected)}
40
29
 
41
30
  Compared using equal?, which compares object identity.
42
31
 
43
32
  MESSAGE
44
- end
45
33
  end
34
+
35
+ def diffable?
36
+ true
37
+ end
38
+
39
+ private
40
+
41
+ def inspect_object(o)
42
+ "#<#{o.class}:#{o.object_id}> => #{o.inspect}"
43
+ end
44
+ end
45
+
46
+ # Passes if <tt>actual.equal?(expected)</tt> (object identity).
47
+ #
48
+ # See http://www.ruby-doc.org/core/classes/Object.html#M001057 for more information about equality in Ruby.
49
+ #
50
+ # @example
51
+ #
52
+ # 5.should equal(5) # Fixnums are equal
53
+ # "5".should_not equal("5") # Strings that look the same are not the same object
54
+ def equal(expected)
55
+ Equal.new(expected)
46
56
  end
47
57
  end
48
58
  end
@@ -1,26 +1,34 @@
1
1
  module RSpec
2
2
  module Matchers
3
- # :call-seq:
4
- # should exist
5
- # should_not exist
6
- #
7
- # Passes if actual.exist? or actual.exists?
8
- def exist(*args)
9
- Matcher.new :exist do
10
- match do |actual|
11
- predicates = [:exist?, :exists?].select { |p| actual.respond_to?(p) }
12
- existance_values = predicates.map { |p| actual.send(p, *args) }
13
- uniq_truthy_values = existance_values.map { |v| !!v }.uniq
3
+ class Exist
4
+ include BaseMatcher
5
+
6
+ def initialize(*args)
7
+ super(args)
8
+ end
9
+
10
+ def matches?(actual)
11
+ super(actual)
12
+ predicates = [:exist?, :exists?].select { |p| actual.respond_to?(p) }
13
+ existance_values = predicates.map { |p| actual.send(p, *expected) }
14
+ uniq_truthy_values = existance_values.map { |v| !!v }.uniq
14
15
 
15
- case uniq_truthy_values.size
16
- when 0; raise NoMethodError.new("#{actual.inspect} does not respond to either #exist? or #exists?")
17
- when 1; existance_values.first
18
- else raise "#exist? and #exists? returned different values:\n\n" +
19
- " exist?: #{existance_values.first}\n" +
20
- "exists?: #{existance_values.last}"
21
- end
16
+ case uniq_truthy_values.size
17
+ when 0; raise NoMethodError.new("#{actual.inspect} does not respond to either #exist? or #exists?")
18
+ when 1; existance_values.first
19
+ else raise "#exist? and #exists? returned different values:\n\n" +
20
+ " exist?: #{existance_values.first}\n" +
21
+ "exists?: #{existance_values.last}"
22
22
  end
23
23
  end
24
24
  end
25
+
26
+ # Passes if `actual.exist?` or `actual.exists?`
27
+ #
28
+ # @example
29
+ # File.should exist("path/to/file")
30
+ def exist(*args)
31
+ Exist.new(*args)
32
+ end
25
33
  end
26
34
  end
@@ -102,28 +102,22 @@ EOF
102
102
  end
103
103
  end
104
104
 
105
- # :call-seq:
106
- # should have(number).named_collection__or__sugar
107
- # should_not have(number).named_collection__or__sugar
105
+ # Passes if receiver is a collection with the submitted number of items OR
106
+ # if the receiver OWNS a collection with the submitted number of items.
108
107
  #
109
- # Passes if receiver is a collection with the submitted
110
- # number of items OR if the receiver OWNS a collection
111
- # with the submitted number of items.
108
+ # If the receiver OWNS the collection, you must use the name of the
109
+ # collection. So if a `Team` instance has a collection named `#players`,
110
+ # you must use that name to set the expectation.
112
111
  #
113
- # If the receiver OWNS the collection, you must use the name
114
- # of the collection. So if a <tt>Team</tt> instance has a
115
- # collection named <tt>#players</tt>, you must use that name
116
- # to set the expectation.
112
+ # If the receiver IS the collection, you can use any name you like for
113
+ # `named_collection`. We'd recommend using either "elements", "members", or
114
+ # "items" as these are all standard ways of describing the things IN a
115
+ # collection.
117
116
  #
118
- # If the receiver IS the collection, you can use any name
119
- # you like for <tt>named_collection</tt>. We'd recommend using
120
- # either "elements", "members", or "items" as these are all
121
- # standard ways of describing the things IN a collection.
117
+ # This also works for Strings, letting you set expectations about their
118
+ # lengths.
122
119
  #
123
- # This also works for Strings, letting you set an expectation
124
- # about its length
125
- #
126
- # == Examples
120
+ # @example
127
121
  #
128
122
  # # Passes if team.players.size == 11
129
123
  # team.should have(11).players
@@ -141,26 +135,26 @@ EOF
141
135
  end
142
136
  alias :have_exactly :have
143
137
 
144
- # :call-seq:
145
- # should have_at_least(number).items
146
- #
147
138
  # Exactly like have() with >=.
148
139
  #
149
- # == Warning
140
+ # @example
141
+ # "this".should have_at_least(3).letters
150
142
  #
151
- # +should_not+ +have_at_least+ is not supported
143
+ # ### Warning:
144
+ #
145
+ # `should_not have_at_least` is not supported
152
146
  def have_at_least(n)
153
147
  Matchers::Have.new(n, :at_least)
154
148
  end
155
149
 
156
- # :call-seq:
157
- # should have_at_most(number).items
158
- #
159
150
  # Exactly like have() with <=.
160
151
  #
161
- # == Warning
152
+ # @example
153
+ # should have_at_most(number).items
154
+ #
155
+ # ### Warning:
162
156
  #
163
- # +should_not+ +have_at_most+ is not supported
157
+ # `should_not have_at_most` is not supported
164
158
  def have_at_most(n)
165
159
  Matchers::Have.new(n, :at_most)
166
160
  end
@@ -1,14 +1,53 @@
1
1
  module RSpec
2
2
  module Matchers
3
- # :call-seq:
4
- # should include(expected)
5
- # should_not include(expected)
6
- #
3
+ class Include
4
+ include BaseMatcher
5
+
6
+ def initialize(*expected)
7
+ super(expected)
8
+ end
9
+
10
+ def matches?(actual)
11
+ perform_match(:all?, :all?, super(actual), expected)
12
+ end
13
+
14
+ def does_not_match?(actual)
15
+ @actual = actual
16
+ perform_match(:none?, :any?, actual, expected)
17
+ end
18
+
19
+ def description
20
+ "include#{expected_to_sentence}"
21
+ end
22
+
23
+ private
24
+
25
+ def perform_match(predicate, hash_predicate, actuals, expecteds)
26
+ expecteds.send(predicate) do |expected|
27
+ if comparing_hash_values?(actuals, expected)
28
+ expected.send(hash_predicate) {|k,v| actuals[k] == v}
29
+ elsif comparing_hash_keys?(actuals, expected)
30
+ actuals.has_key?(expected)
31
+ else
32
+ actuals.include?(expected)
33
+ end
34
+ end
35
+ end
36
+
37
+ def comparing_hash_keys?(actual, expected)
38
+ actual.is_a?(Hash) && !expected.is_a?(Hash)
39
+ end
40
+
41
+ def comparing_hash_values?(actual, expected)
42
+ actual.is_a?(Hash) && expected.is_a?(Hash)
43
+ end
44
+ end
45
+
7
46
  # Passes if actual includes expected. This works for
8
47
  # collections and Strings. You can also pass in multiple args
9
48
  # and it will only pass if all args are found in collection.
10
49
  #
11
- # == Examples
50
+ # @example
12
51
  #
13
52
  # [1,2,3].should include(3)
14
53
  # [1,2,3].should include(2,3) #would pass
@@ -17,38 +56,7 @@ module RSpec
17
56
  # "spread".should include("read")
18
57
  # "spread".should_not include("red")
19
58
  def include(*expected)
20
- Matcher.new :include, *expected do |*_expected|
21
-
22
- diffable
23
-
24
- match_for_should do |actual|
25
- perform_match(:all?, :all?, actual, _expected)
26
- end
27
-
28
- match_for_should_not do |actual|
29
- perform_match(:none?, :any?, actual, _expected)
30
- end
31
-
32
- def perform_match(predicate, hash_predicate, actual, _expected)
33
- _expected.send(predicate) do |expected|
34
- if comparing_hash_values?(actual, expected)
35
- expected.send(hash_predicate) {|k,v| actual[k] == v}
36
- elsif comparing_hash_keys?(actual, expected)
37
- actual.has_key?(expected)
38
- else
39
- actual.include?(expected)
40
- end
41
- end
42
- end
43
-
44
- def comparing_hash_keys?(actual, expected)
45
- actual.is_a?(Hash) && !expected.is_a?(Hash)
46
- end
47
-
48
- def comparing_hash_values?(actual, expected)
49
- actual.is_a?(Hash) && expected.is_a?(Hash)
50
- end
51
- end
59
+ Include.new(*expected)
52
60
  end
53
61
  end
54
62
  end
@@ -1,21 +1,21 @@
1
1
  module RSpec
2
2
  module Matchers
3
- # :call-seq:
4
- # should match(pattern)
5
- # should_not match(pattern)
6
- #
3
+ class Match
4
+ include BaseMatcher
5
+
6
+ def matches?(actual)
7
+ super(actual).match(expected)
8
+ end
9
+ end
10
+
7
11
  # Given a Regexp or String, passes if actual.match(pattern)
8
12
  #
9
- # == Examples
13
+ # @example
10
14
  #
11
15
  # email.should match(/^([^\s]+)((?:[-a-z0-9]+\.)+[a-z]{2,})$/i)
12
16
  # email.should match("@example.com")
13
17
  def match(expected)
14
- Matcher.new :match, expected do |_expected_|
15
- match do |actual|
16
- actual.match(_expected_)
17
- end
18
- end
18
+ Match.new(expected)
19
19
  end
20
20
  end
21
21
  end
@@ -1,6 +1,5 @@
1
1
  module RSpec
2
2
  module Matchers
3
-
4
3
  class MatchArray
5
4
  include RSpec::Matchers::Pretty
6
5
 
@@ -46,20 +45,15 @@ module RSpec
46
45
  end
47
46
  difference
48
47
  end
49
-
50
-
51
48
  end
52
49
 
53
- # :call-seq:
54
- # should =~ expected
55
- #
56
50
  # Passes if actual contains all of the expected regardless of order.
57
51
  # This works for collections. Pass in multiple args and it will only
58
52
  # pass if all args are found in collection.
59
53
  #
60
54
  # NOTE: there is no should_not version of array.should =~ other_array
61
55
  #
62
- # == Examples
56
+ # @example
63
57
  #
64
58
  # [1,2,3].should =~ [1,2,3] # => would pass
65
59
  # [1,2,3].should =~ [2,3,1] # => would pass
@@ -147,14 +147,6 @@ module RSpec
147
147
  @messages[key].arity == 1 ? @messages[key].call(@actual) : @messages[key].call
148
148
  end
149
149
 
150
- def name_to_sentence
151
- split_words(@name)
152
- end
153
-
154
- def expected_to_sentence
155
- to_sentence(@expected)
156
- end
157
-
158
150
  unless method_defined?(:singleton_class)
159
151
  def singleton_class
160
152
  class << self; self; end
@@ -1,6 +1,5 @@
1
1
  module RSpec
2
2
  module Matchers
3
-
4
3
  class OperatorMatcher
5
4
  class << self
6
5
  def registry
@@ -82,6 +81,5 @@ module RSpec
82
81
  end
83
82
 
84
83
  end
85
-
86
84
  end
87
85
  end
@@ -6,7 +6,8 @@ module RSpec
6
6
  end
7
7
 
8
8
  def to_sentence(words)
9
- words = words.map{|w| w.inspect}
9
+ return "" unless words
10
+ words = Array(words).map{|w| w.inspect}
10
11
  case words.length
11
12
  when 0
12
13
  ""
@@ -32,6 +33,28 @@ module RSpec
32
33
  end
33
34
  result
34
35
  end
36
+
37
+ def name_to_sentence
38
+ split_words(name)
39
+ end
40
+
41
+ def expected_to_sentence
42
+ to_sentence(@expected) if defined?(@expected)
43
+ end
44
+
45
+ def name
46
+ defined?(@name) ? @name : underscore(self.class.name.split("::").last)
47
+ end
48
+
49
+ # Borrowed from ActiveSupport
50
+ def underscore(camel_cased_word)
51
+ word = camel_cased_word.to_s.dup
52
+ word.gsub!(/([A-Z]+)([A-Z][a-z])/,'\1_\2')
53
+ word.gsub!(/([a-z\d])([A-Z])/,'\1_\2')
54
+ word.tr!("-", "_")
55
+ word.downcase!
56
+ word
57
+ end
35
58
  end
36
59
  end
37
- end
60
+ end
@@ -25,7 +25,7 @@ module RSpec
25
25
  rescue Exception => @actual_error
26
26
  # This clause should be empty, but rcov will not report it as covered
27
27
  # unless something (anything) is executed within the clause
28
- rcov_error_report = "http://eigenclass.org/hiki.rb?rcov-0.8.0"
28
+ "http://eigenclass.org/hiki.rb?rcov-0.8.0"
29
29
  end
30
30
 
31
31
  unless negative_expectation?
@@ -90,27 +90,13 @@ module RSpec
90
90
  end
91
91
  end
92
92
 
93
- # :call-seq:
94
- # should raise_error()
95
- # should raise_error(NamedError)
96
- # should raise_error(NamedError, String)
97
- # should raise_error(NamedError, Regexp)
98
- # should raise_error() { |error| ... }
99
- # should raise_error(NamedError) { |error| ... }
100
- # should raise_error(NamedError, String) { |error| ... }
101
- # should raise_error(NamedError, Regexp) { |error| ... }
102
- # should_not raise_error()
103
- # should_not raise_error(NamedError)
104
- # should_not raise_error(NamedError, String)
105
- # should_not raise_error(NamedError, Regexp)
106
- #
107
93
  # With no args, matches if any error is raised.
108
94
  # With a named error, matches only if that specific error is raised.
109
95
  # With a named error and messsage specified as a String, matches only if both match.
110
96
  # With a named error and messsage specified as a Regexp, matches only if both match.
111
97
  # Pass an optional block to perform extra verifications on the exception matched
112
98
  #
113
- # == Examples
99
+ # @example
114
100
  #
115
101
  # lambda { do_something_risky }.should raise_error
116
102
  # lambda { do_something_risky }.should raise_error(PoorRiskDecisionError)