rspec-expectations 2.14.0 → 3.0.0

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 (143) hide show
  1. checksums.yaml +15 -0
  2. checksums.yaml.gz.sig +0 -0
  3. data/Changelog.md +369 -25
  4. data/License.txt +1 -0
  5. data/README.md +88 -15
  6. data/lib/rspec/{matchers → expectations}/configuration.rb +44 -14
  7. data/lib/rspec/expectations/expectation_target.rb +67 -33
  8. data/lib/rspec/expectations/fail_with.rb +11 -53
  9. data/lib/rspec/expectations/handler.rb +126 -31
  10. data/lib/rspec/expectations/minitest_integration.rb +16 -0
  11. data/lib/rspec/expectations/syntax.rb +60 -94
  12. data/lib/rspec/expectations/version.rb +1 -1
  13. data/lib/rspec/expectations.rb +45 -23
  14. data/lib/rspec/matchers/aliased_matcher.rb +41 -0
  15. data/lib/rspec/matchers/built_in/all.rb +78 -0
  16. data/lib/rspec/matchers/built_in/base_matcher.rb +63 -15
  17. data/lib/rspec/matchers/built_in/be.rb +170 -81
  18. data/lib/rspec/matchers/built_in/be_between.rb +77 -0
  19. data/lib/rspec/matchers/built_in/be_instance_of.rb +11 -3
  20. data/lib/rspec/matchers/built_in/be_kind_of.rb +5 -0
  21. data/lib/rspec/matchers/built_in/be_within.rb +39 -15
  22. data/lib/rspec/matchers/built_in/change.rb +273 -80
  23. data/lib/rspec/matchers/built_in/compound.rb +122 -0
  24. data/lib/rspec/matchers/built_in/contain_exactly.rb +256 -0
  25. data/lib/rspec/matchers/built_in/cover.rb +3 -0
  26. data/lib/rspec/matchers/built_in/eq.rb +60 -6
  27. data/lib/rspec/matchers/built_in/eql.rb +17 -5
  28. data/lib/rspec/matchers/built_in/equal.rb +55 -21
  29. data/lib/rspec/matchers/built_in/exist.rb +74 -10
  30. data/lib/rspec/matchers/built_in/has.rb +71 -15
  31. data/lib/rspec/matchers/built_in/include.rb +64 -27
  32. data/lib/rspec/matchers/built_in/match.rb +19 -1
  33. data/lib/rspec/matchers/built_in/operators.rb +119 -0
  34. data/lib/rspec/matchers/built_in/output.rb +150 -0
  35. data/lib/rspec/matchers/built_in/raise_error.rb +84 -42
  36. data/lib/rspec/matchers/built_in/respond_to.rb +42 -20
  37. data/lib/rspec/matchers/built_in/satisfy.rb +19 -3
  38. data/lib/rspec/matchers/built_in/start_and_end_with.rb +54 -18
  39. data/lib/rspec/matchers/built_in/throw_symbol.rb +38 -8
  40. data/lib/rspec/matchers/built_in/yield.rb +175 -68
  41. data/lib/rspec/matchers/built_in.rb +45 -33
  42. data/lib/rspec/matchers/composable.rb +179 -0
  43. data/lib/rspec/matchers/dsl.rb +362 -5
  44. data/lib/rspec/matchers/generated_descriptions.rb +13 -6
  45. data/lib/rspec/matchers/matcher_delegator.rb +37 -0
  46. data/lib/rspec/matchers/pretty.rb +27 -20
  47. data/lib/rspec/matchers.rb +361 -136
  48. data.tar.gz.sig +1 -0
  49. metadata +99 -215
  50. metadata.gz.sig +0 -0
  51. data/features/README.md +0 -48
  52. data/features/Upgrade.md +0 -53
  53. data/features/built_in_matchers/README.md +0 -90
  54. data/features/built_in_matchers/be.feature +0 -175
  55. data/features/built_in_matchers/be_within.feature +0 -48
  56. data/features/built_in_matchers/cover.feature +0 -47
  57. data/features/built_in_matchers/end_with.feature +0 -48
  58. data/features/built_in_matchers/equality.feature +0 -139
  59. data/features/built_in_matchers/exist.feature +0 -45
  60. data/features/built_in_matchers/expect_change.feature +0 -59
  61. data/features/built_in_matchers/expect_error.feature +0 -144
  62. data/features/built_in_matchers/have.feature +0 -109
  63. data/features/built_in_matchers/include.feature +0 -174
  64. data/features/built_in_matchers/match.feature +0 -52
  65. data/features/built_in_matchers/operators.feature +0 -227
  66. data/features/built_in_matchers/predicates.feature +0 -137
  67. data/features/built_in_matchers/respond_to.feature +0 -84
  68. data/features/built_in_matchers/satisfy.feature +0 -33
  69. data/features/built_in_matchers/start_with.feature +0 -48
  70. data/features/built_in_matchers/throw_symbol.feature +0 -91
  71. data/features/built_in_matchers/types.feature +0 -116
  72. data/features/built_in_matchers/yield.feature +0 -161
  73. data/features/custom_matchers/access_running_example.feature +0 -53
  74. data/features/custom_matchers/define_diffable_matcher.feature +0 -27
  75. data/features/custom_matchers/define_matcher.feature +0 -368
  76. data/features/custom_matchers/define_matcher_outside_rspec.feature +0 -38
  77. data/features/custom_matchers/define_matcher_with_fluent_interface.feature +0 -24
  78. data/features/customized_message.feature +0 -22
  79. data/features/diffing.feature +0 -85
  80. data/features/implicit_docstrings.feature +0 -52
  81. data/features/step_definitions/additional_cli_steps.rb +0 -22
  82. data/features/support/env.rb +0 -14
  83. data/features/syntax_configuration.feature +0 -71
  84. data/features/test_frameworks/test_unit.feature +0 -44
  85. data/lib/rspec/expectations/deprecation.rb +0 -17
  86. data/lib/rspec/expectations/differ.rb +0 -133
  87. data/lib/rspec/expectations/errors.rb +0 -9
  88. data/lib/rspec/expectations/extensions/array.rb +0 -9
  89. data/lib/rspec/expectations/extensions/object.rb +0 -29
  90. data/lib/rspec/expectations/extensions.rb +0 -2
  91. data/lib/rspec/matchers/be_close.rb +0 -9
  92. data/lib/rspec/matchers/built_in/have.rb +0 -124
  93. data/lib/rspec/matchers/built_in/match_array.rb +0 -51
  94. data/lib/rspec/matchers/compatibility.rb +0 -14
  95. data/lib/rspec/matchers/extensions/instance_eval_with_args.rb +0 -39
  96. data/lib/rspec/matchers/matcher.rb +0 -300
  97. data/lib/rspec/matchers/method_missing.rb +0 -12
  98. data/lib/rspec/matchers/operator_matcher.rb +0 -109
  99. data/lib/rspec/matchers/test_unit_integration.rb +0 -11
  100. data/lib/rspec-expectations.rb +0 -1
  101. data/spec/rspec/expectations/differ_spec.rb +0 -192
  102. data/spec/rspec/expectations/expectation_target_spec.rb +0 -82
  103. data/spec/rspec/expectations/extensions/kernel_spec.rb +0 -67
  104. data/spec/rspec/expectations/fail_with_spec.rb +0 -114
  105. data/spec/rspec/expectations/handler_spec.rb +0 -227
  106. data/spec/rspec/expectations/syntax_spec.rb +0 -139
  107. data/spec/rspec/matchers/base_matcher_spec.rb +0 -62
  108. data/spec/rspec/matchers/be_close_spec.rb +0 -22
  109. data/spec/rspec/matchers/be_instance_of_spec.rb +0 -63
  110. data/spec/rspec/matchers/be_kind_of_spec.rb +0 -41
  111. data/spec/rspec/matchers/be_spec.rb +0 -516
  112. data/spec/rspec/matchers/be_within_spec.rb +0 -137
  113. data/spec/rspec/matchers/change_spec.rb +0 -553
  114. data/spec/rspec/matchers/configuration_spec.rb +0 -206
  115. data/spec/rspec/matchers/cover_spec.rb +0 -69
  116. data/spec/rspec/matchers/description_generation_spec.rb +0 -190
  117. data/spec/rspec/matchers/dsl_spec.rb +0 -57
  118. data/spec/rspec/matchers/eq_spec.rb +0 -60
  119. data/spec/rspec/matchers/eql_spec.rb +0 -41
  120. data/spec/rspec/matchers/equal_spec.rb +0 -78
  121. data/spec/rspec/matchers/exist_spec.rb +0 -124
  122. data/spec/rspec/matchers/has_spec.rb +0 -122
  123. data/spec/rspec/matchers/have_spec.rb +0 -455
  124. data/spec/rspec/matchers/include_matcher_integration_spec.rb +0 -30
  125. data/spec/rspec/matchers/include_spec.rb +0 -531
  126. data/spec/rspec/matchers/match_array_spec.rb +0 -194
  127. data/spec/rspec/matchers/match_spec.rb +0 -61
  128. data/spec/rspec/matchers/matcher_spec.rb +0 -471
  129. data/spec/rspec/matchers/matchers_spec.rb +0 -37
  130. data/spec/rspec/matchers/method_missing_spec.rb +0 -28
  131. data/spec/rspec/matchers/operator_matcher_spec.rb +0 -223
  132. data/spec/rspec/matchers/raise_error_spec.rb +0 -485
  133. data/spec/rspec/matchers/respond_to_spec.rb +0 -292
  134. data/spec/rspec/matchers/satisfy_spec.rb +0 -44
  135. data/spec/rspec/matchers/start_with_end_with_spec.rb +0 -186
  136. data/spec/rspec/matchers/throw_symbol_spec.rb +0 -116
  137. data/spec/rspec/matchers/yield_spec.rb +0 -514
  138. data/spec/spec_helper.rb +0 -54
  139. data/spec/support/classes.rb +0 -56
  140. data/spec/support/in_sub_process.rb +0 -38
  141. data/spec/support/matchers.rb +0 -22
  142. data/spec/support/ruby_version.rb +0 -10
  143. data/spec/support/shared_examples.rb +0 -13
