rspec-expectations 2.99.2 → 3.0.0.beta1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (98) hide show
  1. checksums.yaml +14 -6
  2. checksums.yaml.gz.sig +0 -0
  3. data.tar.gz.sig +2 -0
  4. data/Changelog.md +63 -104
  5. data/License.txt +1 -0
  6. data/README.md +14 -8
  7. data/features/README.md +1 -2
  8. data/features/built_in_matchers/README.md +3 -0
  9. data/features/built_in_matchers/be.feature +44 -44
  10. data/features/built_in_matchers/be_within.feature +1 -1
  11. data/features/built_in_matchers/comparisons.feature +97 -0
  12. data/features/built_in_matchers/cover.feature +3 -3
  13. data/features/built_in_matchers/end_with.feature +3 -3
  14. data/features/built_in_matchers/equality.feature +20 -23
  15. data/features/built_in_matchers/exist.feature +5 -5
  16. data/features/built_in_matchers/expect_error.feature +14 -14
  17. data/features/built_in_matchers/include.feature +15 -15
  18. data/features/built_in_matchers/match.feature +4 -5
  19. data/features/built_in_matchers/match_array.feature +37 -0
  20. data/features/built_in_matchers/predicates.feature +30 -6
  21. data/features/built_in_matchers/respond_to.feature +4 -4
  22. data/features/built_in_matchers/satisfy.feature +2 -2
  23. data/features/built_in_matchers/start_with.feature +3 -3
  24. data/features/built_in_matchers/types.feature +6 -6
  25. data/features/custom_matchers/access_running_example.feature +3 -3
  26. data/features/custom_matchers/define_matcher.feature +6 -34
  27. data/features/custom_matchers/define_matcher_outside_rspec.feature +2 -2
  28. data/features/custom_matchers/define_matcher_with_fluent_interface.feature +1 -1
  29. data/features/customized_message.feature +18 -1
  30. data/features/diffing.feature +3 -3
  31. data/features/implicit_docstrings.feature +9 -9
  32. data/features/step_definitions/additional_cli_steps.rb +0 -10
  33. data/features/support/env.rb +10 -3
  34. data/features/test_frameworks/test_unit.feature +0 -40
  35. data/lib/rspec-expectations.rb +0 -5
  36. data/lib/rspec/expectations.rb +4 -18
  37. data/lib/rspec/expectations/expectation_target.rb +10 -77
  38. data/lib/rspec/expectations/extensions.rb +0 -1
  39. data/lib/rspec/expectations/handler.rb +1 -5
  40. data/lib/rspec/expectations/syntax.rb +25 -5
  41. data/lib/rspec/expectations/version.rb +1 -1
  42. data/lib/rspec/matchers.rb +7 -102
  43. data/lib/rspec/matchers/built_in/base_matcher.rb +10 -17
  44. data/lib/rspec/matchers/built_in/be.rb +5 -18
  45. data/lib/rspec/matchers/built_in/be_within.rb +2 -8
  46. data/lib/rspec/matchers/built_in/change.rb +1 -39
  47. data/lib/rspec/matchers/built_in/has.rb +7 -40
  48. data/lib/rspec/matchers/built_in/include.rb +1 -1
  49. data/lib/rspec/matchers/built_in/match_array.rb +1 -1
  50. data/lib/rspec/matchers/built_in/raise_error.rb +44 -23
  51. data/lib/rspec/matchers/built_in/respond_to.rb +1 -7
  52. data/lib/rspec/matchers/built_in/satisfy.rb +1 -7
  53. data/lib/rspec/matchers/built_in/throw_symbol.rb +2 -10
  54. data/lib/rspec/matchers/built_in/yield.rb +4 -25
  55. data/lib/rspec/matchers/compatibility.rb +2 -2
  56. data/lib/rspec/{expectations → matchers}/configuration.rb +9 -6
  57. data/lib/rspec/matchers/dsl.rb +2 -4
  58. data/lib/rspec/matchers/matcher.rb +163 -283
  59. data/lib/rspec/matchers/operator_matcher.rb +57 -71
  60. data/lib/rspec/matchers/pretty.rb +0 -4
  61. data/lib/rspec/matchers/test_unit_integration.rb +5 -22
  62. data/spec/rspec/expectations/expectation_target_spec.rb +0 -62
  63. data/spec/rspec/expectations/extensions/kernel_spec.rb +0 -4
  64. data/spec/rspec/expectations_spec.rb +2 -43
  65. data/spec/rspec/matchers/base_matcher_spec.rb +12 -27
  66. data/spec/rspec/matchers/be_spec.rb +2 -71
  67. data/spec/rspec/matchers/change_spec.rb +1 -76
  68. data/spec/rspec/{expectations → matchers}/configuration_spec.rb +41 -21
  69. data/spec/rspec/matchers/description_generation_spec.rb +2 -21
  70. data/spec/rspec/matchers/equal_spec.rb +0 -26
  71. data/spec/rspec/matchers/has_spec.rb +0 -24
  72. data/spec/rspec/matchers/match_array_spec.rb +0 -13
  73. data/spec/rspec/matchers/matcher_spec.rb +325 -279
  74. data/spec/rspec/matchers/matchers_spec.rb +36 -0
  75. data/spec/rspec/matchers/operator_matcher_spec.rb +8 -27
  76. data/spec/rspec/matchers/raise_error_spec.rb +65 -209
  77. data/spec/rspec/matchers/yield_spec.rb +32 -9
  78. data/spec/spec_helper.rb +21 -6
  79. data/spec/support/classes.rb +7 -7
  80. data/spec/support/in_sub_process.rb +7 -8
  81. data/spec/support/shared_examples.rb +0 -42
  82. metadata +113 -84
  83. metadata.gz.sig +4 -0
  84. data/features/built_in_matchers/have.feature +0 -109
  85. data/features/built_in_matchers/operators.feature +0 -227
  86. data/lib/rspec/expectations/caller_filter.rb +0 -60
  87. data/lib/rspec/expectations/deprecation.rb +0 -27
  88. data/lib/rspec/expectations/extensions/array.rb +0 -9
  89. data/lib/rspec/matchers/be_close.rb +0 -12
  90. data/lib/rspec/matchers/built_in/have.rb +0 -273
  91. data/lib/rspec/matchers/differentiate_block_method_types.rb +0 -55
  92. data/lib/rspec/matchers/extensions/instance_eval_with_args.rb +0 -39
  93. data/lib/rspec/matchers/match_aliases.rb +0 -22
  94. data/spec/rspec/matchers/be_close_spec.rb +0 -25
  95. data/spec/rspec/matchers/differentiate_block_method_types_spec.rb +0 -39
  96. data/spec/rspec/matchers/have_spec.rb +0 -853
  97. data/spec/rspec/matchers/pretty_spec.rb +0 -23
  98. data/spec/support/helper_methods.rb +0 -42
