rspec-expectations 2.7.0 → 2.8.0.rc1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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)