@@ -1,7 +1,12 @@
1
1
  module RSpec
2
2
  module Matchers
3
3
  module BuiltIn
4
+ # @api private
5
+ # Provides the implementation for `raise_error`.
6
+ # Not intended to be instantiated directly.
4
7
  class RaiseError
8
+ include Composable
9
+
5
10
  def initialize(expected_error_or_message=Exception, expected_message=nil, &block)
6
11
  @block = block
7
12
  @actual_error = nil
@@ -13,29 +18,29 @@ module RSpec
13
18
  end
14
19
  end
15
20
 
16
- def matches?(given_proc, negative_expectation = false)
17
- if negative_expectation && (expecting_specific_exception? || @expected_message)
18
- what_to_deprecate = if expecting_specific_exception? && @expected_message
19
- "`expect { }.not_to raise_error(SpecificErrorClass, message)`"
20
- elsif expecting_specific_exception?
21
- "`expect { }.not_to raise_error(SpecificErrorClass)`"
22
- elsif @expected_message
23
- "`expect { }.not_to raise_error(message)`"
24
- end
25
- RSpec.deprecate(what_to_deprecate, :replacement => "`expect { }.not_to raise_error()`")
26
- end
21
+ # @api public
22
+ # Specifies the expected error message.
23
+ def with_message(expected_message)
24
+ raise_message_already_set if @expected_message
25
+ @expected_message = expected_message
26
+ self
27
+ end
28
+
29
+ # @private
30
+ def matches?(given_proc, negative_expectation = false, &block)
31
+ @given_proc = given_proc
32
+ @block ||= block
27
33
  @raised_expected_error = false
