-
-
Notifications
You must be signed in to change notification settings - Fork 1k
Introduce have_reported_error matcher #2849
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from 12 commits
5e6efcc
5dd2c5c
ce1a162
550c25e
e074991
1fe7e91
6b41d2b
3859b04
8352668
030c27a
2b9bd02
6135d5d
8335664
a14f5c7
af58d83
7259a25
1b6deb6
c77fca5
f5e427a
7b3abc5
2488a71
c1816e2
e1ab316
8674529
8b89342
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,239 @@ | ||
Feature: `have_reported_error` matcher | ||
|
||
The `have_reported_error` matcher is used to check if an error was reported | ||
to Rails error reporting system (`Rails.error`). It can match against error | ||
classes, instances, messages, and attributes. | ||
|
||
The matcher supports several matching strategies: | ||
* Any error reported | ||
* Specific error class | ||
skatkov marked this conversation as resolved.
Show resolved
Hide resolved
|
||
* Specific error instance with message | ||
* Error message patterns using regular expressions | ||
* Error attributes using `.with()` | ||
* Symbol errors | ||
|
||
The matcher is available in all spec types where Rails error reporting is used. | ||
|
||
Background: | ||
Given a file named "app/models/user.rb" with: | ||
"""ruby | ||
class User < ApplicationRecord | ||
skatkov marked this conversation as resolved.
Show resolved
Hide resolved
|
||
def self.process_data | ||
Rails.error.report(StandardError.new("Processing failed")) | ||
end | ||
|
||
def self.process_with_context | ||
Rails.error.report(ArgumentError.new("Invalid input"), context: "user_processing", severity: "high") | ||
end | ||
|
||
def self.process_custom_error | ||
Rails.error.report(ValidationError.new("Email is invalid")) | ||
end | ||
end | ||
""" | ||
And a file named "app/errors/validation_error.rb" with: | ||
"""ruby | ||
class ValidationError < StandardError | ||
end | ||
""" | ||
skatkov marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
Scenario: Checking for any error being reported | ||
Given a file named "spec/models/user_spec.rb" with: | ||
"""ruby | ||
require "rails_helper" | ||
|
||
RSpec.describe User do | ||
it "reports an error during processing" do | ||
skatkov marked this conversation as resolved.
Show resolved
Hide resolved
|
||
expect { | ||
User.process_data | ||
}.to have_reported_error | ||
end | ||
end | ||
""" | ||
When I run `rspec spec/models/user_spec.rb` | ||
Then the examples should all pass | ||
|
||
Scenario: Checking for specific error class | ||
skatkov marked this conversation as resolved.
Show resolved
Hide resolved
|
||
Given a file named "spec/models/user_spec.rb" with: | ||
"""ruby | ||
require "rails_helper" | ||
|
||
RSpec.describe User do | ||
it "reports a StandardError" do | ||
expect { | ||
User.process_data | ||
}.to have_reported_error(StandardError) | ||
end | ||
|
||
it "reports an ArgumentError" do | ||
expect { | ||
User.process_with_context | ||
}.to have_reported_error(ArgumentError) | ||
end | ||
end | ||
""" | ||
When I run `rspec spec/models/user_spec.rb` | ||
Then the examples should all pass | ||
|
||
Scenario: Checking for specific error instance with message | ||
Given a file named "spec/models/user_spec.rb" with: | ||
"""ruby | ||
require "rails_helper" | ||
|
||
RSpec.describe User do | ||
it "reports error with specific message" do | ||
expect { | ||
User.process_data | ||
}.to have_reported_error(StandardError.new("Processing failed")) | ||
end | ||
|
||
it "reports ArgumentError with specific message" do | ||
expect { | ||
User.process_with_context | ||
}.to have_reported_error(ArgumentError.new("Invalid input")) | ||
end | ||
end | ||
""" | ||
When I run `rspec spec/models/user_spec.rb` | ||
Then the examples should all pass | ||
|
||
Scenario: Checking error message patterns with regular expressions | ||
skatkov marked this conversation as resolved.
Show resolved
Hide resolved
|
||
Given a file named "spec/models/user_spec.rb" with: | ||
"""ruby | ||
require "rails_helper" | ||
|
||
RSpec.describe User do | ||
it "reports error with message matching pattern" do | ||
skatkov marked this conversation as resolved.
Show resolved
Hide resolved
|
||
expect { | ||
User.process_data | ||
}.to have_reported_error(/Processing/) | ||
end | ||
|
||
it "reports error with message containing 'failed'" do | ||
expect { | ||
User.process_data | ||
}.to have_reported_error(/failed$/) | ||
end | ||
skatkov marked this conversation as resolved.
Show resolved
Hide resolved
|
||
end | ||
""" | ||
When I run `rspec spec/models/user_spec.rb` | ||
Then the examples should all pass | ||
|
||
Scenario: Checking error attributes using `with` | ||
skatkov marked this conversation as resolved.
Show resolved
Hide resolved
|
||
Given a file named "spec/models/user_spec.rb" with: | ||
"""ruby | ||
require "rails_helper" | ||
|
||
RSpec.describe User do | ||
it "reports error with specific context" do | ||
expect { | ||
User.process_with_context | ||
}.to have_reported_error.with(context: "user_processing") | ||
end | ||
|
||
it "reports error with multiple attributes" do | ||
expect { | ||
User.process_with_context | ||
}.to have_reported_error(ArgumentError).with(context: "user_processing", severity: "high") | ||
end | ||
end | ||
""" | ||
When I run `rspec spec/models/user_spec.rb` | ||
Then the examples should all pass | ||
|
||
Scenario: Checking custom error classes | ||
Given a file named "spec/models/user_spec.rb" with: | ||
"""ruby | ||
require "rails_helper" | ||
|
||
RSpec.describe User do | ||
it "reports a ValidationError" do | ||
expect { | ||
User.process_custom_error | ||
}.to have_reported_error(ValidationError) | ||
end | ||
|
||
it "reports ValidationError with specific message" do | ||
expect { | ||
User.process_custom_error | ||
}.to have_reported_error(ValidationError.new("Email is invalid")) | ||
end | ||
end | ||
""" | ||
When I run `rspec spec/models/user_spec.rb` | ||
Then the examples should all pass | ||
|
||
Scenario: Using negation - expecting no errors | ||
Given a file named "spec/models/user_spec.rb" with: | ||
"""ruby | ||
require "rails_helper" | ||
|
||
RSpec.describe User do | ||
it "does not report any errors for safe operations" do | ||
expect { | ||
# Safe operation that doesn't report errors | ||
"safe code" | ||
}.not_to have_reported_error | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I wonder if the negated form should warn if qualifiers were passed to avoid mistakenly letting unmatched reports through: expect {
User.process_custom_error
}.not_to have_reported_error("Email is TYPO") Meaning that if the matcher is used in the negated form, no class, message, or attributes qualifiers are acceptable. |
||
end | ||
end | ||
""" | ||
When I run `rspec spec/models/user_spec.rb` | ||
Then the examples should all pass | ||
|
||
Scenario: Using in controller specs | ||
Given a file named "spec/controllers/users_controller_spec.rb" with: | ||
"""ruby | ||
require "rails_helper" | ||
|
||
RSpec.describe UsersController, type: :controller do | ||
describe "POST #create" do | ||
it "reports validation errors" do | ||
expect { | ||
post :create, params: { user: { email: "invalid" } } | ||
}.to have_reported_error(ValidationError) | ||
end | ||
end | ||
end | ||
""" | ||
When I run `rspec spec/controllers/users_controller_spec.rb` | ||
Then the examples should all pass | ||
|
||
Scenario: Using in request specs | ||
Given a file named "spec/requests/users_spec.rb" with: | ||
"""ruby | ||
require "rails_helper" | ||
|
||
RSpec.describe "Users", type: :request do | ||
describe "POST /users" do | ||
it "reports processing errors" do | ||
expect { | ||
post "/users", params: { user: { name: "Test" } } | ||
}.to have_reported_error.with(context: "user_creation") | ||
end | ||
end | ||
end | ||
""" | ||
When I run `rspec spec/requests/users_spec.rb` | ||
Then the examples should all pass | ||
|
||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This isn't a controller / request specific matcher so these feel out of place, why these, why not every aspect of Rails... I'd just cut them. |
||
Scenario: Complex error matching with multiple conditions | ||
Given a file named "spec/models/user_spec.rb" with: | ||
"""ruby | ||
require "rails_helper" | ||
|
||
RSpec.describe User do | ||
it "reports error with class, message pattern, and attributes" do | ||
expect { | ||
Rails.error.report( | ||
ArgumentError.new("Invalid user data provided"), | ||
context: "validation", | ||
severity: "critical", | ||
user_id: 123 | ||
) | ||
}.to have_reported_error(ArgumentError) | ||
.with(context: "validation", severity: "critical") | ||
end | ||
end | ||
""" | ||
When I run `rspec spec/models/user_spec.rb` | ||
Then the examples should all pass | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Incorrect line ending here. |
Uh oh!
There was an error while loading. Please reload this page.