Skip to content

Commit ba7f01c

Browse files
committed
test failure messages better
1 parent 0987051 commit ba7f01c

File tree

2 files changed

+60
-14
lines changed

2 files changed

+60
-14
lines changed

lib/rspec/rails/matchers/have_reported_error.rb

Lines changed: 10 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -69,10 +69,10 @@ def description
6969

7070
def failure_message
7171
if !@error_subscriber.events.empty? && !@attributes.empty?
72-
event_data = @error_subscriber.events.last[1].with_indifferent_access
73-
unmatched = unmatched_attributes(event_data["context"])
72+
event_context = @error_subscriber.events.last[1].with_indifferent_access["context"]
73+
unmatched = unmatched_attributes(event_context)
7474
unless unmatched.empty?
75-
return "Expected error attributes to match #{@attributes}, but got these mismatches: #{unmatched} and actual values are #{event_data}"
75+
return "Expected error attributes to match #{@attributes}, but got these mismatches: #{unmatched} and actual values are #{event_context}"
7676
end
7777
elsif @error_subscriber.events.empty?
7878
return 'Expected the block to report an error, but none was reported.'
@@ -94,13 +94,9 @@ def failure_message
9494

9595
def failure_message_when_negated
9696
error_count = @error_subscriber.events.count
97-
if defined?(ActiveSupport::Inflector)
98-
error_word = 'error'.pluralize(error_count)
99-
verb = error_count == 1 ? 'has' : 'have'
100-
else
101-
error_word = error_count == 1 ? 'error' : 'errors'
102-
verb = error_count == 1 ? 'has' : 'have'
103-
end
97+
error_word = 'error'.pluralize(error_count)
98+
verb = error_count == 1 ? 'has' : 'have'
99+
104100
"Expected the block not to report any errors, but #{error_count} #{error_word} #{verb} been reported."
105101
end
106102

@@ -129,8 +125,8 @@ def attributes_match_if_specified?
129125
return true if @attributes.empty?
130126
return false if @error_subscriber.events.empty?
131127

132-
event_data = @error_subscriber.events.last[1].with_indifferent_access
133-
attributes_match?(event_data["context"])
128+
event_context = @error_subscriber.events.last[1].with_indifferent_access["context"]
129+
attributes_match?(event_context)
134130
end
135131

136132
def actual_error
@@ -139,7 +135,7 @@ def actual_error
139135

140136
def attributes_match?(actual)
141137
@attributes.all? do |key, value|
142-
if defined?(RSpec::Matchers) && value.respond_to?(:matches?)
138+
if value.respond_to?(:matches?)
143139
value.matches?(actual[key])
144140
else
145141
actual[key] == value
@@ -149,7 +145,7 @@ def attributes_match?(actual)
149145

150146
def unmatched_attributes(actual)
151147
@attributes.reject do |key, value|
152-
if defined?(RSpec::Matchers) && value.respond_to?(:matches?)
148+
if value.respond_to?(:matches?)
153149
value.matches?(actual[key])
154150
else
155151
actual[key] == value

spec/rspec/rails/matchers/have_reported_error_spec.rb

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -95,6 +95,56 @@ class AnotherTestError < StandardError; end
9595
end
9696
end
9797

98+
describe "failure messages for attribute mismatches" do
99+
it "provides detailed failure message when attributes don't match" do
100+
test_block = proc do
101+
Rails.error.report(StandardError.new("test"), context: { user_id: 123, context: "actual" })
102+
end
103+
matcher = have_reported_error.with(user_id: 456, context: "expected")
104+
105+
matcher.matches?(test_block)
106+
107+
expect(matcher.failure_message).to include("Expected error attributes to match")
108+
expect(matcher.failure_message).to include("user_id: 456")
109+
expect(matcher.failure_message).to include("context: \"expected\"")
110+
end
111+
112+
it "identifies partial attribute mismatches correctly" do
113+
test_block = proc do
114+
Rails.error.report(StandardError.new("test"), context: { user_id: 123, status: "active", role: "admin" })
115+
end
116+
matcher = have_reported_error.with(user_id: 456, status: "active") # user_id wrong, status correct
117+
118+
matcher.matches?(test_block)
119+
120+
failure_msg = matcher.failure_message
121+
expect(failure_msg).to include("got these mismatches: {user_id: 456}")
122+
end
123+
124+
it "handles RSpec matcher mismatches in failure messages" do
125+
test_block = proc do
126+
Rails.error.report(StandardError.new("test"), context: { params: { foo: "different" } })
127+
end
128+
matcher = have_reported_error.with(params: a_hash_including(foo: "bar"))
129+
130+
matcher.matches?(test_block)
131+
132+
expect(matcher.failure_message).to include("Expected error attributes to match")
133+
end
134+
135+
it "shows actual context values when attributes don't match" do
136+
test_block = proc do
137+
Rails.error.report(StandardError.new("test"), context: { user_id: 123, context: "actual" })
138+
end
139+
matcher = have_reported_error.with(user_id: 456)
140+
141+
matcher.matches?(test_block)
142+
143+
failure_msg = matcher.failure_message
144+
expect(failure_msg).to include("actual values are {\"user_id\" => 123, \"context\" => \"actual\"}")
145+
end
146+
end
147+
98148
describe "attribute matching with .with chain" do
99149
it "passes when attributes match exactly" do
100150
test_block = proc do

0 commit comments

Comments
 (0)