28
34
  @with_expected_message = false
29
35
  @eval_block = false
30
36
  @eval_block_passed = false
31
- unless given_proc.respond_to?(:call)
32
- ::Kernel.warn "`raise_error` was called with non-proc object #{given_proc.inspect}"
33
- return false
34
- end
37
+
38
+ return false unless Proc === given_proc
39
+
35
40
  begin
36
41
  given_proc.call
37
42
  rescue Exception => @actual_error
38
- if @actual_error == @expected_error || @expected_error === @actual_error
43
+ if values_match?(@expected_error, @actual_error)
39
44
  @raised_expected_error = true
40
45
  @with_expected_message = verify_message
41
46
  end
@@ -44,13 +49,51 @@ module RSpec
44
49
  unless negative_expectation
45
50
  eval_block if @raised_expected_error && @with_expected_message && @block
46
51
  end
47
- ensure
48
- return (@raised_expected_error & @with_expected_message) ? (@eval_block ? @eval_block_passed : true) : false
52
+
53
+ expectation_matched?
49
54
  end
50
- alias == matches?
51
55
 
56
+ # @private
52
57
  def does_not_match?(given_proc)
53
- !matches?(given_proc, :negative_expectation)
58
+ prevent_invalid_expectations
59
+ !matches?(given_proc, :negative_expectation) && Proc === given_proc
60
+ end
61
+
62
+ # @private
63
+ def supports_block_expectations?
64
+ true
65
+ end
66
+
67
+ # @api private
68
+ # @return [String]
69
+ def failure_message
70
+ @eval_block ? @actual_error.message : "expected #{expected_error}#{given_error}"
71
+ end
72
+
73
+ # @api private
74
+ # @return [String]
75
+ def failure_message_when_negated
76
+ "expected no #{expected_error}#{given_error}"
77
+ end
78
+
79
+ # @api private
80
+ # @return [String]
81
+ def description
82
+ "raise #{expected_error}"
83
+ end
84
+
85
+ private
86
+
87
+ def expectation_matched?
88
+ error_and_message_match? && block_matches?
89
+ end
90
+
91
+ def error_and_message_match?
92
+ @raised_expected_error && @with_expected_message
93
+ end
94
+
95
+ def block_matches?
96
+ @eval_block ? @eval_block_passed : true
54
97
  end
