1
+ Feature : `have_reported_error` matcher
2
+
3
+ The `have_reported_error` matcher is used to check if an error was reported
4
+ to Rails error reporting system (`Rails.error`). It can match against error
5
+ classes, instances, messages, and attributes.
6
+
7
+ The matcher supports several matching strategies:
8
+ * Any error reported
9
+ * Specific error class
10
+ * Specific error instance with message
11
+ * Error message patterns using regular expressions
12
+ * Error attributes using `.with()`
13
+ * Symbol errors
14
+
15
+ The matcher is available in all spec types where Rails error reporting is used.
16
+
17
+ Background :
18
+ Given a file named "app/models/user.rb" with:
19
+ """ruby
20
+ class User < ApplicationRecord
21
+ def self.process_data
22
+ Rails.error.report(StandardError.new("Processing failed"))
23
+ end
24
+
25
+ def self.process_with_context
26
+ Rails.error.report(ArgumentError.new("Invalid input"), context: "user_processing", severity: "high")
27
+ end
28
+
29
+ def self.process_custom_error
30
+ Rails.error.report(ValidationError.new("Email is invalid"))
31
+ end
32
+ end
33
+ """
34
+ And a file named "app/errors/validation_error.rb" with:
35
+ """ruby
36
+ class ValidationError < StandardError
37
+ end
38
+ """
39
+
40
+ Scenario : Checking for any error being reported
41
+ Given a file named "spec/models/user_spec.rb" with:
42
+ """ruby
43
+ require "rails_helper"
44
+
45
+ RSpec.describe User do
46
+ it "reports an error during processing" do
47
+ expect {
48
+ User.process_data
49
+ }.to have_reported_error
50
+ end
51
+ end
52
+ """
53
+ When I run `rspec spec/models/user_spec.rb`
54
+ Then the examples should all pass
55
+
56
+ Scenario : Checking for specific error class
57
+ Given a file named "spec/models/user_spec.rb" with:
58
+ """ruby
59
+ require "rails_helper"
60
+
61
+ RSpec.describe User do
62
+ it "reports a StandardError" do
63
+ expect {
64
+ User.process_data
65
+ }.to have_reported_error(StandardError)
66
+ end
67
+
68
+ it "reports an ArgumentError" do
69
+ expect {
70
+ User.process_with_context
71
+ }.to have_reported_error(ArgumentError)
72
+ end
73
+ end
74
+ """
75
+ When I run `rspec spec/models/user_spec.rb`
76
+ Then the examples should all pass
77
+
78
+ Scenario : Checking for specific error instance with message
79
+ Given a file named "spec/models/user_spec.rb" with:
80
+ """ruby
81
+ require "rails_helper"
82
+
83
+ RSpec.describe User do
84
+ it "reports error with specific message" do
85
+ expect {
86
+ User.process_data
87
+ }.to have_reported_error(StandardError.new("Processing failed"))
88
+ end
89
+
90
+ it "reports ArgumentError with specific message" do
91
+ expect {
92
+ User.process_with_context
93
+ }.to have_reported_error(ArgumentError.new("Invalid input"))
94
+ end
95
+ end
96
+ """
97
+ When I run `rspec spec/models/user_spec.rb`
98
+ Then the examples should all pass
99
+
100
+ Scenario : Checking error message patterns with regular expressions
101
+ Given a file named "spec/models/user_spec.rb" with:
102
+ """ruby
103
+ require "rails_helper"
104
+
105
+ RSpec.describe User do
106
+ it "reports error with message matching pattern" do
107
+ expect {
108
+ User.process_data
109
+ }.to have_reported_error(/Processing/)
110
+ end
111
+
112
+ it "reports error with message containing 'failed'" do
113
+ expect {
114
+ User.process_data
115
+ }.to have_reported_error(/failed$/)
116
+ end
117
+ end
118
+ """
119
+ When I run `rspec spec/models/user_spec.rb`
120
+ Then the examples should all pass
121
+
122
+ Scenario : Checking error attributes using `with`
123
+ Given a file named "spec/models/user_spec.rb" with:
124
+ """ruby
125
+ require "rails_helper"
126
+
127
+ RSpec.describe User do
128
+ it "reports error with specific context" do
129
+ expect {
130
+ User.process_with_context
131
+ }.to have_reported_error.with(context: "user_processing")
132
+ end
133
+
134
+ it "reports error with multiple attributes" do
135
+ expect {
136
+ User.process_with_context
137
+ }.to have_reported_error(ArgumentError).with(context: "user_processing", severity: "high")
138
+ end
139
+ end
140
+ """
141
+ When I run `rspec spec/models/user_spec.rb`
142
+ Then the examples should all pass
143
+
144
+ Scenario : Checking custom error classes
145
+ Given a file named "spec/models/user_spec.rb" with:
146
+ """ruby
147
+ require "rails_helper"
148
+
149
+ RSpec.describe User do
150
+ it "reports a ValidationError" do
151
+ expect {
152
+ User.process_custom_error
153
+ }.to have_reported_error(ValidationError)
154
+ end
155
+
156
+ it "reports ValidationError with specific message" do
157
+ expect {
158
+ User.process_custom_error
159
+ }.to have_reported_error(ValidationError.new("Email is invalid"))
160
+ end
161
+ end
162
+ """
163
+ When I run `rspec spec/models/user_spec.rb`
164
+ Then the examples should all pass
165
+
166
+ Scenario : Using negation - expecting no errors
167
+ Given a file named "spec/models/user_spec.rb" with:
168
+ """ruby
169
+ require "rails_helper"
170
+
171
+ RSpec.describe User do
172
+ it "does not report any errors for safe operations" do
173
+ expect {
174
+ # Safe operation that doesn't report errors
175
+ "safe code"
176
+ }.not_to have_reported_error
177
+ end
178
+ end
179
+ """
180
+ When I run `rspec spec/models/user_spec.rb`
181
+ Then the examples should all pass
182
+
183
+ Scenario : Using in controller specs
184
+ Given a file named "spec/controllers/users_controller_spec.rb" with:
185
+ """ruby
186
+ require "rails_helper"
187
+
188
+ RSpec.describe UsersController, type: :controller do
189
+ describe "POST #create" do
190
+ it "reports validation errors" do
191
+ expect {
192
+ post :create, params: { user: { email: "invalid" } }
193
+ }.to have_reported_error(ValidationError)
194
+ end
195
+ end
196
+ end
197
+ """
198
+ When I run `rspec spec/controllers/users_controller_spec.rb`
199
+ Then the examples should all pass
200
+
201
+ Scenario : Using in request specs
202
+ Given a file named "spec/requests/users_spec.rb" with:
203
+ """ruby
204
+ require "rails_helper"
205
+
206
+ RSpec.describe "Users", type: :request do
207
+ describe "POST /users" do
208
+ it "reports processing errors" do
209
+ expect {
210
+ post "/users", params: { user: { name: "Test" } }
211
+ }.to have_reported_error.with(context: "user_creation")
212
+ end
213
+ end
214
+ end
215
+ """
216
+ When I run `rspec spec/requests/users_spec.rb`
217
+ Then the examples should all pass
218
+
219
+ Scenario : Complex error matching with multiple conditions
220
+ Given a file named "spec/models/user_spec.rb" with:
221
+ """ruby
222
+ require "rails_helper"
223
+
224
+ RSpec.describe User do
225
+ it "reports error with class, message pattern, and attributes" do
226
+ expect {
227
+ Rails.error.report(
228
+ ArgumentError.new("Invalid user data provided"),
229
+ context: "validation",
230
+ severity: "critical",
231
+ user_id: 123
232
+ )
233
+ }.to have_reported_error(ArgumentError)
234
+ .with(context: "validation", severity: "critical")
235
+ end
236
+ end
237
+ """
238
+ When I run `rspec spec/models/user_spec.rb`
239
+ Then the examples should all pass
0 commit comments