@@ -13,14 +13,11 @@ module RSpec
13
13
  # class. If/when this changes, we will announce it and remove this warning.
14
14
  class BaseMatcher
15
15
  include RSpec::Matchers::Pretty
16
- include RSpec::Matchers::MatchAliases
17
-
18
- UNDEFINED = Object.new.freeze
19
16
 
20
17
  attr_reader :actual, :expected, :rescued_exception
21
18
 
22
- def initialize(expected = UNDEFINED)
23
- @expected = expected unless UNDEFINED.equal?(expected)
19
+ def initialize(expected = nil)
20
+ @expected = expected
24
21
  end
25
22
 
26
23
  def matches?(actual)
@@ -39,32 +36,28 @@ module RSpec
39
36
  end
40
37
 
41
38
  def failure_message_for_should
42
- assert_ivars :@actual
43
- "expected #{@actual.inspect} to #{name_to_sentence}#{to_sentence expected}"
39
+ assert_ivars :@actual, :@expected
40
+ "expected #{@actual.inspect} to #{name_to_sentence}#{expected_to_sentence}"
44
41
  end
45
42
 
46
43
  def failure_message_for_should_not
47
- assert_ivars :@actual
48
- "expected #{@actual.inspect} not to #{name_to_sentence}#{to_sentence expected}"
44
+ assert_ivars :@actual, :@expected
45
+ "expected #{@actual.inspect} not to #{name_to_sentence}#{expected_to_sentence}"
49
46
  end
