rubocop-rspec 2.14.2 → 2.16.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (43) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +24 -0
  3. data/config/default.yml +48 -29
  4. data/lib/rubocop/cop/rspec/be.rb +2 -0
  5. data/lib/rubocop/cop/rspec/be_eq.rb +3 -0
  6. data/lib/rubocop/cop/rspec/be_eql.rb +3 -0
  7. data/lib/rubocop/cop/rspec/capybara/current_path_expectation.rb +3 -3
  8. data/lib/rubocop/cop/rspec/capybara/negation_matcher.rb +1 -1
  9. data/lib/rubocop/cop/rspec/capybara/specific_actions.rb +1 -1
  10. data/lib/rubocop/cop/rspec/capybara/specific_finders.rb +1 -1
  11. data/lib/rubocop/cop/rspec/capybara/specific_matcher.rb +3 -5
  12. data/lib/rubocop/cop/rspec/capybara/visibility_matcher.rb +1 -1
  13. data/lib/rubocop/cop/rspec/duplicated_metadata.rb +58 -0
  14. data/lib/rubocop/cop/rspec/empty_line_after_example.rb +2 -0
  15. data/lib/rubocop/cop/rspec/expect_actual.rb +2 -0
  16. data/lib/rubocop/cop/rspec/factory_bot/attribute_defined_statically.rb +1 -1
  17. data/lib/rubocop/cop/rspec/factory_bot/consistent_parentheses_style.rb +16 -9
  18. data/lib/rubocop/cop/rspec/factory_bot/create_list.rb +9 -2
  19. data/lib/rubocop/cop/rspec/factory_bot/factory_class_name.rb +1 -1
  20. data/lib/rubocop/cop/rspec/factory_bot/factory_name_style.rb +74 -0
  21. data/lib/rubocop/cop/rspec/implicit_expect.rb +2 -0
  22. data/lib/rubocop/cop/rspec/leading_subject.rb +2 -2
  23. data/lib/rubocop/cop/rspec/message_spies.rb +2 -0
  24. data/lib/rubocop/cop/rspec/mixin/metadata.rb +49 -0
  25. data/lib/rubocop/cop/rspec/named_subject.rb +81 -6
  26. data/lib/rubocop/cop/rspec/nested_groups.rb +1 -1
  27. data/lib/rubocop/cop/rspec/pending_without_reason.rb +123 -0
  28. data/lib/rubocop/cop/rspec/predicate_matcher.rb +2 -0
  29. data/lib/rubocop/cop/rspec/rails/have_http_status.rb +5 -2
  30. data/lib/rubocop/cop/rspec/rails/inferred_spec_type.rb +1 -1
  31. data/lib/rubocop/cop/rspec/repeated_description.rb +25 -2
  32. data/lib/rubocop/cop/rspec/scattered_setup.rb +2 -0
  33. data/lib/rubocop/cop/rspec/sort_metadata.rb +4 -35
  34. data/lib/rubocop/cop/rspec/stubbed_mock.rb +2 -0
  35. data/lib/rubocop/cop/rspec/unspecified_exception.rb +2 -0
  36. data/lib/rubocop/cop/rspec_cops.rb +3 -0
  37. data/lib/rubocop/rspec/config_formatter.rb +2 -2
  38. data/lib/rubocop/rspec/description_extractor.rb +5 -10
  39. data/lib/rubocop/rspec/language.rb +9 -3
  40. data/lib/rubocop/rspec/shared_contexts/default_rspec_language_config_context.rb +29 -0
  41. data/lib/rubocop/rspec/version.rb +1 -1
  42. data/lib/rubocop-rspec.rb +18 -13
  43. metadata +7 -2
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: bbd70ea9708a7d87e0a1307234e3ac5cc37cc6197e6b1cc72487342b772ec6f1
4
- data.tar.gz: 0c50303e8a0d4218508c51e778d5cb6633b54fe6f823951ea5f8df68d162dfda
3
+ metadata.gz: c31ad963289938a78bf4a8439ad44c6f1a2eaf852a25d715be483ebe71e622fc
4
+ data.tar.gz: 70b4e942004dd6654fa12c3ecaf7367c1f6bcf4bcd122573129984f5f0a66ff5
5
5
  SHA512:
