rubocop-rspec 2.15.0 → 2.17.0

Sign up to get free protection for your applications and to get access to all the features.
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 ...)