50
47
 
51
48
  def description
52
- defined?(@expected) ? "#{name_to_sentence} #{@expected.inspect}" : name_to_sentence
49
+ expected ? "#{name_to_sentence} #{@expected.inspect}" : name_to_sentence
53
50
  end
54
51
 
55
52
  def diffable?
56
53
  false
57
54
  end
58
55
 
59
- # @api private
60
- # Most matchers are value matchers (i.e. meant to work with `expect(value)`)
61
- # rather than block matchers (i.e. meant to work with `expect { }`), so
62
- # this defaults to false. Block matchers must override this to return true.
63
- def supports_block_expectations?
64
- false
56
+ def ==(other)
57
+ matches?(other)
65
58
  end
66
59
 
67
- private
60
+ private
68
61
 
69
62
  def assert_ivars *ivars
70
63
  raise "#{self.class.name} needs to supply #{to_sentence ivars}" unless ivars.all? { |v| instance_variables.map(&:intern).include? v }
@@ -143,23 +143,17 @@ it is a bit confusing.
143
143
  @actual = actual
144
144
 
145
145
  if is_private_on?( @actual )
146
- RSpec.deprecate "matching with be_#{predicate.to_s.gsub(/\?$/,'')} on private method #{predicate}",
147
- :replacement => "`expect(object.send(#{predicate.inspect})).to be_true` or change the method's visibility to public",
148
- :call_site => caller(0)[3]
146
+ raise Expectations::ExpectationNotMetError.new("expectation set on private method `#{predicate}`")
149
147
  end
150
148
 
151
149
  begin
152
- @result = actual.__send__(predicate, *@args, &@block)
153
- check_respond_to(predicate)
154
- return @result
150
+ return @result = actual.__send__(predicate, *@args, &@block)
155
151
  rescue NameError => predicate_missing_error
156
152
  "this needs to be here or rcov will not count this branch even though it's executed in a code example"
157
153
  end
158
154
 
159
155
  begin
160
- @result = actual.__send__(present_tense_predicate, *@args, &@block)
161
- check_respond_to(present_tense_predicate)
162
- return @result
156
+ return @result = actual.__send__(present_tense_predicate, *@args, &@block)
163
157
  rescue NameError
164
158
  raise predicate_missing_error
165
159
  end
@@ -179,10 +173,10 @@ it is a bit confusing.
179
173
  "#{prefix_to_sentence}#{expected_to_sentence}#{args_to_sentence}"
180
174
  end
181
175
 
182
- private
176
+ private
183
177
 
184
178
  # support 1.8.7
185
- if String === methods.first
179
+ if methods.first.is_a? String
186
180
  def is_private_on? actual
187
181
  actual.private_methods.include? predicate.to_s
188
182
  end
@@ -213,13 +207,6 @@ it is a bit confusing.
213
207
  def prefix_to_sentence
214
208
  split_words(@prefix)
215
209
  end
216
-
217
- def check_respond_to(method)
218
- RSpec.deprecate(
219
- "Matching with #{@prefix}#{@expected} on an object that doesn't respond to `#{method}`",
220
- :replacement => "`respond_to_missing?` or `respond_to?` on your object"
221
- ) unless actual.respond_to?(method)
222
- end
223
210
  end
224
211
  end
225
212
  end
@@ -2,8 +2,6 @@ module RSpec
2
2
  module Matchers
3
3
  module BuiltIn
4
4
  class BeWithin
5
- include MatchAliases
6
-
7
5
  def initialize(delta)
8
6
  @delta = delta
9
7
  end