6
- metadata.gz: 2e1a6e55fb7aeef036448fe57f03b2d80b796e6971fbd22cd63db496e61b1e211a64e89e987cccc74f5124746713581fb621c805d458f7ff273d436432599483
7
- data.tar.gz: 76655025092f103fbd6ca3eda6d466236a8a9857f207e11bc3f8e51c38238367346971c4a0f3feeca6b9069a53fa48bf8281d5dff61f68c6562edce4405a10f0
6
+ metadata.gz: 250a68082a8e6406df3934035e5ccba4e1a7f9a13e021e196911c15981a2f4557e7b7a98efa93f995ad164d2a52e41bf948f4c1fa7c9637829c3c219c8116f74
7
+ data.tar.gz: 7ce965fc56bf214eb65b63d2138cc710766ac16b476a63399271cc5562fb259cefc81cddcf3878f6324faf104d6552e48efcba2eff1fa0865bf463963e5a1a8e
data/CHANGELOG.md CHANGED
@@ -2,6 +2,27 @@
2
2
 
3
3
  ## Master (Unreleased)
4
4
 
5
+ ## 2.16.0 (2022-12-13)
6
+
7
+ - Add new `RSpec/FactoryBot/FactoryNameStyle` cop. ([@ydah])
8
+ - Improved processing speed for `RSpec/Be`, `RSpec/ExpectActual`, `RSpec/ImplicitExpect`, `RSpec/MessageSpies`, `RSpec/PredicateMatcher` and `RSpec/Rails/HaveHttpStatus`. ([@ydah])
9
+ - Fix wrong autocorrection in `n_times` style on `RSpec/FactoryBot/CreateList`. ([@r7kamura])
10
+ - Fix a false positive for `RSpec/FactoryBot/ConsistentParenthesesStyle` when using `generate` with multiple arguments. ([@ydah])
11
+ - Mark `RSpec/BeEq` as `Safe: false` ([@r7kamura])
12
+ - Add `RSpec/DuplicatedMetadata` cop. ([@r7kamura])
13
+ - Mark `RSpec/BeEql` as `Safe: false`. ([@r7kamura])
14
+ - Add `RSpec/PendingWithoutReason` cop. ([@r7kamura])
15
+
16
+ ## 2.15.0 (2022-11-03)
17
+
18
+ - Fix a false positive for `RSpec/RepeatedDescription` when different its block expectations are used. ([@ydah])
19
+ - Add `named_only` style to `RSpec/NamedSubject`. ([@kuahyeow])
20
+ - Fix `RSpec/FactoryBot/ConsistentParenthesesStyle` to ignore calls without the first positional argument. ([@pirj])
21
+ - Fix `RSpec/FactoryBot/ConsistentParenthesesStyle` to ignore calls inside a Hash or an Array. ([@pirj])
22
+ - Fix `RSpec/NestedGroups` to correctly use `AllowedGroups` config. ([@samrjenkins])
23
+ - Remove `Runners` and `HookScopes` RSpec DSL elements from configuration. ([@pirj])
24
+ - Add `with default RSpec/Language config` helper to `lib` (under `rubocop/rspec/shared_contexts/default_rspec_language_config_context`), to allow use for downstream cops based on `RuboCop::Cop::RSpec::Base`. ([@smcgivern])
25
+
5
26
  ## 2.14.2 (2022-10-25)
6
27
 
7
28
  - Fix an incorrect autocorrect for `FactoryBot/ConsistentParenthesesStyle` with `omit_parentheses` option when method name and first argument are not on same line. ([@ydah])
@@ -724,6 +745,7 @@ Compatibility release so users can upgrade RuboCop to 0.51.0. No new features.
724
745
  [@jtannas]: https://github.com/jtannas
725
746
  [@kellysutton]: https://github.com/kellysutton
726
747
  [@koic]: https://github.com/koic
748
+ [@kuahyeow]: https://github.com/kuahyeow
727
749
  [@lazycoder9]: https://github.com/lazycoder9
728
750
  [@leoarnold]: https://github.com/leoarnold
729
751
  [@liberatys]: https://github.com/Liberatys
@@ -760,9 +782,11 @@ Compatibility release so users can upgrade RuboCop to 0.51.0. No new features.
760
782
  [@rrosenblum]: https://github.com/rrosenblum
761
783
  [@rspeicher]: https://github.com/rspeicher
762
784
  [@rst-j]: https://github.com/RST-J
