rubocop-rspec 2.15.0 → 2.17.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (44) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +20 -0
  3. data/README.md +1 -1
  4. data/config/default.yml +54 -16
  5. data/lib/rubocop/cop/rspec/be.rb +2 -0
  6. data/lib/rubocop/cop/rspec/be_eq.rb +3 -0
  7. data/lib/rubocop/cop/rspec/be_eql.rb +3 -0
  8. data/lib/rubocop/cop/rspec/capybara/current_path_expectation.rb +3 -3
  9. data/lib/rubocop/cop/rspec/capybara/match_style.rb +60 -0
  10. data/lib/rubocop/cop/rspec/capybara/negation_matcher.rb +1 -1
  11. data/lib/rubocop/cop/rspec/capybara/specific_actions.rb +1 -1
  12. data/lib/rubocop/cop/rspec/capybara/specific_finders.rb +1 -1
  13. data/lib/rubocop/cop/rspec/capybara/specific_matcher.rb +3 -5
  14. data/lib/rubocop/cop/rspec/capybara/visibility_matcher.rb +1 -1
  15. data/lib/rubocop/cop/rspec/context_wording.rb +0 -1
  16. data/lib/rubocop/cop/rspec/duplicated_metadata.rb +58 -0
  17. data/lib/rubocop/cop/rspec/empty_line_after_example.rb +2 -0
  18. data/lib/rubocop/cop/rspec/expect_actual.rb +2 -0
  19. data/lib/rubocop/cop/rspec/factory_bot/attribute_defined_statically.rb +1 -1
  20. data/lib/rubocop/cop/rspec/factory_bot/consistent_parentheses_style.rb +5 -3
  21. data/lib/rubocop/cop/rspec/factory_bot/create_list.rb +9 -2
  22. data/lib/rubocop/cop/rspec/factory_bot/factory_class_name.rb +1 -1
  23. data/lib/rubocop/cop/rspec/factory_bot/factory_name_style.rb +74 -0
  24. data/lib/rubocop/cop/rspec/implicit_expect.rb +2 -0
  25. data/lib/rubocop/cop/rspec/leading_subject.rb +2 -2
  26. data/lib/rubocop/cop/rspec/message_spies.rb +2 -0
  27. data/lib/rubocop/cop/rspec/mixin/metadata.rb +49 -0
  28. data/lib/rubocop/cop/rspec/pending_without_reason.rb +121 -0
  29. data/lib/rubocop/cop/rspec/predicate_matcher.rb +4 -1
  30. data/lib/rubocop/cop/rspec/rails/have_http_status.rb +5 -2
  31. data/lib/rubocop/cop/rspec/rails/inferred_spec_type.rb +1 -1
  32. data/lib/rubocop/cop/rspec/rails/minitest_assertions.rb +60 -0
  33. data/lib/rubocop/cop/rspec/scattered_setup.rb +2 -0
  34. data/lib/rubocop/cop/rspec/sort_metadata.rb +4 -35
  35. data/lib/rubocop/cop/rspec/stubbed_mock.rb +3 -1
  36. data/lib/rubocop/cop/rspec/subject_stub.rb +0 -1
  37. data/lib/rubocop/cop/rspec/unspecified_exception.rb +2 -0
  38. data/lib/rubocop/cop/rspec_cops.rb +5 -0
  39. data/lib/rubocop/rspec/config_formatter.rb +2 -2
  40. data/lib/rubocop/rspec/description_extractor.rb +5 -10
  41. data/lib/rubocop/rspec/language.rb +6 -2
  42. data/lib/rubocop/rspec/version.rb +1 -1
  43. data/lib/rubocop-rspec.rb +18 -13
  44. metadata +9 -3
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 1e120f8d06ef760cbe4f3a3d077ca6cd8ceeb274a26042a6e1469fe9a280c969
4
- data.tar.gz: 0c80cc155e8f64b03a97de1327e454d9ff2efb1a75b02e3b098f868afed30d17
3
+ metadata.gz: 803b0cb494f6f1204fdb3ec31f7d4a4113b57fb2384066fb322e84107abbc65a
4
+ data.tar.gz: cb5a6a141c0af43cf179ac9d3e568e8bc3b5764abf4fda4e8a09340e7d311161
5
5
  SHA512:
6
- metadata.gz: e982f97a23de2473c5cae6cd20bb653bcbcee806abddf0dda09c7b30692193858fc105c7b46ce3c004f28a7f680d1b3a475298c7b10d0e1499d5b80333fde504
7
- data.tar.gz: c3b79b39a2c98d9103cb4edbf6c2d8e2cc957790fd8fa617e1fdece172f3dfaaf652bf482e7236a1da663f3b9afae943c17efee1e4a5f0293acc771bbc1c3c43
6
+ metadata.gz: 263c0f3e23a10ba54a9fc888646ab9f4e55ea4a08e0adb5b2b32db14c1fc773ed3fa956df3c7a12794c7c3ebea4415e68a42a5d7d109e2da6b88d623417e2102
7
+ data.tar.gz: d976c48d81cfd2d33b4857f08c9860d3857d5f8b51017f99c5ae650102184884dc76d95096d1efc2b70472a063a1887ef4d8e72dc7a6d003b131bf4ca67c4c5e
data/CHANGELOG.md CHANGED
@@ -2,6 +2,26 @@
2
2
 
3
3
  ## Master (Unreleased)
4
4
 
5
+ ## 2.17.0 (2023-01-13)
6
+
7
+ - Fix a false positive for `RSpec/PendingWithoutReason` when pending/skip is argument of methods. ([@ydah])
8
+ - Add new `RSpec/Capybara/MatchStyle` cop. ([@ydah])
9
+ - Add new `RSpec/Rails/MinitestAssertions` cop. ([@ydah])
10
+ - Fix a false positive for `RSpec/PendingWithoutReason` when not inside example. ([@ydah])
11
+ - Fix a false negative for `RSpec/PredicateMatcher` when using `include` and `respond_to`. ([@ydah])
12
+ - Fix a false positive for `RSpec/StubbedMock` when stubbed message expectation with a block and block parameter. ([@ydah])
13
+
14
+ ## 2.16.0 (2022-12-13)
15
+
16
+ - Add new `RSpec/FactoryBot/FactoryNameStyle` cop. ([@ydah])
17
+ - Improved processing speed for `RSpec/Be`, `RSpec/ExpectActual`, `RSpec/ImplicitExpect`, `RSpec/MessageSpies`, `RSpec/PredicateMatcher` and `RSpec/Rails/HaveHttpStatus`. ([@ydah])
18
+ - Fix wrong autocorrection in `n_times` style on `RSpec/FactoryBot/CreateList`. ([@r7kamura])
19
+ - Fix a false positive for `RSpec/FactoryBot/ConsistentParenthesesStyle` when using `generate` with multiple arguments. ([@ydah])
20
+ - Mark `RSpec/BeEq` as `Safe: false` ([@r7kamura])
21
+ - Add `RSpec/DuplicatedMetadata` cop. ([@r7kamura])
22
+ - Mark `RSpec/BeEql` as `Safe: false`. ([@r7kamura])
23
+ - Add `RSpec/PendingWithoutReason` cop. ([@r7kamura])
24
+
5
25
  ## 2.15.0 (2022-11-03)
6
26
 
7
27
  - Fix a false positive for `RSpec/RepeatedDescription` when different its block expectations are used. ([@ydah])
data/README.md CHANGED
@@ -2,7 +2,7 @@
2
2
 
