rspec-expectations 2.13.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 (142) hide show
  1. checksums.yaml +15 -0
  2. checksums.yaml.gz.sig +0 -0
  3. data/Changelog.md +413 -23
  4. data/License.txt +1 -0
  5. data/README.md +109 -80
  6. data/lib/rspec/{matchers → expectations}/configuration.rb +44 -14
  7. data/lib/rspec/expectations/expectation_target.rb +71 -38
  8. data/lib/rspec/expectations/fail_with.rb +12 -44
  9. data/lib/rspec/expectations/handler.rb +135 -35
  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 +46 -24
  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 -79
  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 +40 -16
  22. data/lib/rspec/matchers/built_in/change.rb +275 -74
  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 +58 -29
  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 +91 -33
  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 +237 -55
  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 +33 -20
  47. data/lib/rspec/matchers.rb +450 -227
  48. data.tar.gz.sig +1 -0
  49. metadata +100 -215
  50. metadata.gz.sig +0 -0
  51. data/features/README.md +0 -49
  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 -146
  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 -5
  83. data/features/syntax_configuration.feature +0 -68
  84. data/features/test_frameworks/test_unit.feature +0 -46
  85. data/lib/rspec/expectations/deprecation.rb +0 -38
  86. data/lib/rspec/expectations/differ.rb +0 -115
  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 -39
  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 -108
  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-expectations.rb +0 -1
  100. data/spec/rspec/expectations/differ_spec.rb +0 -170
  101. data/spec/rspec/expectations/expectation_target_spec.rb +0 -75
  102. data/spec/rspec/expectations/extensions/kernel_spec.rb +0 -67
  103. data/spec/rspec/expectations/fail_with_spec.rb +0 -95
  104. data/spec/rspec/expectations/handler_spec.rb +0 -206
  105. data/spec/rspec/expectations/syntax_spec.rb +0 -97
  106. data/spec/rspec/matchers/base_matcher_spec.rb +0 -62
  107. data/spec/rspec/matchers/be_close_spec.rb +0 -22
  108. data/spec/rspec/matchers/be_instance_of_spec.rb +0 -63
  109. data/spec/rspec/matchers/be_kind_of_spec.rb +0 -41
  110. data/spec/rspec/matchers/be_spec.rb +0 -516
  111. data/spec/rspec/matchers/be_within_spec.rb +0 -129
  112. data/spec/rspec/matchers/change_spec.rb +0 -542
  113. data/spec/rspec/matchers/configuration_spec.rb +0 -238
  114. data/spec/rspec/matchers/cover_spec.rb +0 -69
  115. data/spec/rspec/matchers/description_generation_spec.rb +0 -176
  116. data/spec/rspec/matchers/dsl_spec.rb +0 -57
  117. data/spec/rspec/matchers/eq_spec.rb +0 -60
  118. data/spec/rspec/matchers/eql_spec.rb +0 -41
  119. data/spec/rspec/matchers/equal_spec.rb +0 -78
  120. data/spec/rspec/matchers/exist_spec.rb +0 -124
  121. data/spec/rspec/matchers/has_spec.rb +0 -122
  122. data/spec/rspec/matchers/have_spec.rb +0 -445
  123. data/spec/rspec/matchers/include_matcher_integration_spec.rb +0 -30
  124. data/spec/rspec/matchers/include_spec.rb +0 -531
  125. data/spec/rspec/matchers/match_array_spec.rb +0 -194
  126. data/spec/rspec/matchers/match_spec.rb +0 -61
  127. data/spec/rspec/matchers/matcher_spec.rb +0 -471
  128. data/spec/rspec/matchers/matchers_spec.rb +0 -37
  129. data/spec/rspec/matchers/method_missing_spec.rb +0 -28
  130. data/spec/rspec/matchers/operator_matcher_spec.rb +0 -223
  131. data/spec/rspec/matchers/raise_error_spec.rb +0 -395
  132. data/spec/rspec/matchers/respond_to_spec.rb +0 -292
  133. data/spec/rspec/matchers/satisfy_spec.rb +0 -44
  134. data/spec/rspec/matchers/start_with_end_with_spec.rb +0 -186
  135. data/spec/rspec/matchers/throw_symbol_spec.rb +0 -116
  136. data/spec/rspec/matchers/yield_spec.rb +0 -437
  137. data/spec/spec_helper.rb +0 -54
  138. data/spec/support/classes.rb +0 -56
  139. data/spec/support/in_sub_process.rb +0 -38
  140. data/spec/support/matchers.rb +0 -22
  141. data/spec/support/ruby_version.rb +0 -10
  142. 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,32 +18,82 @@ module RSpec