@@ -14,6 +12,7 @@ module RSpec
14
12
  raise needs_subtractable unless @actual.respond_to? :-
15
13
  (@actual - @expected).abs <= @tolerance
16
14
  end
15
+ alias == matches?
17
16
 
18
17
  def of(expected)
19
18
  @expected = expected
@@ -41,12 +40,7 @@ module RSpec
41
40
  "be within #{@delta}#{@unit} of #{@expected}"
42
41
  end
43
42
 
44
- # @private
45
- def supports_block_expectations?
46
- false
47
- end
48
-
49
- private
43
+ private
50
44
 
51
45
  def needs_subtractable
52
46
  ArgumentError.new "The actual value (#{@actual.inspect}) must respond to `-`"
@@ -2,8 +2,6 @@ module RSpec
2
2
  module Matchers
3
3
  module BuiltIn
4
4
  class Change
5
- include MatchAliases
6
-
7
5
  def initialize(receiver=nil, message=nil, &block)
8
6
  @message = message
9
7
  @value_proc = block || lambda {receiver.__send__(message)}
@@ -20,39 +18,7 @@ module RSpec
20
18
 
21
19
  (!change_expected? || changed?) && matches_before? && matches_after? && matches_expected_delta? && matches_min? && matches_max?
22
20
  end
23
-
24
- def does_not_match?(event_proc, &block)
25
- expression = if @expected_delta
26
- "by()"
27
- elsif @minimum
28
- "by_at_least()"
29
- elsif @maximum
30
- "by_at_most()"
31
- elsif @eval_after
32
- "to()"
33
- end
34
-
35
- if expression
36
- RSpec.deprecate("`expect { }.not_to change { }.#{expression}`")
37
- end
38
-
39
- matched_positively = matches?(event_proc, &block)
40
-
41
- unless matches_before?
42
- RSpec.warn_deprecation(<<-EOS.gsub(/^\s+\|/, ''))
43
- |The semantics of `expect { }.not_to change { }.from()` are changing
44
- |in RSpec 3. In RSpec 2.x, this would pass if the value changed but
45
- |the starting value was not what you specified with `from()`. In
46
- |RSpec 3, this will only pass if the starting value matches your
47
- |`from()` value _and_ it has not changed.
48
- |
49
- |You have an expectation that relies upon the old RSpec 2.x semantics
50
- |at: #{CallerFilter.first_non_rspec_line}"
51
- EOS
52
- end
53
-
54
- !matched_positively
55
- end
21
+ alias == matches?
56
22
 
57
23
  def raise_block_syntax_error
58
24
  raise SyntaxError.new(<<-MESSAGE)
@@ -124,10 +90,6 @@ MESSAGE
124
90
  "change ##{message}"
125
91
  end
126
92
 
127
- def supports_block_expectations?
128
- true
129
- end
130
-
131
93
  private
132
94
 
133
95
  def failure_message_for_expected_after
@@ -2,57 +2,31 @@ module RSpec
2
2
  module Matchers
3
3
  module BuiltIn
4
4
  class Has
5
- include MatchAliases
6
-
7
5
  def initialize(expected, *args)
8
6
  @expected, @args = expected, args
9
7
  end
10
8
 
11
9
  def matches?(actual)
12
- method = predicate
13
-
14
- if is_private_on?(actual)
15
- RSpec.deprecate "matching with #{@expected} on private method #{predicate}",
16
- :replacement => "`expect(object.send(#{predicate.inspect})).to be_true` or change the method's visibility to public"
17
- end
18
-
19
- result = actual.__send__(method, *@args)
20
- check_respond_to(actual, method)
21
- result
10
+ actual.__send__(predicate(@expected), *@args)
22
11
  end
12
+ alias == matches?
23
13
 
24
14
  def failure_message_for_should
25
- "expected ##{predicate}#{failure_message_args_description} to return true, got false"
15
+ "expected ##{predicate(@expected)}#{failure_message_args_description} to return true, got false"
26
16
  end
27
17
 
28
18
  def failure_message_for_should_not