55
98
 
56
99
  def eval_block
@@ -64,38 +107,32 @@ module RSpec
64
107
  end
65
108
 
66
109
  def verify_message
67
- case @expected_message
68
- when nil
69
- true
70
- when Regexp
71
- @expected_message =~ @actual_error.message
72
- else
73
- @expected_message == @actual_error.message
74
- end
75
- end
76
-
77
- def failure_message_for_should
78
- @eval_block ? @actual_error.message : "expected #{expected_error}#{given_error}"
79
- end
80
-
81
- def failure_message_for_should_not
82
- "expected no #{expected_error}#{given_error}"
110
+ return true if @expected_message.nil?
111
+ values_match?(@expected_message, @actual_error.message)
83
112
  end
84
113
 
85
- def description
86
- "raise #{expected_error}"
114
+ def prevent_invalid_expectations
115
+ if (expecting_specific_exception? || @expected_message)
116
+ what_to_raise = if expecting_specific_exception? && @expected_message
117
+ "`expect { }.not_to raise_error(SpecificErrorClass, message)`"
118
+ elsif expecting_specific_exception?
119
+ "`expect { }.not_to raise_error(SpecificErrorClass)`"
120
+ elsif @expected_message
121
+ "`expect { }.not_to raise_error(message)`"
122
+ end
123
+ specific_class_error = ArgumentError.new("#{what_to_raise} is not valid, use `expect { }.not_to raise_error` (with no args) instead")
124
+ raise specific_class_error
125
+ end
87
126
  end
88
127
 
89
- private
90
-
91
128
  def expected_error
92
129
  case @expected_message
93
130
  when nil
94
- @expected_error.inspect
131
+ description_of(@expected_error)
95
132
  when Regexp
96
133
  "#{@expected_error} with message matching #{@expected_message.inspect}"
97
134
  else
98
- "#{@expected_error} with #{@expected_message.inspect}"
135
+ "#{@expected_error} with #{description_of @expected_message}"
99
136
  end
