Skip to content
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 configuration option CustomTransformPatterns to RSpec/SpecFilePathFormat #1716

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
- Add support for correcting "it will" (future tense) for `RSpec/ExampleWording`. ([@jdufresne])
- Add support for `symbol` style for `RSpec/SharedExamples`. ([@jessieay])
- Ensure `PendingWithoutReason` can detect violations inside shared groups. ([@robinaugh])
- Add configuration option `CustomTransformPatterns` to `RSpec/SpecFilePathFormat`. ([@ydah])

## 2.25.0 (2023-10-27)

Expand Down
3 changes: 3 additions & 0 deletions config/default.yml
Original file line number Diff line number Diff line change
Expand Up @@ -889,10 +889,13 @@ RSpec/SpecFilePathFormat:
CustomTransform:
RuboCop: rubocop
RSpec: rspec
CustomTransformPatterns:
API: api
IgnoreMethods: false
IgnoreMetadata:
type: routing
VersionAdded: '2.24'
VersionChanged: "<<next>>"
Reference: https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/SpecFilePathFormat

RSpec/SpecFilePathSuffix:
Expand Down
21 changes: 20 additions & 1 deletion docs/modules/ROOT/pages/cops_rspec.adoc
Original file line number Diff line number Diff line change
@@ -1,3 +1,9 @@
////
Do NOT edit this file by hand directly, as it is automatically generated.

Please make any necessary changes to the cop documentation within the source files themselves.
////

= RSpec

== RSpec/AlignLeftLetBrace
Expand Down Expand Up @@ -5270,7 +5276,7 @@ it 'works', :a, :b, baz: true, foo: 'bar'
| Yes
| No
| 2.24
| -
| <<next>>
|===

Checks that spec file paths are consistent and well-formed.
Expand Down Expand Up @@ -5298,6 +5304,15 @@ rubocop_spec.rb # describe RuboCop
rspec_spec.rb # describe RSpec
----

==== `CustomTransformPatterns: {API=>api}` (default)

[source,ruby]
----
# good
apis_spec.rb # describe APIs
foo_apis_spec.rb # describe Foo::APIs
----

==== `IgnoreMethods: false` (default)

[source,ruby]
Expand Down Expand Up @@ -5339,6 +5354,10 @@ whatever_spec.rb # describe MyClass, type: :routing do; end
| `{"RuboCop"=>"rubocop", "RSpec"=>"rspec"}`
|

| CustomTransformPatterns
| `{"API"=>"api"}`
|

| IgnoreMethods
| `false`
| Boolean
Expand Down
6 changes: 6 additions & 0 deletions docs/modules/ROOT/pages/cops_rspec_capybara.adoc
Original file line number Diff line number Diff line change
@@ -1,3 +1,9 @@
////
Do NOT edit this file by hand directly, as it is automatically generated.

Please make any necessary changes to the cop documentation within the source files themselves.
////

= RSpec/Capybara

== RSpec/Capybara/CurrentPathExpectation
Expand Down
6 changes: 6 additions & 0 deletions docs/modules/ROOT/pages/cops_rspec_factorybot.adoc
Original file line number Diff line number Diff line change
@@ -1,3 +1,9 @@
////
Do NOT edit this file by hand directly, as it is automatically generated.

Please make any necessary changes to the cop documentation within the source files themselves.
////

= RSpec/FactoryBot

== RSpec/FactoryBot/AttributeDefinedStatically
Expand Down
6 changes: 6 additions & 0 deletions docs/modules/ROOT/pages/cops_rspec_rails.adoc
Original file line number Diff line number Diff line change
@@ -1,3 +1,9 @@
////
Do NOT edit this file by hand directly, as it is automatically generated.

Please make any necessary changes to the cop documentation within the source files themselves.
////

= RSpec/Rails

== RSpec/Rails/AvoidSetupHook
Expand Down
17 changes: 17 additions & 0 deletions lib/rubocop/cop/rspec/spec_file_path_format.rb
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,11 @@ module RSpec
# rubocop_spec.rb # describe RuboCop
# rspec_spec.rb # describe RSpec
#
# @example `CustomTransformPatterns: {API=>api}` (default)
# # good
# apis_spec.rb # describe APIs
# foo_apis_spec.rb # describe Foo::APIs
#
# @example `IgnoreMethods: false` (default)
# # bad
# my_class_spec.rb # describe MyClass, '#method'
Expand Down Expand Up @@ -100,11 +105,19 @@ def expected_path(constant)