29
- "expected ##{predicate}#{failure_message_args_description} to return false, got true"
19
+ "expected ##{predicate(@expected)}#{failure_message_args_description} to return false, got true"
30
20
  end
31
21
 
32
22
  def description
33
23
  [method_description(@expected), args_description].compact.join(' ')
34
24
  end
35
25
 
36
- # @private
37
- def supports_block_expectations?
38
- false
39
- end
40
-
41
- private
26
+ private
42
27
 
43
- # support 1.8.7
44
- if String === methods.first
45
- def is_private_on? actual
46
- actual.private_methods.include? predicate.to_s
47
- end
48
- else
49
- def is_private_on? actual
50
- actual.private_methods.include? predicate
51
- end
52
- end
53
-
54
- def predicate
55
- "#{@expected.to_s.sub("have_","has_")}?".to_sym
28
+ def predicate(sym)
29
+ "#{sym.to_s.sub("have_","has_")}?".to_sym
56
30
  end
57
31
 
58
32
  def method_description(method)
@@ -68,13 +42,6 @@ module RSpec
68
42
  desc = args_description
69
43
  "(#{desc})" if desc
70
44
  end
71
-
72
- def check_respond_to(actual, method)
73
- RSpec.deprecate(
74
- "Matching with #{@expected} on an object that doesn't respond to `#{method}`",
75
- :replacement => "`respond_to_missing?` or `respond_to?` on your object"
76
- ) unless actual.respond_to?(method)
77
- end
78
45
  end
79
46
  end
80
47
  end
@@ -17,7 +17,7 @@ module RSpec
17
17
  end
18
18
 
19
19
  def description
20
- "include#{to_sentence expected}"
20
+ "include#{expected_to_sentence}"
21
21
  end
22
22
 
23
23
  def diffable?
@@ -27,7 +27,7 @@ module RSpec
27
27
  end
28
28
 
29
29
  def description
30
- "contain exactly#{to_sentence(expected)}"
30
+ "contain exactly #{_pretty_print(expected)}"
31
31
  end
32
32
 
33
33
  private
@@ -2,8 +2,6 @@ module RSpec
2
2
  module Matchers
3
3
  module BuiltIn
4
4
  class RaiseError
5
- include MatchAliases
6
-
7
5
  def initialize(expected_error_or_message=Exception, expected_message=nil, &block)
8
6
  @block = block
9
7
  @actual_error = nil
@@ -15,29 +13,24 @@ module RSpec
15
13
  end
16
14
  end
17
15
 
18
- def matches?(given_proc, negative_expectation = false)
19
- if negative_expectation && (expecting_specific_exception? || @expected_message)
20
- what_to_deprecate = if expecting_specific_exception? && @expected_message
21
- "`expect { }.not_to raise_error(SpecificErrorClass, message)`"
22
- elsif expecting_specific_exception?
23
- "`expect { }.not_to raise_error(SpecificErrorClass)`"
24
- elsif @expected_message
25
- "`expect { }.not_to raise_error(message)`"
26
- end
16
+ def with_message(expected_message)
17
+ raise_message_already_set if @expected_message
18
+ @expected_message = expected_message
19
+ self
20
+ end
27
21
 
28
- RSpec.deprecate(
29
- what_to_deprecate,
30
- :replacement => "`expect { }.not_to raise_error` (with no args)"
31
- )
32
- end
22
+ def matches?(given_proc, negative_expectation = false, &block)
23
+ @block ||= block
33
24
  @raised_expected_error = false
34
25
  @with_expected_message = false
35
26
  @eval_block = false
36
27
  @eval_block_passed = false
28
+
37
29
  unless given_proc.respond_to?(:call)
38
30
  ::Kernel.warn "`raise_error` was called with non-proc object #{given_proc.inspect}"
39
31
  return false
40
32
  end
33
+
41
34
  begin
42
35
  given_proc.call
43
36
  rescue Exception => @actual_error
@@ -50,11 +43,26 @@ module RSpec
50
43
  unless negative_expectation