100
137
  end
101
138
 
@@ -105,6 +142,7 @@ module RSpec
105
142
  end
106
143
 
107
144
  def given_error
145
+ return " but was not given a block" unless Proc === @given_proc
108
146
  return " but nothing was raised" unless @actual_error
109
147
 
110
148
  backtrace = format_backtrace(@actual_error.backtrace)
@@ -117,6 +155,10 @@ module RSpec
117
155
  def expecting_specific_exception?
118
156
  @expected_error != Exception
119
157
  end
158
+
159
+ def raise_message_already_set
160
+ raise "`expect { }.to raise_error(message).with_message(message)` is not valid. The matcher only allows the expected message to be specified once"
161
+ end
120
162
  end
121
163
  end
122
164
  end
@@ -1,44 +1,71 @@
1
1
  module RSpec
2
2
  module Matchers
3
3
  module BuiltIn
4
+ # @api private
5
+ # Provides the implementation for `respond_to`.
6
+ # Not intended to be instantiated directly.
4
7
  class RespondTo
8
+ include Composable
9
+
5
10
  def initialize(*names)
6
11
  @names = names
7
12
  @expected_arity = nil
8
13
  end
9
14
 
15
+ # @api public
16
+ # Specifies the number of expected arguments.
17
+ #
18
+ # @example
19
+ # expect(obj).to respond_to(:message).with(3).arguments
20
+ def with(n)
21
+ @expected_arity = n
22
+ self
23
+ end
24
+
25
+ # @api public
26
+ # No-op. Intended to be used as syntactic sugar when using `with`.
27
+ #
28
+ # @example
29
+ # expect(obj).to respond_to(:message).with(3).arguments
30
+ def argument
31
+ self
32
+ end
33
+ alias :arguments :argument
34
+
35
+ # @private
10
36
  def matches?(actual)
11
37
  find_failing_method_names(actual, :reject).empty?
12
38
  end
13
- alias == matches?
14
39
 
40
+ # @private
15
41
  def does_not_match?(actual)
16
42
  find_failing_method_names(actual, :select).empty?
17
43
  end
18
44
 
19
- def failure_message_for_should
45
+ # @api private
46
+ # @return [String]
47
+ def failure_message
20
48
  "expected #{@actual.inspect} to respond to #{@failing_method_names.collect {|name| name.inspect }.join(', ')}#{with_arity}"
21
49
  end
22
50
 
23
- def failure_message_for_should_not
24
- failure_message_for_should.sub(/to respond to/, 'not to respond to')
51
+ # @api private
52
+ # @return [String]
53
+ def failure_message_when_negated
54
+ failure_message.sub(/to respond to/, 'not to respond to')
25
55
  end
26
56
 
57
+ # @api private
58
+ # @return [String]
27
59
  def description
28
60
  "respond to #{pp_names}#{with_arity}"
29
61
  end
30
62
 
31
- def with(n)
32
- @expected_arity = n
33
- self
34
- end
35
-
36
- def argument
37
- self
63
+ # @private
64
+ def supports_block_expectations?
65
+ false
38
66
  end
39
- alias :arguments :argument
40
67
 
41
- private
68
+ private
42
69
 
43
70
  def find_failing_method_names(actual, filter_method)
44
71
  @actual = actual
@@ -50,13 +77,8 @@ module RSpec
50
77
  def matches_arity?(actual, name)
51
78
  return true unless @expected_arity
52
79
 
53
- actual_arity = actual.method(name).arity
54
- if actual_arity < 0
55
- # ~ inverts the one's complement and gives us the number of required args
56
- ~actual_arity <= @expected_arity
57
- else
58
- actual_arity == @expected_arity
59
- end
80
+ signature = Support::MethodSignature.new(actual.method(name))
81
+ Support::MethodSignatureVerifier.new(signature, Array.new(@expected_arity)).valid?
60
82
  end
61
83
 
62
84
  def with_arity
@@ -1,29 +1,45 @@
1
1
  module RSpec
2
2
  module Matchers