3
3
  [![Join the chat at https://gitter.im/rubocop-rspec/Lobby](https://badges.gitter.im/rubocop-rspec/Lobby.svg)](https://gitter.im/rubocop-rspec/Lobby)
4
4
  [![Gem Version](https://badge.fury.io/rb/rubocop-rspec.svg)](https://rubygems.org/gems/rubocop-rspec)
5
- ![CI](https://github.com/rubocop-hq/rubocop-rspec/workflows/CI/badge.svg)
5
+ ![CI](https://github.com/rubocop/rubocop-rspec/workflows/CI/badge.svg)
6
6
 
7
7
  RSpec-specific analysis for your projects, as an extension to
8
8
  [RuboCop](https://github.com/rubocop/rubocop).
data/config/default.yml CHANGED
@@ -147,13 +147,17 @@ RSpec/Be:
147
147
  RSpec/BeEq:
148
148
  Description: Check for expectations where `be(...)` can replace `eq(...)`.
149
149
  Enabled: pending
150
+ Safe: false
150
151
  VersionAdded: 2.9.0
152
+ VersionChanged: '2.16'
151
153
  Reference: https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/BeEq
152
154
 
153
155
  RSpec/BeEql:
154
156
  Description: Check for expectations where `be(...)` can replace `eql(...)`.
155
157
  Enabled: true
158
+ Safe: false
156
159
  VersionAdded: '1.7'
160
+ VersionChanged: '2.16'
157
161
  Reference: https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/BeEql
158
162
 
159
163
  RSpec/BeNil:
@@ -284,6 +288,12 @@ RSpec/Dialect:
284
288
  VersionAdded: '1.33'
285
289
  Reference: https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/Dialect
286
290
 
291
+ RSpec/DuplicatedMetadata:
292
+ Description: Avoid duplicated metadata.
293
+ Enabled: pending
294
+ VersionAdded: '2.16'
295
+ Reference: https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/DuplicatedMetadata
296
+
287
297
  RSpec/EmptyExampleGroup:
288
298
  Description: Checks if an example group does not include any tests.
289
299
  Enabled: true
@@ -356,12 +366,6 @@ RSpec/ExampleWithoutDescription:
356
366
  VersionAdded: '1.22'
357
367
  Reference: https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/ExampleWithoutDescription
358
368
 
359
- RSpec/ExcessiveDocstringSpacing:
360
- Description: Checks for excessive whitespace in example descriptions.
361
- Enabled: pending
362
- VersionAdded: '2.5'
363
- Reference: https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/ExcessiveDocstringSpacing
364
-
365
369
  RSpec/ExampleWording:
366
370
  Description: Checks for common mistakes in example descriptions.
367
371
  Enabled: true
@@ -378,6 +382,12 @@ RSpec/ExampleWording:
378
382
  StyleGuide: https://rspec.rubystyle.guide/#should-in-example-docstrings
379
383
  Reference: https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/ExampleWording
380
384
 
385
+ RSpec/ExcessiveDocstringSpacing:
386
+ Description: Checks for excessive whitespace in example descriptions.
387
+ Enabled: pending
388
+ VersionAdded: '2.5'
389
+ Reference: https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/ExcessiveDocstringSpacing
390
+
381
391
  RSpec/ExpectActual:
382
392
  Description: Checks for `expect(...)` calls containing literal values.
383
393
  Enabled: true
@@ -664,6 +674,12 @@ RSpec/Pending:
664
674
  VersionAdded: '1.25'
665
675
  Reference: https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/Pending
666
676
 
677
+ RSpec/PendingWithoutReason:
678
+ Description: Checks for pending or skipped examples without reason.
679
+ Enabled: pending
680
+ VersionAdded: '2.16'
681
+ Reference: https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/PendingWithoutReason
682
+
667
683
  RSpec/PredicateMatcher:
668
684
  Description: Prefer using predicate matcher over using predicate method directly.
669
685
  Enabled: true
@@ -871,6 +887,12 @@ RSpec/Capybara/FeatureMethods:
871
887
  VersionChanged: '2.0'
872
888
  Reference: https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/Capybara/FeatureMethods
873
889
 
890
+ RSpec/Capybara/MatchStyle:
891
+ Description: Checks for usage of deprecated style methods.
892
+ Enabled: pending
893
+ VersionAdded: '2.17'
894
+ Reference: https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/Capybara/MatchStyle
895
+
874
896
  RSpec/Capybara/NegationMatcher:
875
897
  Description: Enforces use of `have_no_*` or `not_to` for negated expectations.
876
898
  Enabled: pending
@@ -960,6 +982,16 @@ RSpec/FactoryBot/FactoryClassName:
960
982
  VersionChanged: '2.0'
961
983
  Reference: https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/FactoryBot/FactoryClassName
962
984
 
985
+ RSpec/FactoryBot/FactoryNameStyle:
986
+ Description: Checks for name style for argument of FactoryBot::Syntax::Methods.
987
+ Enabled: pending
988
+ VersionAdded: '2.16'
989
+ EnforcedStyle: symbol
990
+ SupportedStyles:
991
+ - symbol
992
+ - string
993
+ Reference: https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/FactoryBot/FactoryNameStyle
994
+
963
995
  RSpec/FactoryBot/SyntaxMethods:
964
996
  Description: Use shorthands from `FactoryBot::Syntax::Methods` in your specs.
965
997
  Enabled: pending
@@ -985,6 +1017,17 @@ RSpec/Rails/HaveHttpStatus:
985
1017
  VersionAdded: '2.12'
986
1018
  Reference: https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/Rails/HaveHttpStatus
987
1019
 
1020
+ RSpec/Rails/HttpStatus:
1021
+ Description: Enforces use of symbolic or numeric value to describe HTTP status.
1022
+ Enabled: true
1023
+ EnforcedStyle: symbolic
1024
+ SupportedStyles:
1025
+ - numeric
1026
+ - symbolic
1027
+ VersionAdded: '1.23'
1028
+ VersionChanged: '2.0'
1029
+ Reference: https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/Rails/HttpStatus
1030
+
988
1031
  RSpec/Rails/InferredSpecType:
989
1032
  Description: Identifies redundant spec type.
990
1033
  Enabled: pending
@@ -1008,13 +1051,8 @@ RSpec/Rails/InferredSpecType:
1008
1051
  system: system
1009
1052
  views: view
1010
1053
 
1011
- RSpec/Rails/HttpStatus:
1012
- Description: Enforces use of symbolic or numeric value to describe HTTP status.
1013
- Enabled: true
1014
- EnforcedStyle: symbolic
1015
- SupportedStyles:
1016
- - numeric
1017
- - symbolic
1018
- VersionAdded: '1.23'
1019
- VersionChanged: '2.0'
1020
- Reference: https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/Rails/HttpStatus
1054
+ RSpec/Rails/MinitestAssertions:
1055
+ Description: Check if using Minitest matchers.
1056
+ Enabled: pending
1057
+ VersionAdded: '2.17'
1058
+ Reference: https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/Rails/MinitestAssertions
@@ -21,6 +21,8 @@ module RuboCop
21
21
  class Be < Base
22
22
  MSG = "Don't use `be` without an argument."
23
23
 
24
+ RESTRICT_ON_SEND = Runners.all
25
+
24
26
  # @!method be_without_args(node)
25
27
  def_node_matcher :be_without_args, <<-PATTERN
26
28
  (send _ #Runners.all $(send nil? :be))
@@ -9,6 +9,9 @@ module RuboCop
9
9
  # using `==`. Booleans and nil can be compared by identity and therefore
10
10
  # the `be` matcher is preferable as it is a more strict test.
11
11
  #
12
+ # @safety
13
+ # This cop is unsafe because it changes how values are compared.
14
+ #
12
15
  # @example
13
16
  # # bad
14
17
  # expect(foo).to eq(true)
@@ -10,6 +10,9 @@ module RuboCop
10
10
  # can be compared by identity and therefore the `be` matcher is
11
11
  # preferable as it is a more strict test.
12
12
  #
13
+ # @safety
14
+ # This cop is unsafe because it changes how values are compared.
15
+ #
13
16
  # @example
14
17
  # # bad
15
18
  # expect(foo).to eql(1)
@@ -29,7 +29,7 @@ module RuboCop
29
29
  # # good
30
30
  # expect(page).to have_current_path('/callback')
31
31
  #
32
- class CurrentPathExpectation < Base
32
+ class CurrentPathExpectation < ::RuboCop::Cop::Base
33
33
  extend AutoCorrector
34
34
 
35
35
  MSG = 'Do not set an RSpec expectation on `current_path` in ' \
@@ -47,14 +47,14 @@ module RuboCop
47
47
  # @!method as_is_matcher(node)
48
48
  def_node_matcher :as_is_matcher, <<-PATTERN
49
49
  (send
50
- #expectation_set_on_current_path $#Runners.all
50
+ #expectation_set_on_current_path ${:to :to_not :not_to}
51
51
  ${(send nil? :eq ...) (send nil? :match (regexp ...))})
52
52
  PATTERN
53
53
 
54
54
  # @!method regexp_str_matcher(node)
55
55
  def_node_matcher :regexp_str_matcher, <<-PATTERN
56
56
  (send
57
- #expectation_set_on_current_path $#Runners.all
57
+ #expectation_set_on_current_path ${:to :to_not :not_to}
58
58
  $(send nil? :match (str $_)))
59
59
  PATTERN
60
60
 
@@ -0,0 +1,60 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RuboCop
4
+ module Cop
5
+ module RSpec
6
+ module Capybara
7
+ # Checks for usage of deprecated style methods.
8
+ #
9
+ # @example when using `assert_style`
10
+ # # bad
11
+ # page.find(:css, '#first').assert_style(display: 'block')
12
+ #
13
+ # # good
14
+ # page.find(:css, '#first').assert_matches_style(display: 'block')
15
+ #
16
+ # @example when using `has_style?`
17
+ # # bad
18
+ # expect(page.find(:css, 'first')
19
+ # .has_style?(display: 'block')).to be true
20
+ #
21
+ # # good
22
+ # expect(page.find(:css, 'first')
23
+ # .matches_style?(display: 'block')).to be true
24
+ #
25
+ # @example when using `have_style`
26
+ # # bad
27
+ # expect(page).to have_style(display: 'block')
28
+ #
29
+ # # good
30
+ # expect(page).to match_style(display: 'block')
31
+ #
32
+ class MatchStyle < Base
33
+ extend AutoCorrector
34
+
35
+ MSG = 'Use `%<good>s` instead of `%<bad>s`.'
36
+ RESTRICT_ON_SEND = %i[assert_style has_style? have_style].freeze
37
+ PREFERRED_METHOD = {
38
+ 'assert_style' => 'assert_matches_style',
39
+ 'has_style?' => 'matches_style?',
40
+ 'have_style' => 'match_style'
41
+ }.freeze
42
+
43
+ def on_send(node)
44
+ method_node = node.loc.selector
45
+ add_offense(method_node) do |corrector|
46
+ corrector.replace(method_node,
47
+ PREFERRED_METHOD[method_node.source])
48
+ end
49
+ end
50
+
51
+ private
52
+
53
+ def message(node)
54
+ format(MSG, good: PREFERRED_METHOD[node.source], bad: node.source)
55
+ end
56
+ end
57
+ end
58
+ end
59
+ end
60
+ end
@@ -24,7 +24,7 @@ module RuboCop
24
24
  # expect(page).to have_no_selector
25
25
  # expect(page).to have_no_css('a')
26
26
  #
27
- class NegationMatcher < Base
27
+ class NegationMatcher < ::RuboCop::Cop::Base
28
28
  extend AutoCorrector
29
29
  include ConfigurableEnforcedStyle
30
30
 
@@ -20,7 +20,7 @@ module RuboCop
20
20
  # click_link(exact_text: 'foo')
21
21
  # find('div').click_button
22
22
  #
23
- class SpecificActions < Base
23
+ class SpecificActions < ::RuboCop::Cop::Base
24
24
  MSG = "Prefer `%<good_action>s` over `find('%<selector>s').click`."
25
25
  RESTRICT_ON_SEND = %i[click].freeze
26
26
  SPECIFIC_ACTION = {
@@ -15,7 +15,7 @@ module RuboCop
15
15
  # find_by_id('some-id')
16
16
  # find_by_id('some-id', visible: true)
17
17
  #
18
- class SpecificFinders < Base
18
+ class SpecificFinders < ::RuboCop::Cop::Base
19
19
  extend AutoCorrector
20
20
 
21
21
  include RangeHelp
@@ -26,9 +26,7 @@ module RuboCop
26
26
  # expect(page).to have_select
27
27
  # expect(page).to have_field('foo')
28
28
  #
29
- class SpecificMatcher < Base
30
- include CapybaraHelp
31
-
29
+ class SpecificMatcher < ::RuboCop::Cop::Base
32
30
  MSG = 'Prefer `%<good_matcher>s` over `%<bad_matcher>s`.'
33
31
  RESTRICT_ON_SEND = %i[have_selector have_no_selector have_css
34
32
  have_no_css].freeze
@@ -49,8 +47,8 @@ module RuboCop
49
47
  first_argument(node) do |arg|
50
48
  next unless (matcher = specific_matcher(arg))
51
49
  next if CssSelector.multiple_selectors?(arg)
52
- next unless specific_option?(node, arg, matcher)
53
- next unless specific_pseudo_classes?(arg)
50
+ next unless CapybaraHelp.specific_option?(node, arg, matcher)
51
+ next unless CapybaraHelp.specific_pseudo_classes?(arg)
54
52
 
55
53
  add_offense(node, message: message(node, matcher))
56
54
  end
@@ -26,7 +26,7 @@ module RuboCop
26
26
  # expect(page).to have_css('.foo', visible: :all)
27
27
  # expect(page).to have_link('my link', visible: :hidden)
28
28
  #
29
- class VisibilityMatcher < Base
29
+ class VisibilityMatcher < ::RuboCop::Cop::Base
30
30
  MSG_FALSE = 'Use `:all` or `:hidden` instead of `false`.'
31
31
  MSG_TRUE = 'Use `:visible` instead of `true`.'
32
32
  CAPYBARA_MATCHER_METHODS = %w[
@@ -10,7 +10,6 @@ module RuboCop
10
10
  # include `if`, `unless`, `for`, `before`, `after`, or `during`.
11
11
  # They may consist of multiple words if desired.
12
12
  #
13
- # @see https://rspec.rubystyle.guide/#context-descriptions
14
13
  # @see http://www.betterspecs.org/#contexts
15
14
  #
16
15
  # @example `Prefixes` configuration
@@ -0,0 +1,58 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RuboCop
4
+ module Cop
5
+ module RSpec
6
+ # Avoid duplicated metadata.
7
+ #
8
+ # @example
9
+ # # bad
10
+ # describe 'Something', :a, :a
11
+ #
12
+ # # good
13
+ # describe 'Something', :a
14
+ class DuplicatedMetadata < Base
15
+ extend AutoCorrector
16
+
17
+ include Metadata
18
+ include RangeHelp
19
+
20
+ MSG = 'Avoid duplicated metadata.'
21
+
22
+ def on_metadata(symbols, _pairs)
23
+ symbols.each do |symbol|
24
+ on_metadata_symbol(symbol)
25
+ end
26
+ end
27
+
28
+ private
29
+
30
+ def on_metadata_symbol(node)
31
+ return unless duplicated?(node)
32
+
33
+ add_offense(node) do |corrector|
34
+ autocorrect(corrector, node)
35
+ end
36
+ end
37
+
38
+ def autocorrect(corrector, node)
39
+ corrector.remove(
40
+ range_with_surrounding_comma(
41
+ range_with_surrounding_space(
42
+ node.location.expression,
43
+ side: :left
44
+ ),
45
+ :left
46
+ )
47
+ )
48
+ end
49
+
50
+ def duplicated?(node)
51
+ node.left_siblings.any? do |sibling|
52
+ sibling.eql?(node)
53
+ end
54
+ end
55
+ end
56
+ end
57
+ end
58
+ end
@@ -55,6 +55,8 @@ module RuboCop
55
55
  end
56
56
  end
57
57
 
58
+ private
59
+
58
60
  def allowed_one_liner?(node)
59
61
  consecutive_one_liner?(node) && allow_consecutive_one_liners?
60
62
  end
@@ -26,6 +26,8 @@ module RuboCop
26
26
 
27
27
  MSG = 'Provide the actual you are testing to `expect(...)`.'
28
28
 
29
+ RESTRICT_ON_SEND = Runners.all
30
+
29
31
  SIMPLE_LITERALS = %i[
30
32
  true
31
33
  false
@@ -25,7 +25,7 @@ module RuboCop
25
25
  # # good
26
26
  # count { 1 }
27
27
  #
28
- class AttributeDefinedStatically < Base
28
+ class AttributeDefinedStatically < ::RuboCop::Cop::Base
29
29
  extend AutoCorrector
30
30
 
31
31
  MSG = 'Use a block to declare attribute values.'
@@ -40,7 +40,7 @@ module RuboCop
40
40
  # name: 'foo'
41
41
  # )
42
42
  #
43
- class ConsistentParenthesesStyle < Base
43
+ class ConsistentParenthesesStyle < ::RuboCop::Cop::Base
44
44
  extend AutoCorrector
45
45
  include ConfigurableEnforcedStyle
46
46
  include RuboCop::RSpec::FactoryBot::Language
@@ -69,6 +69,8 @@ module RuboCop
69
69
  return if ambiguous_without_parentheses?(node)
70
70
 
71
71
  factory_call(node) do
72
+ return if node.method?(:generate) && node.arguments.count > 1
73
+
72
74
  if node.parenthesized?
73
75
  process_with_parentheses(node)
74
76
  else
@@ -77,6 +79,8 @@ module RuboCop
77
79
  end
78
80
  end
79
81
 
82
+ private
83
+
80
84
  def process_with_parentheses(node)
81
85
  return unless style == :omit_parentheses
82
86
  return unless same_line?(node, node.first_argument)
@@ -102,8 +106,6 @@ module RuboCop
102
106
  node.parent&.array_type?
103
107
  end
104
108
 
105
- private
106
-
107
109
  def remove_parentheses(corrector, node)
108
110
  corrector.replace(node.location.begin, ' ')
109
111
  corrector.remove(node.location.end)
@@ -31,7 +31,7 @@ module RuboCop
31
31
  # # good
32
32
  # 3.times { create :user }
33
33
  #
34
- class CreateList < Base
34
+ class CreateList < ::RuboCop::Cop::Base
35
35
  extend AutoCorrector
36
36
  include ConfigurableEnforcedStyle
37
37
  include RuboCop::RSpec::FactoryBot::Language
@@ -143,7 +143,7 @@ module RuboCop
143
143
 
144
144
  def call(corrector)
145
145
  replacement = generate_n_times_block(node)
146
- corrector.replace(node, replacement)
146
+ corrector.replace(node.block_node || node, replacement)
147
147
  end
148
148
 
149
149
  private
@@ -159,8 +159,15 @@ module RuboCop
159
159
 
160
160
  replacement = format_receiver(node.receiver)
161
161
  replacement += format_method_call(node, 'create', arguments)
162
+ replacement += " #{factory_call_block_source}" if node.block_node
162
163
  "#{count.source}.times { #{replacement} }"
163
164
  end
165
+
166
+ def factory_call_block_source
167
+ node.block_node.location.begin.with(
168
+ end_pos: node.block_node.location.end.end_pos
169
+ ).source
170
+ end
164
171
  end
165
172
 
166
173
  # :nodoc:
@@ -20,7 +20,7 @@ module RuboCop
20
20
  # factory :foo, class: 'Foo' do
21
21
  # end
22
22
  #
23
- class FactoryClassName < Base
23
+ class FactoryClassName < ::RuboCop::Cop::Base
24
24
  extend AutoCorrector
25
25
 
26
26
  MSG = "Pass '%<class_name>s' string instead of `%<class_name>s` " \
@@ -0,0 +1,74 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RuboCop
4
+ module Cop
5
+ module RSpec
6
+ module FactoryBot
7
+ # Checks for name style for argument of FactoryBot::Syntax::Methods.
8
+ #
9
+ # @example EnforcedStyle: symbol (default)
10
+ # # bad
11
+ # create('user')
12
+ # build "user", username: "NAME"
13
+ #
14
+ # # good
15
+ # create(:user)
16
+ # build :user, username: "NAME"
17
+ #
18
+ # @example EnforcedStyle: string
19
+ # # bad
20
+ # create(:user)
21
+ # build :user, username: "NAME"
22
+ #
23
+ # # good
24
+ # create('user')
25
+ # build "user", username: "NAME"
26
+ #
27
+ class FactoryNameStyle < ::RuboCop::Cop::Base
28
+ extend AutoCorrector
29
+ include ConfigurableEnforcedStyle
30
+ include RuboCop::RSpec::FactoryBot::Language
31
+
32
+ MSG = 'Use %<prefer>s to refer to a factory.'
33
+ FACTORY_CALLS = RuboCop::RSpec::FactoryBot::Language::METHODS
34
+ RESTRICT_ON_SEND = FACTORY_CALLS
35
+
36
+ # @!method factory_call(node)
37
+ def_node_matcher :factory_call, <<-PATTERN
38
+ (send
39
+ {#factory_bot? nil?} %FACTORY_CALLS
40
+ ${str sym} ...
41
+ )
42
+ PATTERN
43
+
44
+ def on_send(node)
45
+ factory_call(node) do |name|
46
+ if offense_for_symbol_style?(name)
47
+ register_offense(name, name.value.to_sym.inspect)
48
+ elsif offense_for_string_style?(name)
49
+ register_offense(name, name.value.to_s.inspect)
50
+ end
51
+ end
52
+ end
53
+
54
+ private
55
+
56
+ def offense_for_symbol_style?(name)
57
+ name.str_type? && style == :symbol
58
+ end
59
+
60
+ def offense_for_string_style?(name)
61
+ name.sym_type? && style == :string
62
+ end
63
+
64
+ def register_offense(name, prefer)
65
+ add_offense(name,
66
+ message: format(MSG, prefer: style.to_s)) do |corrector|
67
+ corrector.replace(name, prefer)
68
+ end
69
+ end
70
+ end
71
+ end
72
+ end
73
+ end
74
+ end
@@ -28,6 +28,8 @@ module RuboCop
28
28
 
29
29
  MSG = 'Prefer `%<good>s` over `%<bad>s`.'
30
30
 
31
+ RESTRICT_ON_SEND = Runners.all + %i[should should_not]
32
+
31
33
  # @!method implicit_expect(node)
32
34
  def_node_matcher :implicit_expect, <<-PATTERN
33
35
  {
@@ -44,6 +44,8 @@ module RuboCop
44
44
  check_previous_nodes(node)
45
45
  end
46
46
 
47
+ private
48
+
47
49
  def check_previous_nodes(node)
48
50
  offending_node(node) do |offender|
49
51
  msg = format(MSG, offending: offender.method_name)
@@ -53,8 +55,6 @@ module RuboCop
53
55
  end
54
56
  end
55
57
 
56
- private
57
-
58
58
  def offending_node(node)
59
59
  parent(node).each_child_node.find do |sibling|
60
60
  break if sibling.equal?(node)
@@ -41,6 +41,8 @@ module RuboCop
41
41
 
42
42
  SUPPORTED_STYLES = %w[have_received receive].freeze
43
43
 
44
+ RESTRICT_ON_SEND = Runners.all
45
+
44
46
  # @!method message_expectation(node)
45
47
  def_node_matcher :message_expectation, %(
46
48
  (send (send nil? :expect $_) #Runners.all ...)