51
44
  eval_block if @raised_expected_error && @with_expected_message && @block
52
45
  end
53
- ensure
54
- return (@raised_expected_error & @with_expected_message) ? (@eval_block ? @eval_block_passed : true) : false
46
+
47
+ expectation_matched?
48
+ end
49
+
50
+ alias == matches?
51
+
52
+ def expectation_matched?
53
+ error_and_message_match? && block_matches?
54
+ end
55
+
56
+ def error_and_message_match?
57
+ @raised_expected_error && @with_expected_message
58
+ end
59
+
60
+ def block_matches?
61
+ @eval_block ? @eval_block_passed : true
55
62
  end
56
63
 
57
64
  def does_not_match?(given_proc)
65
+ prevent_invalid_expectations
58
66
  !matches?(given_proc, :negative_expectation)
59
67
  end
60
68
 
@@ -91,13 +99,22 @@ module RSpec
91
99
  "raise #{expected_error}"
92
100
  end
93
101
 
94
- # @private
95
- def supports_block_expectations?
96
- true
97
- end
98
-
99
102
  private
100
103
 
104
+ def prevent_invalid_expectations
105
+ if (expecting_specific_exception? || @expected_message)
106
+ what_to_raise = if expecting_specific_exception? && @expected_message
107
+ "`expect { }.not_to raise_error(SpecificErrorClass, message)`"
108
+ elsif expecting_specific_exception?
109
+ "`expect { }.not_to raise_error(SpecificErrorClass)`"
110
+ elsif @expected_message
111
+ "`expect { }.not_to raise_error(message)`"
112
+ end
113
+ specific_class_error = ArgumentError.new("#{what_to_raise} is not valid, use `expect { }.not_to raise_error` (with no args) instead")
114
+ raise specific_class_error
115
+ end
116
+ end
117
+
101
118
  def expected_error
102
119
  case @expected_message
103
120
  when nil
@@ -127,6 +144,10 @@ module RSpec
127
144
  def expecting_specific_exception?
128
145
  @expected_error != Exception
129
146
  end
147
+
148
+ def raise_message_already_set
149
+ raise "`expect { }.to raise_error(message).with_message(message)` is not valid. The matcher only allows the expected message to be specified once"
150
+ end
130
151
  end
131
152
  end
132
153
  end
@@ -2,8 +2,6 @@ module RSpec
2
2
  module Matchers
3
3
  module BuiltIn
4
4
  class RespondTo
5
- include MatchAliases
6
-
7
5
  def initialize(*names)
8
6
  @names = names
9
7
  @expected_arity = nil
@@ -12,6 +10,7 @@ module RSpec
12
10
  def matches?(actual)
13
11
  find_failing_method_names(actual, :reject).empty?
14
12
  end
13
+ alias == matches?
15
14
 
16
15
  def does_not_match?(actual)
17
16
  find_failing_method_names(actual, :select).empty?
@@ -39,11 +38,6 @@ module RSpec
39
38
  end
40
39
  alias :arguments :argument
41
40
 
42
- # @private
43
- def supports_block_expectations?
44
- false
45
- end
46
-
47
41
  private
48
42
 
49
43
  def find_failing_method_names(actual, filter_method)
@@ -2,8 +2,6 @@ module RSpec
2
2
  module Matchers
3
3
  module BuiltIn
4
4
  class Satisfy
5
- include MatchAliases
6
-
7
5
  def initialize(&block)
8
6
  @block = block
9
7
  end
@@ -13,6 +11,7 @@ module RSpec
13
11
  @actual = actual
14
12
  @block.call(actual)
15
13
  end
14
+ alias == matches?
16
15
 
17
16
  def failure_message_for_should
18
17
  "expected #{@actual} to satisfy block"
@@ -25,11 +24,6 @@ module RSpec
25
24
  def description
26
25
  "satisfy block"
27
26
  end
28
-
29
- # @private
30
- def supports_block_expectations?
31
- false
32
- end
33
27
  end
34
28
  end
35
29
  end