3
3
  module BuiltIn
4
+ # @api private
5
+ # Provides the implementation for `satisfy`.
6
+ # Not intended to be instantiated directly.
4
7
  class Satisfy
8
+ include Composable
9
+
5
10
  def initialize(&block)
6
11
  @block = block
7
12
  end
8
13
 
14
+ # @private
9
15
  def matches?(actual, &block)
10
16
  @block = block if block
11
17
  @actual = actual
12
18
  @block.call(actual)
13
19
  end
14
- alias == matches?
15
20
 
16
- def failure_message_for_should
21
+ # @api private
22
+ # @return [String]
23
+ def failure_message
17
24
  "expected #{@actual} to satisfy block"
18
25
  end
19
26
 
20
- def failure_message_for_should_not
27
+ # @api private
28
+ # @return [String]
29
+ def failure_message_when_negated
21
30
  "expected #{@actual} not to satisfy block"
22
31
  end
23
32
 
33
+ # @api private
34
+ # @return [String]
24
35
  def description
25
36
  "satisfy block"
26
37
  end
38
+
39
+ # @private
40
+ def supports_block_expectations?
41
+ false
42
+ end
27
43
  end
28
44
  end
29
45
  end
@@ -1,46 +1,82 @@
1
1
  module RSpec
2
2
  module Matchers
3
3
  module BuiltIn
4
+ # @api private
5
+ # Base class for the `end_with` and `start_with` matchers.
6
+ # Not intended to be instantiated directly.
4
7
  class StartAndEndWith < BaseMatcher
5
8
  def initialize(*expected)
9
+ @actual_does_not_have_ordered_elements = false
6
10
  @expected = expected.length == 1 ? expected.first : expected
7
11
  end
8
12
 
9
- def matches?(actual)
10
- @actual = actual.respond_to?(:[]) ? actual : (raise ArgumentError.new("#{actual.inspect} does not respond to :[]"))
11
- begin
12
- @expected.respond_to?(:length) ? subset_matches?(@expected, @actual) : element_matches?(@expected, @actual)
13
- rescue ArgumentError
14
- raise ArgumentError.new("#{actual.inspect} does not have ordered elements")
13
+ # @api private
14
+ # @return [String]
15
+ def failure_message
16
+ super.tap do |msg|
17
+ if @actual_does_not_have_ordered_elements
18
+ msg << ", but it does not have ordered elements"
19
+ elsif !actual.respond_to?(:[])
20
+ msg << ", but it cannot be indexed using #[]"
21
+ end
15
22
  end
16
23
  end
17
24
 
18
- def failure_message_for_should
19
- "expected #{@actual.inspect} to #{self.class.name.split('::').last.sub(/With/,'').downcase} with #{@expected.inspect}"
25
+ # @api private
26
+ # @return [String]
27
+ def description
28
+ return super unless Hash === expected
29
+ "#{name_to_sentence} #{surface_descriptions_in(expected).inspect}"
20
30
  end
21
31
 
22
- def failure_message_for_should_not
23
- "expected #{@actual.inspect} not to #{self.class.name.split('::').last.sub(/With/,'').downcase} with #{@expected.inspect}"
32
+ private
33
+
34
+ def match(expected, actual)
35
+ return false unless actual.respond_to?(:[])
36
+
37
+ begin
38
+ return subset_matches? if expected.respond_to?(:length)
39
+ element_matches?
40
+ rescue ArgumentError
41
+ @actual_does_not_have_ordered_elements = true
42
+ return false
43
+ end
44
+ end
45
+
46
+ def actual_is_unordered
47
+ ArgumentError.new("#{actual.inspect} does not have ordered elements")
24
48
  end
25
49
  end
26
50
 
51
+ # @api private
52
+ # Provides the implementation for `start_with`.
53
+ # Not intended to be instantiated directly.
27
54
  class StartWith < StartAndEndWith
28
- def subset_matches?(expected, actual)
29
- actual[0, expected.length] == expected
55
+
56
+ private
57
+
58
+ def subset_matches?
59
+ values_match?(expected, actual[0, expected.length])
30
60
  end
