33module RSpec
44 module Rails
55 module Matchers
6+ # @api private
7+ # Sentinel value to distinguish between no argument passed vs explicitly passed nil.
8+ # This follows the same pattern as RSpec's raise_error matcher.
9+ UndefinedValue = Object . new . freeze
10+
611 # @api private
712 class ErrorSubscriber
813 attr_reader :events
@@ -28,17 +33,20 @@ def report(error, **attrs)
2833 class HaveReportedError < RSpec ::Rails ::Matchers ::BaseMatcher
2934 # Initialize the matcher following raise_error patterns
3035 #
36+ # Uses UndefinedValue as default to distinguish between no argument
37+ # passed vs explicitly passed nil (same as raise_error matcher).
38+ #
3139 # @param expected_error_or_message [Class, String, Regexp, nil]
3240 # Error class, message string, or message pattern
3341 # @param expected_message [String, Regexp, nil]
3442 # Expected message when first param is a class
35- def initialize ( expected_error_or_message = nil , expected_message = nil )
43+ def initialize ( expected_error_or_message = UndefinedValue , expected_message = nil )
3644 @actual_error = nil
3745 @attributes = { }
3846 @error_subscriber = nil
3947
4048 case expected_error_or_message
41- when nil
49+ when nil , UndefinedValue
4250 @expected_error = nil
4351 @expected_message = expected_message
4452 when String , Regexp
@@ -232,7 +240,7 @@ def unmatched_attributes(actual)
232240 #
233241 # @param expected_error_or_message [Class, String, Regexp, nil] the expected error class, message string, or message pattern
234242 # @param expected_message [String, Regexp, nil] the expected error message to match
235- def have_reported_error ( expected_error_or_message = nil , expected_message = nil )
243+ def have_reported_error ( expected_error_or_message = UndefinedValue , expected_message = nil )
236244 HaveReportedError . new ( expected_error_or_message , expected_message )
237245 end
238246
0 commit comments