-
-
Notifications
You must be signed in to change notification settings - Fork 277
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
Add new RSpec/PredicateMatcher
cop
#442
Conversation
961273b
to
421baf1
Compare
Wow this is amazing! You did this in one day? I'll try to review this beast now |
PATTERN | ||
|
||
def_node_matcher :be_bool?, <<-PATTERN | ||
(send nil {:be :eq} {true false}) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I use eql
a lot so I'd love an :eql
here too
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
👍
And I guess I should add equal
also.
# # bad | ||
# expect(foo).to be_something | ||
# | ||
# # good - the above code is rewrited to it by this cop |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
rewritten
@pocke a few correctness notes that I noticed after running this on a private project. I configured the cop with
and ran autocorrect. A lot of tests failed but only for a few reasons it seems: $ rspec --only-failures > rspec_output.log
$ ack "undefined method \`(.+)'" rspec_output.log --output='$1' | sort | uniq -c | sort -n
9 downcase
14 an_instance_of?
34 has_received?
357 has_attributes?
$ ack --no-filename '^\s+alias_matcher :(\w+),\s+:(\w+)' lib
alias_matcher :a_truthy_value, :be_truthy
alias_matcher :be_falsy, :be_falsey
alias_matcher :a_falsey_value, :be_falsey
alias_matcher :a_falsy_value, :be_falsey
alias_matcher :a_nil_value, :be_nil
alias_matcher :a_value, :be, :klass => AliasedMatcherWithOperatorSupport
alias_matcher :an_instance_of, :be_an_instance_of
alias_matcher :a_kind_of, :be_a_kind_of
alias_matcher :a_value_between, :be_between
alias_matcher :a_value_within, :be_within
alias_matcher :within, :be_within
alias_matcher :a_block_changing, :change
alias_matcher :changing, :change
alias_matcher :a_collection_containing_exactly, :contain_exactly
alias_matcher :containing_exactly, :contain_exactly
alias_matcher :a_range_covering, :cover
alias_matcher :covering, :cover
alias_matcher :a_collection_ending_with, :end_with
alias_matcher :a_string_ending_with, :end_with
alias_matcher :ending_with, :end_with
alias_matcher :an_object_eq_to, :eq
alias_matcher :eq_to, :eq
alias_matcher :an_object_eql_to, :eql
alias_matcher :eql_to, :eql
alias_matcher :an_object_equal_to, :equal
alias_matcher :equal_to, :equal
alias_matcher :an_object_existing, :exist
alias_matcher :existing, :exist
alias_matcher :an_object_having_attributes, :have_attributes
alias_matcher :having_attributes, :have_attributes
alias_matcher :a_collection_including, :include
alias_matcher :a_string_including, :include
alias_matcher :a_hash_including, :include
alias_matcher :including, :include
alias_matcher :match_regex, :match
alias_matcher :an_object_matching, :match
alias_matcher :a_string_matching, :match
alias_matcher :matching, :match
alias_matcher :a_block_outputting, :output
alias_matcher :a_block_raising, :raise_error do |desc|
alias_matcher :raising, :raise_error do |desc|
alias_matcher :an_object_responding_to, :respond_to
alias_matcher :responding_to, :respond_to
alias_matcher :an_object_satisfying, :satisfy
alias_matcher :satisfying, :satisfy
alias_matcher :a_collection_starting_with, :start_with
alias_matcher :a_string_starting_with, :start_with
alias_matcher :starting_with, :start_with
alias_matcher :a_block_throwing, :throw_symbol do |desc|
alias_matcher :throwing, :throw_symbol do |desc|
alias_matcher :a_block_yielding_control, :yield_control
alias_matcher :yielding_control, :yield_control
alias_matcher :a_block_yielding_with_no_args, :yield_with_no_args
alias_matcher :yielding_with_no_args, :yield_with_no_args
alias_matcher :a_block_yielding_with_args, :yield_with_args
alias_matcher :yielding_with_args, :yield_with_args
alias_matcher :a_block_yielding_successive_args, :yield_successive_args
alias_matcher :yielding_successive_args, :yield_successive_args
it 'redirects to settings page' do
expect(response_code).to be(302)
expect(response_headers).to include('Location' => '/settings')
end in this case, This cop is looking really great! Keep up the good work 😄. I'll probably keep reviewing and commenting a bit but just ping me when you've fixed these cases |
Thank for your comment!
👍
👍 I think this cop should be aware of
Definitely. describe do
it 'include' do
hash = {a: 1, b: 2}
expect(hash).to include a: 1
end
it 'include?' do
hash = {a: 1, b: 2}
expect(hash.include?(a: 1)).to be true
end
end $ rspec a.rb
include
include? (FAILED - 1)
Failures:
1) include?
Failure/Error: expect(hash.include?(a: 1)).to be true
expected true
got false
# ./a.rb:9:in `block (2 levels) in <top (required)>'
Finished in 0.01871 seconds (files took 0.15634 seconds to load)
2 examples, 1 failure
Failed examples:
rspec ./a.rb:7 # include? And RSpec documentation mentions it.
|
@backus updated! |
Looks almost perfect! Think I found one more edge case. Try autocorrecting this
with
Once you've fixed that can you squash down? I think I'm good to merge after that |
c3102b0
to
a9f5e9a
Compare
Did you mean # frozen_string_literal: true
RSpec.describe Foo do
specify do
expect(a.an_instance_of??(b)).to be_truthy
end
end I fixed the bug, I made this cop not to add offense if matcher name ends with a diff --git a/lib/rubocop/cop/rspec/predicate_matcher.rb b/lib/rubocop/cop/rspec/predicate_matcher.rb
index e67a604..1079c96 100644
--- a/lib/rubocop/cop/rspec/predicate_matcher.rb
+++ b/lib/rubocop/cop/rspec/predicate_matcher.rb
@@ -163,7 +163,8 @@ module RuboCop
def predicate_matcher_name?(name)
name = name.to_s
name.start_with?('be_', 'have_') &&
- !BUILT_IN_MATCHERS.include?(name)
+ !BUILT_IN_MATCHERS.include?(name) &&
+ !name.end_with?('?')
end
def message_explicit(matcher)
And squashed. Thanks! |
Whoops sorry I messed up my example. This is the before case: # frozen_string_literal: true
RSpec.describe Foo do
it 'works great' do
expect(a.instance_of?(b)).to be(true)
end
end and this is what happens when you autocorrect # frozen_string_literal: true
RSpec.describe Foo do
it 'works great' do
expect(a).to be_an_instance_of?(b)
end
end |
a9f5e9a
to
8a491eb
Compare
8a491eb
to
6374901
Compare
I fixed the autocorrection bug, it was a typo. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Awesome cop! Really great job 😄
Thanks for this awesome cop @pocke! |
Add new `RSpec/PredicateMatcher` cop
Ref #83 #176
This cop is configurable. See this documentation for more details https://github.com/pocke/rubocop-rspec/blob/421baf13936f57c7a97eda09b4ee5f86d2c8025d/lib/rubocop/cop/rspec/predicate_matcher.rb#L232-L268