31
61
 
32
- def element_matches?(expected, actual)
33
- @actual[0] == @expected
62
+ def element_matches?
63
+ values_match?(expected, actual[0])
34
64
  end
35
65
  end
36
66
 
67
+ # @api private
68
+ # Provides the implementation for `end_with`.
69
+ # Not intended to be instantiated directly.
37
70
  class EndWith < StartAndEndWith
38
- def subset_matches?(expected, actual)
39
- actual[-expected.length, expected.length] == expected
71
+
72
+ private
73
+
74
+ def subset_matches?
75
+ values_match?(expected, actual[-expected.length, expected.length])
40
76
  end
41
77
 
42
- def element_matches?(expected, actual)
43
- actual[-1] == expected
78
+ def element_matches?
79
+ values_match?(expected, actual[-1])
44
80
  end
45
81
  end
46
82
  end
@@ -1,14 +1,23 @@
1
1
  module RSpec
2
2
  module Matchers
3
3
  module BuiltIn
4
+ # @api private
5
+ # Provides the implementation for `throw_symbol`.
6
+ # Not intended to be instantiated directly.
4
7
  class ThrowSymbol
8
+ include Composable
9
+
5
10
  def initialize(expected_symbol = nil, expected_arg=nil)
6
11
  @expected_symbol = expected_symbol
7
12
  @expected_arg = expected_arg
8
13
  @caught_symbol = @caught_arg = nil
9
14
  end
10
15
 
16
+ # @private
11
17
  def matches?(given_proc)
18
+ @block = given_proc
19
+ return false unless Proc === given_proc
20
+
12
21
  begin
13
22
  if @expected_symbol.nil?
14
23
  given_proc.call
@@ -45,27 +54,48 @@ module RSpec
45
54
  if @expected_arg.nil?
46
55
  return @caught_symbol == @expected_symbol
47
56
  else
48
- return (@caught_symbol == @expected_symbol) & (@caught_arg == @expected_arg)
57
+ return (@caught_symbol == @expected_symbol) && values_match?(@expected_arg, @caught_arg)
49
58
  end
50
59
  end
51
60
  end
52
61
  end
53
62
  end
54
- alias == matches?
55
63
 
56
- def failure_message_for_should
57
- "expected #{expected} to be thrown, got #{caught}"
64
+ def does_not_match?(given_proc)
65
+ !matches?(given_proc) && Proc === given_proc
66
+ end
67
+
68
+ # @api private
69
+ # @return [String]
70
+ def failure_message
71
+ "expected #{expected} to be thrown, #{actual_result}"
58
72
  end
59
73
 
60
- def failure_message_for_should_not
61
- "expected #{expected('no Symbol')}#{' not' if @expected_symbol} to be thrown, got #{caught}"
74
+ # @api private
75
+ # @return [String]
76
+ def failure_message_when_negated
77
+ "expected #{expected('no Symbol')}#{' not' if @expected_symbol} to be thrown, #{actual_result}"
62
78
  end
63
79
 
80
+ # @api private
81
+ # @return [String]
64
82
  def description
65
83
  "throw #{expected}"
66
84
  end
67
85
 
68
- private
86
+ # @api private
87
+ # Indicates this matcher matches against a block.
88
+ # @return [True]
89
+ def supports_block_expectations?
90
+ true
91
+ end
92
+
93
+ private
94
+
95
+ def actual_result
96
+ return "but was not a block" unless Proc === @block
97
+ "got #{caught}"
98
+ end
69
99
 
70
100
  def expected(symbol_desc = 'a Symbol')
71
101
  throw_description(@expected_symbol || symbol_desc, @expected_arg)
@@ -79,7 +109,7 @@ module RSpec
79
109
  symbol_description = symbol.is_a?(String) ? symbol : symbol.inspect
80
110
 
81
111
  arg_description = if arg
82
- " with #{arg.inspect}"
112
+ " with #{description_of arg}"
83
113
  elsif @expected_arg && @caught_symbol == @expected_symbol
84
114
  " with no argument"
85
115
  else