785
+ [@samrjenkins]: https://github.com/samrjenkins
763
786
  [@schmijos]: https://github.com/schmijos
764
787
  [@seanpdoyle]: https://github.com/seanpdoyle
765
788
  [@sl4vr]: https://github.com/sl4vr
789
+ [@smcgivern]: https://github.com/smcgivern
766
790
  [@stephannv]: https://github.com/stephannv
767
791
  [@t3h2mas]: https://github.com/t3h2mas
768
792
  [@tdeo]: https://github.com/tdeo
data/config/default.yml CHANGED
@@ -12,8 +12,6 @@ RSpec:
12
12
  - Expectations
13
13
  - Helpers
14
14
  - Hooks
15
- - HookScopes
16
- - Runners
17
15
  - Subjects
18
16
  ExampleGroups:
19
17
  inherit_mode:
@@ -81,12 +79,6 @@ RSpec:
81
79
  - prepend_after
82
80
  - after
83
81
  - append_after
84
- HookScopes:
85
- - each
86
- - example
87
- - context
88
- - all
89
- - suite
90
82
  Includes:
91
83
  inherit_mode:
92
84
  merge:
@@ -98,10 +90,6 @@ RSpec:
98
90
  - include_examples
99
91
  Context:
100
92
  - include_context
101
- Runners:
102
- - to
103
- - to_not
104
- - not_to
105
93
  SharedGroups:
106
94
  inherit_mode:
107
95
  merge:
@@ -159,13 +147,17 @@ RSpec/Be:
159
147
  RSpec/BeEq:
160
148
  Description: Check for expectations where `be(...)` can replace `eq(...)`.
161
149
  Enabled: pending
150
+ Safe: false
162
151
  VersionAdded: 2.9.0
152
+ VersionChanged: '2.16'
163
153
  Reference: https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/BeEq
164
154
 
165
155
  RSpec/BeEql:
166
156
  Description: Check for expectations where `be(...)` can replace `eql(...)`.
167
157
  Enabled: true
158
+ Safe: false
168
159
  VersionAdded: '1.7'
160
+ VersionChanged: '2.16'
169
161
  Reference: https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/BeEql
170
162
 
171
163
  RSpec/BeNil:
@@ -296,6 +288,12 @@ RSpec/Dialect:
296
288
  VersionAdded: '1.33'
297
289
  Reference: https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/Dialect
298
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
+
299
297
  RSpec/EmptyExampleGroup:
300
298
  Description: Checks if an example group does not include any tests.
301
299
  Enabled: true
@@ -368,12 +366,6 @@ RSpec/ExampleWithoutDescription:
368
366
  VersionAdded: '1.22'
369
367
  Reference: https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/ExampleWithoutDescription
370
368
 
371
- RSpec/ExcessiveDocstringSpacing:
372
- Description: Checks for excessive whitespace in example descriptions.
373
- Enabled: pending
374
- VersionAdded: '2.5'
375
- Reference: https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/ExcessiveDocstringSpacing
376
-
377
369
  RSpec/ExampleWording:
378
370
  Description: Checks for common mistakes in example descriptions.
379
371
  Enabled: true
@@ -390,6 +382,12 @@ RSpec/ExampleWording:
390
382
  StyleGuide: https://rspec.rubystyle.guide/#should-in-example-docstrings
391
383
  Reference: https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/ExampleWording
392
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
+
393
391
  RSpec/ExpectActual:
394
392
  Description: Checks for `expect(...)` calls containing literal values.
395
393
  Enabled: true
@@ -624,8 +622,13 @@ RSpec/MultipleSubjects:
624
622
  RSpec/NamedSubject:
625
623
  Description: Checks for explicitly referenced test subjects.
626
624
  Enabled: true
625
+ EnforcedStyle: always
626
+ SupportedStyles:
627
+ - always
628
+ - named_only
627
629
  IgnoreSharedExamples: true
628
630
  VersionAdded: 1.5.3
631
+ VersionChanged: '2.15'
629
632
  StyleGuide: https://rspec.rubystyle.guide/#use-subject
630
633
  Reference: https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/NamedSubject
631
634
 
@@ -671,6 +674,12 @@ RSpec/Pending:
671
674
  VersionAdded: '1.25'
672
675
  Reference: https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/Pending
673
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
+
674
683
  RSpec/PredicateMatcher:
675
684
  Description: Prefer using predicate matcher over using predicate method directly.
676
685
  Enabled: true
@@ -967,6 +976,16 @@ RSpec/FactoryBot/FactoryClassName:
967
976
  VersionChanged: '2.0'
968
977
  Reference: https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/FactoryBot/FactoryClassName
969
978
 
979
+ RSpec/FactoryBot/FactoryNameStyle:
980
+ Description: Checks for name style for argument of FactoryBot::Syntax::Methods.
981
+ Enabled: pending
982
+ VersionAdded: '2.16'
983
+ EnforcedStyle: symbol
984
+ SupportedStyles:
985
+ - symbol
986
+ - string
987
+ Reference: https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/FactoryBot/FactoryNameStyle
988
+
970
989
  RSpec/FactoryBot/SyntaxMethods:
971
990
  Description: Use shorthands from `FactoryBot::Syntax::Methods` in your specs.
972
991
  Enabled: pending
@@ -992,6 +1011,17 @@ RSpec/Rails/HaveHttpStatus:
992
1011
  VersionAdded: '2.12'
993
1012
  Reference: https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/Rails/HaveHttpStatus
994
1013
 
1014
+ RSpec/Rails/HttpStatus:
1015
+ Description: Enforces use of symbolic or numeric value to describe HTTP status.
1016
+ Enabled: true
1017
+ EnforcedStyle: symbolic
1018
+ SupportedStyles:
1019
+ - numeric
1020
+ - symbolic
1021
+ VersionAdded: '1.23'
1022
+ VersionChanged: '2.0'
1023
+ Reference: https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/Rails/HttpStatus
1024
+
995
1025
  RSpec/Rails/InferredSpecType:
996
1026
  Description: Identifies redundant spec type.
997
1027
  Enabled: pending
@@ -1014,14 +1044,3 @@ RSpec/Rails/InferredSpecType:
1014
1044
  routing: routing
1015
1045
  system: system
1016
1046
  views: view
1017
-
1018
- RSpec/Rails/HttpStatus:
1019
- Description: Enforces use of symbolic or numeric value to describe HTTP status.
1020
- Enabled: true
1021
- EnforcedStyle: symbolic
1022
- SupportedStyles:
1023
- - numeric
1024
- - symbolic
1025
- VersionAdded: '1.23'
1026
- VersionChanged: '2.0'
1027
- Reference: https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/Rails/HttpStatus
@@ -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
 
@@ -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[
@@ -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
@@ -55,17 +55,22 @@ module RuboCop
55
55
 
56
56
  FACTORY_CALLS = RuboCop::RSpec::FactoryBot::Language::METHODS
57
57
 
58
+ RESTRICT_ON_SEND = FACTORY_CALLS
59
+
58
60
  # @!method factory_call(node)
59
61
  def_node_matcher :factory_call, <<-PATTERN
60
- (send
61
- ${#factory_bot? nil?} %FACTORY_CALLS
62
- $...)
62
+ (send
63
+ {#factory_bot? nil?} %FACTORY_CALLS
64
+ {sym str send lvar} _*
65
+ )
63
66
  PATTERN
64
67
 
65
68
  def on_send(node)
66
- return if nested_call?(node) # prevent from nested matching
69
+ return if ambiguous_without_parentheses?(node)
67
70
 
68
71
  factory_call(node) do
72
+ return if node.method?(:generate) && node.arguments.count > 1
73
+
69
74
  if node.parenthesized?
70
75
  process_with_parentheses(node)
71
76
  else
@@ -74,6 +79,8 @@ module RuboCop
74
79
  end
75
80
  end
76
81
 
82
+ private
83
+
77
84
  def process_with_parentheses(node)
78
85
  return unless style == :omit_parentheses
79
86
  return unless same_line?(node, node.first_argument)
@@ -93,12 +100,12 @@ module RuboCop
93
100
  end
94
101
  end
95
102
 
96
- def nested_call?(node)
97
- node.parent&.send_type?
103
+ def ambiguous_without_parentheses?(node)
104
+ node.parent&.send_type? ||
105
+ node.parent&.pair_type? ||
106
+ node.parent&.array_type?
98
107
  end
99
108
 
100
- private
101
-
102
109
  def remove_parentheses(corrector, node)
103
110
  corrector.replace(node.location.begin, ' ')
104
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 ...)