13
18
  end
14
19
  end
15
20
 
16
- def matches?(given_proc, negative_expectation = false)
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
17
33
  @raised_expected_error = false
18
34
  @with_expected_message = false
19
35
  @eval_block = false
20
36
  @eval_block_passed = false
37
+
38
+ return false unless Proc === given_proc
39
+
21
40
  begin
22
41
  given_proc.call
23
- rescue @expected_error => @actual_error
24
- @raised_expected_error = true
25
- @with_expected_message = verify_message
26
42
  rescue Exception => @actual_error
27
- # This clause should be empty, but rcov will not report it as covered
28
- # unless something (anything) is executed within the clause
29
- "http://eigenclass.org/hiki.rb?rcov-0.8.0"
43
+ if values_match?(@expected_error, @actual_error)
44
+ @raised_expected_error = true
45
+ @with_expected_message = verify_message
46
+ end
30
47
  end
31
48
 
32
49
  unless negative_expectation
33
50
  eval_block if @raised_expected_error && @with_expected_message && @block
34
51
  end
35
- ensure
36
- return (@raised_expected_error & @with_expected_message) ? (@eval_block ? @eval_block_passed : true) : false
52
+
53
+ expectation_matched?
37
54
  end
38
- alias == matches?
39
55
 
56
+ # @private
40
57
  def does_not_match?(given_proc)
41
- !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
42
97
  end
43
98
 
44
99
  def eval_block
@@ -52,38 +107,32 @@ module RSpec
52
107
  end
53
108
 
54
109
  def verify_message
55
- case @expected_message
56
- when nil
57
- true
58
- when Regexp
59
- @expected_message =~ @actual_error.message
60
- else
61
- @expected_message == @actual_error.message
62
- end
63
- end
64
-
65
- def failure_message_for_should
66
- @eval_block ? @actual_error.message : "expected #{expected_error}#{given_error}"
110
+ return true if @expected_message.nil?
111
+ values_match?(@expected_message, @actual_error.message)
67
112
  end
68
113
 
69
- def failure_message_for_should_not
70
- "expected no #{expected_error}#{given_error}"
71
- end
72
-
73
- def description
74
- "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
75
126
  end
76
127
 
77
- private
78
-
79
128
  def expected_error
80
129
  case @expected_message
81
130
  when nil
82
- @expected_error
131
+ description_of(@expected_error)
83
132
  when Regexp
84
133
  "#{@expected_error} with message matching #{@expected_message.inspect}"
85
134
  else
86
- "#{@expected_error} with #{@expected_message.inspect}"
135
+ "#{@expected_error} with #{description_of @expected_message}"
87
136
  end
88
137
  end
89
138
 
@@ -93,6 +142,7 @@ module RSpec
93
142
  end
94
143
 
95
144
  def given_error
145
+ return " but was not given a block" unless Proc === @given_proc
96
146
  return " but nothing was raised" unless @actual_error
97
147
 
98
148
  backtrace = format_backtrace(@actual_error.backtrace)
@@ -101,6 +151,14 @@ module RSpec
101
151
  *backtrace
102
152
  ].join("\n # ")
103
153
  end
154
+
155
+ def expecting_specific_exception?
156
+ @expected_error != Exception
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
104
162
  end
105
163
  end
106
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