-
-
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
Fix RSpec/SortMetadata
cop to sort strings and variables first
#1948
base: master
Are you sure you want to change the base?
Fix RSpec/SortMetadata
cop to sort strings and variables first
#1948
Conversation
it 'registers an offense when a symbol metadata is before second docstring ' \ | ||
'argument' do | ||
expect_offense(<<~RUBY) | ||
RSpec.describe 'Something', :a, :z, 'second docstring' do |
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.
Invalid RSpec syntax:
ArgumentError:
wrong number of arguments (given 4, expected 0..2)
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.
Yes indeed.
Actually there was already an existing test on master
which would lead to this ArgumentError
, even after autocorrect:
rubocop-rspec/spec/rubocop/cop/rspec/sort_metadata_spec.rb
Lines 98 to 111 in 74d7837
it 'registers an offense when using mixed metadata ' \ | |
'and both symbols metadata and hash keys are not in alphabetical order ' \ | |
'and the hash values are complex objects' do | |
expect_offense(<<~RUBY) | |
it 'Something', variable, 'B', :a, key => {}, foo: ->(x) { bar(x) }, Identifier.sample => true, baz: Snafu.new do | |
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Sort metadata alphabetically. | |
end | |
RUBY | |
expect_correction(<<~RUBY) | |
it 'Something', :a, 'B', variable, baz: Snafu.new, foo: ->(x) { bar(x) }, Identifier.sample => true, key => {} do | |
end | |
RUBY | |
end |
That's why I thought adding this test would be ok. Note that after autocorrect the last string argument is moved at the 2nd place, so the ArgumentError
would not occur anymore.
How should I rewrite this one?
it 'registers an offense when a symbol metadata is before a variable ' \ | ||
'argument' do | ||
expect_offense(<<~RUBY) | ||
RSpec.describe 'Something', :a, :z, variable, foo: :bar do |
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.
If the variable
holds something that is not a symbol, this will fail with a similar ArgumentError
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.
Yes indeed.
It is a bit like this existing test of MetadataStyle
cop:
rubocop-rspec/spec/rubocop/cop/rspec/metadata_style_spec.rb
Lines 354 to 364 in 74d7837
context 'with symbol metadata with another existing non-literal metadata' do | |
it 'registers offense' do | |
expect_offense(<<~RUBY) | |
describe 'Something', :a, b do | |
^^ Use hash style for metadata. | |
end | |
RUBY | |
expect_no_corrections | |
end | |
end |
This one too will fail if b
is not a symbol nor a hash.
How should I rewrite it then? Adding a variable = :v
on the first line?
it 'does not register an offense when a symbol metadata is before a ' \ | ||
'variable argument being the last argument as it could be a hash' do | ||
expect_no_offenses(<<~RUBY) | ||
RSpec.describe 'Something', :a, :z, some_hash do |
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.
What if it's a
RSpec.describe 'Something', :z, :a, some_hash do
?
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.
Then it would register an offense and would autocorrect it like this:
RSpec.describe 'Something', :a, :z, some_hash do
This test was inspired from this MetadataStyle
cop test:
rubocop-rspec/spec/rubocop/cop/rspec/metadata_style_spec.rb
Lines 354 to 364 in 74d7837
context 'with symbol metadata with another existing non-literal metadata' do | |
it 'registers offense' do | |
expect_offense(<<~RUBY) | |
describe 'Something', :a, b do | |
^^ Use hash style for metadata. | |
end | |
RUBY | |
expect_no_corrections | |
end | |
end |
It ensures that a variable is not moved at the start of the arguments list if this variable is at the end of the arguments list, because it could hold a hash.
Should I update the spec to swap :a
and :z
and expect the offense and correction as described above?
it 'does not register an offense when using a second level description ' \ | ||
'not in alphabetical order with symbol metadata' do | ||
expect_no_offenses(<<~RUBY) | ||
RSpec.describe 'Something', 'second docstring', :a, :b do |
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.
Invalid syntax
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.
Actually, this one is correct.
It's when there are more than 2 non-symbol arguments that the ArgumentError: wrong number of arguments (given 4, expected 0..2)
is raised.
I suggest extending the spec in accordance with our findings. I'm happy to help on this front. Please accept my apologies for the delay in review, it's a summer season over here. |
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 replied to your comments and I am open to amend this pull request with your suggestions.
Please accept my apologies for the delay as well. As you wrote, it's summer season.
it 'registers an offense when a symbol metadata is before second docstring ' \ | ||
'argument' do | ||
expect_offense(<<~RUBY) | ||
RSpec.describe 'Something', :a, :z, 'second docstring' do |
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.
Yes indeed.
Actually there was already an existing test on master
which would lead to this ArgumentError
, even after autocorrect:
rubocop-rspec/spec/rubocop/cop/rspec/sort_metadata_spec.rb
Lines 98 to 111 in 74d7837
it 'registers an offense when using mixed metadata ' \ | |
'and both symbols metadata and hash keys are not in alphabetical order ' \ | |
'and the hash values are complex objects' do | |
expect_offense(<<~RUBY) | |
it 'Something', variable, 'B', :a, key => {}, foo: ->(x) { bar(x) }, Identifier.sample => true, baz: Snafu.new do | |
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Sort metadata alphabetically. | |
end | |
RUBY | |
expect_correction(<<~RUBY) | |
it 'Something', :a, 'B', variable, baz: Snafu.new, foo: ->(x) { bar(x) }, Identifier.sample => true, key => {} do | |
end | |
RUBY | |
end |
That's why I thought adding this test would be ok. Note that after autocorrect the last string argument is moved at the 2nd place, so the ArgumentError
would not occur anymore.
How should I rewrite this one?
it 'registers an offense when a symbol metadata is before a variable ' \ | ||
'argument' do | ||
expect_offense(<<~RUBY) | ||
RSpec.describe 'Something', :a, :z, variable, foo: :bar do |
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.
Yes indeed.
It is a bit like this existing test of MetadataStyle
cop:
rubocop-rspec/spec/rubocop/cop/rspec/metadata_style_spec.rb
Lines 354 to 364 in 74d7837
context 'with symbol metadata with another existing non-literal metadata' do | |
it 'registers offense' do | |
expect_offense(<<~RUBY) | |
describe 'Something', :a, b do | |
^^ Use hash style for metadata. | |
end | |
RUBY | |
expect_no_corrections | |
end | |
end |
This one too will fail if b
is not a symbol nor a hash.
How should I rewrite it then? Adding a variable = :v
on the first line?
it 'does not register an offense when a symbol metadata is before a ' \ | ||
'variable argument being the last argument as it could be a hash' do | ||
expect_no_offenses(<<~RUBY) | ||
RSpec.describe 'Something', :a, :z, some_hash do |
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.
Then it would register an offense and would autocorrect it like this:
RSpec.describe 'Something', :a, :z, some_hash do
This test was inspired from this MetadataStyle
cop test:
rubocop-rspec/spec/rubocop/cop/rspec/metadata_style_spec.rb
Lines 354 to 364 in 74d7837
context 'with symbol metadata with another existing non-literal metadata' do | |
it 'registers offense' do | |
expect_offense(<<~RUBY) | |
describe 'Something', :a, b do | |
^^ Use hash style for metadata. | |
end | |
RUBY | |
expect_no_corrections | |
end | |
end |
It ensures that a variable is not moved at the start of the arguments list if this variable is at the end of the arguments list, because it could hold a hash.
Should I update the spec to swap :a
and :z
and expect the offense and correction as described above?
it 'does not register an offense when using a second level description ' \ | ||
'not in alphabetical order with symbol metadata' do | ||
expect_no_offenses(<<~RUBY) | ||
RSpec.describe 'Something', 'second docstring', :a, :b do |
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.
Actually, this one is correct.
It's when there are more than 2 non-symbol arguments that the ArgumentError: wrong number of arguments (given 4, expected 0..2)
is raised.
Fixes rubocop#1946. Symbols in metadata are processed by RSpec only when they are positioned last, meaning the other parameter types must be positioned before the symbols. RSpec `context`/`describe` accepts second non-symbol argument as an additional description which is why strings are sorted first.
95de9d6
to
7d1c8b8
Compare
Fixes #1946.
Symbols in metadata are processed by RSpec only when they are positioned last, meaning the other parameter types must be positioned before the symbols. RSpec
context
/describe
accepts second non-symbol argument as an additional description which is why strings are sorted first.Questions for reviewers:
describe 'Something', :a, b, :c
because the metadata is sorted. I could not come up with a good message. Suggestions?describe 'Something', :b, :a, { foo: :bar }
: it gets autocorrected todescribe 'Something', :b, :a, foo: :bar }
. Should it be fixed in the same PR?RuboCop::Cop::RSpec::Metadata#on_metadata_arguments
method because it was skipping the last argument if it was not a hash. I also renamedsymbols
tometadata_arguments
(orargs
inRSpec/SortMetadata
cop). Shouldsymbols
be renamed tometadata_arguments
orargs
in other cops relying onon_metadata
too?Before submitting the PR make sure the following are checked:
master
(if not - rebase it).CHANGELOG.md
if the new code introduces user-observable changes.bundle exec rake
) passes (be sure to run this locally, since it may produce updated documentation that you will need to commit).