File.join(
constants.map do |name|
pattern, transformed = transformed_pattern(name)
name.gsub!(pattern, transformed.capitalize) if transformed
custom_transform.fetch(name) { camel_to_snake_case(name) }
end
)
end

def transformed_pattern(name)
custom_transform_patterns.find do |pattern, _|
name.include?(pattern)
end
end

def camel_to_snake_case(string)
string
.gsub(/([^A-Z])([A-Z]+)/, '\1_\2')
Expand All @@ -116,6 +129,10 @@ def custom_transform
cop_config.fetch('CustomTransform', {})
end

def custom_transform_patterns
cop_config.fetch('CustomTransformPatterns', {})
end

def ignore_methods?
cop_config['IgnoreMethods']
end
Expand Down
59 changes: 53 additions & 6 deletions spec/rubocop/cop/rspec/spec_file_path_format_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -233,19 +233,66 @@ class Foo
RUBY
end

context 'when configured with `CustomTransform: { "FooFoo" => "foofoo" }`' do
let(:cop_config) { { 'CustomTransform' => { 'FooFoo' => 'foofoo' } } }
context 'when configured with `CustomTransform: { "RSpec" => "rspec" }`' do
let(:cop_config) do
{
'CustomTransform' => { 'RSpec' => 'rspec' },
'CustomTransformPatterns' => {}
}
end

it 'registers an offense when not an exact match to custom ' \
'module name transformation' do
expect_offense(<<-RUBY, 'rspec_foo_spec.rb')
RSpec.describe RSpecFoo do; end
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The best way to demo the difference between those two option would be RSpec.describe CustomDSL and DSL => dsl mapping. One would insist on custom_d_s_l_*spec.rb, the other on custom_dsl_*spec.rb, right?

Namespaces and RSpecFoo don't help understand it.

I keep losing grip about this option.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This does not appear to be an offense when followed by only one uppercase letter, as in DSL, so this is not the case that can be resolved with this option. This option may not be a common use case.

^^^^^^^^^^^^^^^^^^^^^^^ Spec path should end with `r_spec_foo*_spec.rb`.
RUBY
end

it 'registers an offense when not an exact match to custom ' \
'module name transformation with nested directories' do
expect_offense(<<-RUBY, 'foo/some/rspec_foo/bar_spec.rb')
describe Foo::Some::RSpecFoo, '#bar' do; end
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Spec path should end with `foo/some/r_spec_foo*bar*_spec.rb`.
RUBY
end

it 'does not register an offense when an exact match to custom ' \
'module name transformation' do
expect_no_offenses(<<-RUBY, 'rspec/some/foo/bar_spec.rb')
describe RSpec::Some::Foo, '#bar' do; end
RUBY
end
end

context 'when configured with `CustomTransformPatterns: ' \
'{ "API" => "api" }`' do
let(:cop_config) { { 'CustomTransformPatterns' => { 'API' => 'api' } } }

it 'does not register an offense when not an exact match to custom ' \
'module name transformation' do
expect_no_offenses(<<-RUBY, 'foo/some/apis_foo/bar_spec.rb')
describe Foo::Some::APIsFoo, '#bar' do; end
RUBY
end

it 'does not register an offense when an exact match to custom ' \
'module name transformation' do
expect_no_offenses(<<-RUBY, 'foo_apis_spec.rb')
RSpec.describe FooAPIs do; end
RUBY
end

it 'does not register an offense for custom module name transformation' do
expect_no_offenses(<<~RUBY, 'foofoo/some/class/bar_spec.rb')
describe FooFoo::Some::Class, '#bar' do; end
it 'does not register an offense when an exact match to custom ' \
'module name transformation with nested directories' do
expect_no_offenses(<<-RUBY, 'apis/some/foo/bar_spec.rb')
describe APIs::Some::Foo, '#bar' do; end
RUBY
end
end

context 'when configured with `IgnoreMethods: false`' do
let(:cop_config) { { 'IgnoreMethods' => false } }
let(:suffix) { 'my_class*look_here_a_method*_spec.rb' }

it 'registers an offense when file path not include method name' do
expect_offense(<<~RUBY, 'my_class_spec.rb')
Expand Down