rubocop-rspec 2.16.0 → 2.24.1

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 (99) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +124 -9
  3. data/README.md +3 -3
  4. data/config/default.yml +145 -18
  5. data/config/obsoletion.yml +15 -0
  6. data/lib/rubocop/cop/rspec/be_empty.rb +44 -0
  7. data/lib/rubocop/cop/rspec/be_nil.rb +2 -2
  8. data/lib/rubocop/cop/rspec/capybara/current_path_expectation.rb +29 -115
  9. data/lib/rubocop/cop/rspec/capybara/match_style.rb +38 -0
  10. data/lib/rubocop/cop/rspec/capybara/negation_matcher.rb +23 -96
  11. data/lib/rubocop/cop/rspec/capybara/specific_actions.rb +19 -75
  12. data/lib/rubocop/cop/rspec/capybara/specific_finders.rb +14 -83
  13. data/lib/rubocop/cop/rspec/capybara/specific_matcher.rb +25 -69
  14. data/lib/rubocop/cop/rspec/capybara/visibility_matcher.rb +26 -63
  15. data/lib/rubocop/cop/rspec/change_by_zero.rb +33 -23
  16. data/lib/rubocop/cop/rspec/contain_exactly.rb +56 -0
  17. data/lib/rubocop/cop/rspec/context_method.rb +5 -1
  18. data/lib/rubocop/cop/rspec/context_wording.rb +13 -6
  19. data/lib/rubocop/cop/rspec/describe_method.rb +16 -8
  20. data/lib/rubocop/cop/rspec/described_class.rb +2 -1
  21. data/lib/rubocop/cop/rspec/described_class_module_wrapping.rb +7 -5
  22. data/lib/rubocop/cop/rspec/dialect.rb +1 -1
  23. data/lib/rubocop/cop/rspec/duplicated_metadata.rb +2 -2
  24. data/lib/rubocop/cop/rspec/empty_example_group.rb +10 -7
  25. data/lib/rubocop/cop/rspec/empty_hook.rb +2 -2
  26. data/lib/rubocop/cop/rspec/empty_line_after_example_group.rb +1 -1
  27. data/lib/rubocop/cop/rspec/empty_metadata.rb +46 -0
  28. data/lib/rubocop/cop/rspec/eq.rb +47 -0
  29. data/lib/rubocop/cop/rspec/example_wording.rb +1 -1
  30. data/lib/rubocop/cop/rspec/excessive_docstring_spacing.rb +14 -5
  31. data/lib/rubocop/cop/rspec/expect_actual.rb +4 -4
  32. data/lib/rubocop/cop/rspec/expect_in_hook.rb +1 -1
  33. data/lib/rubocop/cop/rspec/factory_bot/attribute_defined_statically.rb +25 -118
  34. data/lib/rubocop/cop/rspec/factory_bot/consistent_parentheses_style.rb +40 -107
  35. data/lib/rubocop/cop/rspec/factory_bot/create_list.rb +30 -250
  36. data/lib/rubocop/cop/rspec/factory_bot/factory_class_name.rb +19 -46
  37. data/lib/rubocop/cop/rspec/factory_bot/factory_name_style.rb +23 -64
  38. data/lib/rubocop/cop/rspec/factory_bot/syntax_methods.rb +45 -79
  39. data/lib/rubocop/cop/rspec/file_path.rb +8 -2
  40. data/lib/rubocop/cop/rspec/focus.rb +19 -5
  41. data/lib/rubocop/cop/rspec/hook_argument.rb +12 -9
  42. data/lib/rubocop/cop/rspec/hooks_before_examples.rb +5 -3
  43. data/lib/rubocop/cop/rspec/indexed_let.rb +112 -0
  44. data/lib/rubocop/cop/rspec/instance_variable.rb +1 -1
  45. data/lib/rubocop/cop/rspec/leaky_constant_declaration.rb +1 -1
  46. data/lib/rubocop/cop/rspec/let_before_examples.rb +8 -4
  47. data/lib/rubocop/cop/rspec/let_setup.rb +6 -8
  48. data/lib/rubocop/cop/rspec/match_array.rb +59 -0
  49. data/lib/rubocop/cop/rspec/metadata_style.rb +197 -0
  50. data/lib/rubocop/cop/rspec/mixin/empty_line_separation.rb +1 -2
  51. data/lib/rubocop/cop/rspec/mixin/file_help.rb +14 -0
  52. data/lib/rubocop/cop/rspec/mixin/location_help.rb +37 -0
  53. data/lib/rubocop/cop/rspec/mixin/metadata.rb +21 -7
  54. data/lib/rubocop/cop/rspec/mixin/skip_or_pending.rb +20 -4
  55. data/lib/rubocop/cop/rspec/multiple_expectations.rb +2 -1
  56. data/lib/rubocop/cop/rspec/named_subject.rb +7 -5
  57. data/lib/rubocop/cop/rspec/no_expectation_example.rb +2 -5
  58. data/lib/rubocop/cop/rspec/overwriting_setup.rb +3 -1
  59. data/lib/rubocop/cop/rspec/pending.rb +23 -13
  60. data/lib/rubocop/cop/rspec/pending_without_reason.rb +72 -36
  61. data/lib/rubocop/cop/rspec/predicate_matcher.rb +49 -40
  62. data/lib/rubocop/cop/rspec/rails/have_http_status.rb +11 -6
  63. data/lib/rubocop/cop/rspec/rails/http_status.rb +107 -34
  64. data/lib/rubocop/cop/rspec/rails/inferred_spec_type.rb +4 -4
  65. data/lib/rubocop/cop/rspec/rails/minitest_assertions.rb +60 -0
  66. data/lib/rubocop/cop/rspec/rails/negation_be_valid.rb +102 -0
  67. data/lib/rubocop/cop/rspec/rails/travel_around.rb +92 -0
  68. data/lib/rubocop/cop/rspec/receive_counts.rb +1 -1
  69. data/lib/rubocop/cop/rspec/receive_messages.rb +161 -0
  70. data/lib/rubocop/cop/rspec/redundant_around.rb +65 -0
  71. data/lib/rubocop/cop/rspec/repeated_example_group_body.rb +3 -6
  72. data/lib/rubocop/cop/rspec/repeated_example_group_description.rb +3 -6
  73. data/lib/rubocop/cop/rspec/repeated_include_example.rb +3 -4
  74. data/lib/rubocop/cop/rspec/scattered_setup.rb +23 -6
  75. data/lib/rubocop/cop/rspec/shared_context.rb +12 -13
  76. data/lib/rubocop/cop/rspec/shared_examples.rb +6 -4
  77. data/lib/rubocop/cop/rspec/skip_block_inside_example.rb +46 -0
  78. data/lib/rubocop/cop/rspec/sort_metadata.rb +4 -3
  79. data/lib/rubocop/cop/rspec/spec_file_path_format.rb +133 -0
  80. data/lib/rubocop/cop/rspec/spec_file_path_suffix.rb +40 -0
  81. data/lib/rubocop/cop/rspec/stubbed_mock.rb +1 -1
  82. data/lib/rubocop/cop/rspec/subject_stub.rb +0 -1
  83. data/lib/rubocop/cop/rspec/variable_definition.rb +5 -2
  84. data/lib/rubocop/cop/rspec/variable_name.rb +4 -1
  85. data/lib/rubocop/cop/rspec/verified_double_reference.rb +7 -7
  86. data/lib/rubocop/cop/rspec/verified_doubles.rb +1 -1
  87. data/lib/rubocop/cop/rspec/void_expect.rb +2 -1
  88. data/lib/rubocop/cop/rspec_cops.rb +16 -0
  89. data/lib/rubocop/rspec/config_formatter.rb +16 -0
  90. data/lib/rubocop/rspec/example_group.rb +6 -8
  91. data/lib/rubocop/rspec/language/node_pattern.rb +26 -0
  92. data/lib/rubocop/rspec/language.rb +25 -16
  93. data/lib/rubocop/rspec/version.rb +1 -1
  94. data/lib/rubocop-rspec.rb +4 -5
  95. metadata +50 -8
  96. data/lib/rubocop/cop/rspec/mixin/capybara_help.rb +0 -80
  97. data/lib/rubocop/cop/rspec/mixin/css_selector.rb +0 -146
  98. data/lib/rubocop/rspec/factory_bot/language.rb +0 -37
  99. data/lib/rubocop/rspec/factory_bot.rb +0 -64
@@ -24,7 +24,7 @@ module RuboCop
24
24
  class ExpectActual < Base
25
25
  extend AutoCorrector
26
26
 
27
- MSG = 'Provide the actual you are testing to `expect(...)`.'
27
+ MSG = 'Provide the actual value you are testing to `expect(...)`.'
28
28
 
29
29
  RESTRICT_ON_SEND = Runners.all
30
30
 
@@ -77,7 +77,7 @@ module RuboCop
77
77
 
78
78
  private
79
79
 
80
- # This is not implement using a NodePattern because it seems
80
+ # This is not implemented using a NodePattern because it seems
81
81
  # to not be able to match against an explicit (nil) sexp
82
82
  def literal?(node)
83
83
  node && (simple_literal?(node) || complex_literal?(node))
@@ -93,8 +93,8 @@ module RuboCop
93
93
  end
94
94
 
95
95
  def swap(corrector, actual, expected)
96
- corrector.replace(actual.source_range, expected.source)
97
- corrector.replace(expected.source_range, actual.source)
96
+ corrector.replace(actual, expected.source)
97
+ corrector.replace(expected, actual.source)
98
98
  end
99
99
  end
100
100
  end
@@ -25,7 +25,7 @@ module RuboCop
25
25
  MSG = 'Do not use `%<expect>s` in `%<hook>s` hook'
26
26
 
27
27
  # @!method expectation(node)
28
- def_node_search :expectation, send_pattern('#Expectations.all')
28
+ def_node_search :expectation, '(send nil? #Expectations.all ...)'
29
29
 
30
30
  def on_block(node) # rubocop:disable InternalAffairs/NumblockHandler
31
31
  return unless hook?(node)
@@ -4,124 +4,31 @@ module RuboCop
4
4
  module Cop
5
5
  module RSpec
6
6
  module FactoryBot
7
- # Always declare attribute values as blocks.
8
- #
9
- # @example
10
- # # bad
11
- # kind [:active, :rejected].sample
12
- #
13
- # # good
14
- # kind { [:active, :rejected].sample }
15
- #
16
- # # bad
17
- # closed_at 1.day.from_now
18
- #
19
- # # good
20
- # closed_at { 1.day.from_now }
21
- #
22
- # # bad
23
- # count 1
24
- #
25
- # # good
26
- # count { 1 }
27
- #
28
- class AttributeDefinedStatically < ::RuboCop::Cop::Base
29
- extend AutoCorrector
30
-
31
- MSG = 'Use a block to declare attribute values.'
32
-
33
- # @!method value_matcher(node)
34
- def_node_matcher :value_matcher, <<-PATTERN
35
- (send _ !#reserved_method? $...)
36
- PATTERN
37
-
38
- # @!method factory_attributes(node)
39
- def_node_matcher :factory_attributes, <<-PATTERN
40
- (block (send _ #attribute_defining_method? ...) _ { (begin $...) $(send ...) } )
41
- PATTERN
42
-
43
- def on_block(node) # rubocop:disable InternalAffairs/NumblockHandler
44
- attributes = factory_attributes(node) || []
45
- attributes = [attributes] unless attributes.is_a?(Array) # rubocop:disable Style/ArrayCoercion, Lint/RedundantCopDisableDirective
46
-
47
- attributes.each do |attribute|
48
- next unless offensive_receiver?(attribute.receiver, node)
49
- next if proc?(attribute) || association?(attribute.first_argument)
50
-
51
- add_offense(attribute) do |corrector|
52
- autocorrect(corrector, attribute)
53
- end
54
- end
55
- end
56
-
57
- private
58
-
59
- def autocorrect(corrector, node)
60
- if node.parenthesized?
61
- autocorrect_replacing_parens(corrector, node)
62
- else
63
- autocorrect_without_parens(corrector, node)
64
- end
65
- end
66
-
67
- def offensive_receiver?(receiver, node)
68
- receiver.nil? ||
69
- receiver.self_type? ||
70
- receiver_matches_first_block_argument?(receiver, node)
71
- end
72
-
73
- def receiver_matches_first_block_argument?(receiver, node)
74
- first_block_argument = node.arguments.first
75
-
76
- !first_block_argument.nil? &&
77
- receiver.lvar_type? &&
78
- receiver.node_parts == first_block_argument.node_parts
79
- end
80
-
81
- def proc?(attribute)
82
- value_matcher(attribute).to_a.all?(&:block_pass_type?)
83
- end
84
-
85
- # @!method association?(node)
86
- def_node_matcher :association?, '(hash <(pair (sym :factory) _) ...>)'
87
-
88
- def autocorrect_replacing_parens(corrector, node)
89
- left_braces, right_braces = braces(node)
90
-
91
- corrector.replace(node.location.begin, " #{left_braces}")
92
- corrector.replace(node.location.end, right_braces)
93
- end
94
-
95
- def autocorrect_without_parens(corrector, node)
96
- left_braces, right_braces = braces(node)
97
-
98
- argument = node.first_argument
99
- expression = argument.location.expression
100
- corrector.insert_before(expression, left_braces)
101
- corrector.insert_after(expression, right_braces)
102
- end
103
-
104
- def braces(node)
105
- if value_hash_without_braces?(node.first_argument)
106
- ['{ { ', ' } }']
107
- else
108
- ['{ ', ' }']
109
- end
110
- end
111
-
112
- def value_hash_without_braces?(node)
113
- node.hash_type? && !node.braces?
114
- end
115
-
116
- def reserved_method?(method_name)
117
- RuboCop::RSpec::FactoryBot.reserved_methods.include?(method_name)
118
- end
119
-
120
- def attribute_defining_method?(method_name)
121
- RuboCop::RSpec::FactoryBot.attribute_defining_methods
122
- .include?(method_name)
123
- end
124
- end
7
+ # @!parse
8
+ # # Always declare attribute values as blocks.
9
+ # #
10
+ # # @example
11
+ # # # bad
12
+ # # kind [:active, :rejected].sample
13
+ # #
14
+ # # # good
15
+ # # kind { [:active, :rejected].sample }
16
+ # #
17
+ # # # bad
18
+ # # closed_at 1.day.from_now
19
+ # #
20
+ # # # good
21
+ # # closed_at { 1.day.from_now }
22
+ # #
23
+ # # # bad
24
+ # # count 1
25
+ # #
26
+ # # # good
27
+ # # count { 1 }
28
+ # #
29
+ # class AttributeDefinedStatically < ::RuboCop::Cop::Base; end
30
+ AttributeDefinedStatically =
31
+ ::RuboCop::Cop::FactoryBot::AttributeDefinedStatically
125
32
  end
126
33
  end
127
34
  end
@@ -4,113 +4,46 @@ module RuboCop
4
4
  module Cop
5
5
  module RSpec
6
6
  module FactoryBot
7
- # Use a consistent style for parentheses in factory bot calls.
8
- #
9
- # @example
10
- #
11
- # # bad
12
- # create :user
13
- # build(:user)
14
- # create(:login)
15
- # create :login
16
- #
17
- # @example `EnforcedStyle: require_parentheses` (default)
18
- #
19
- # # good
20
- # create(:user)
21
- # create(:user)
22
- # create(:login)
23
- # build(:login)
24
- #
25
- # @example `EnforcedStyle: omit_parentheses`
26
- #
27
- # # good
28
- # create :user
29
- # build :user
30
- # create :login
31
- # create :login
32
- #
33
- # # also good
34
- # # when method name and first argument are not on same line
35
- # create(
36
- # :user
37
- # )
38
- # build(
39
- # :user,
40
- # name: 'foo'
41
- # )
42
- #
43
- class ConsistentParenthesesStyle < ::RuboCop::Cop::Base
44
- extend AutoCorrector
45
- include ConfigurableEnforcedStyle
46
- include RuboCop::RSpec::FactoryBot::Language
47
- include RuboCop::Cop::Util
48
-
49
- def self.autocorrect_incompatible_with
50
- [Style::MethodCallWithArgsParentheses]
51
- end
52
-
53
- MSG_REQUIRE_PARENS = 'Prefer method call with parentheses'
54
- MSG_OMIT_PARENS = 'Prefer method call without parentheses'
55
-
56
- FACTORY_CALLS = RuboCop::RSpec::FactoryBot::Language::METHODS
57
-
58
- RESTRICT_ON_SEND = FACTORY_CALLS
59
-
60
- # @!method factory_call(node)
61
- def_node_matcher :factory_call, <<-PATTERN
62
- (send
63
- {#factory_bot? nil?} %FACTORY_CALLS
64
- {sym str send lvar} _*
65
- )
66
- PATTERN
67
-
68
- def on_send(node)
69
- return if ambiguous_without_parentheses?(node)
70
-
71
- factory_call(node) do
72
- return if node.method?(:generate) && node.arguments.count > 1
73
-
74
- if node.parenthesized?
75
- process_with_parentheses(node)
76
- else
77
- process_without_parentheses(node)
78
- end
79
- end
80
- end
81
-
82
- private
83
-
84
- def process_with_parentheses(node)
85
- return unless style == :omit_parentheses
86
- return unless same_line?(node, node.first_argument)
87
-
88
- add_offense(node.loc.selector,
89
- message: MSG_OMIT_PARENS) do |corrector|
90
- remove_parentheses(corrector, node)
91
- end
92
- end
93
-
94
- def process_without_parentheses(node)
95
- return unless style == :require_parentheses
96
-
97
- add_offense(node.loc.selector,
98
- message: MSG_REQUIRE_PARENS) do |corrector|
99
- add_parentheses(node, corrector)
100
- end
101
- end
102
-
103
- def ambiguous_without_parentheses?(node)
104
- node.parent&.send_type? ||
105
- node.parent&.pair_type? ||
106
- node.parent&.array_type?
107
- end
108
-
109
- def remove_parentheses(corrector, node)
110
- corrector.replace(node.location.begin, ' ')
111
- corrector.remove(node.location.end)
112
- end
113
- end
7
+ # @!parse
8
+ # # Use a consistent style for parentheses in factory bot calls.
9
+ # #
10
+ # # @example
11
+ # #
12
+ # # # bad
13
+ # # create :user
14
+ # # build(:user)
15
+ # # create(:login)
16
+ # # create :login
17
+ # #
18
+ # # @example `EnforcedStyle: require_parentheses` (default)
19
+ # #
20
+ # # # good
21
+ # # create(:user)
22
+ # # create(:user)
23
+ # # create(:login)
24
+ # # build(:login)
25
+ # #
26
+ # # @example `EnforcedStyle: omit_parentheses`
27
+ # #
28
+ # # # good
29
+ # # create :user
30
+ # # build :user
31
+ # # create :login
32
+ # # create :login
33
+ # #
34
+ # # # also good
35
+ # # # when method name and first argument are not on same line
36
+ # # create(
37
+ # # :user
38
+ # # )
39
+ # # build(
40
+ # # :user,
41
+ # # name: 'foo'
42
+ # # )
43
+ # #
44
+ # class ConsistentParenthesesStyle < ::RuboCop::Cop::Base; end
45
+ ConsistentParenthesesStyle =
46
+ ::RuboCop::Cop::FactoryBot::ConsistentParenthesesStyle
114
47
  end
115
48
  end
116
49
  end
@@ -4,256 +4,36 @@ module RuboCop
4
4
  module Cop
5
5
  module RSpec
6
6
  module FactoryBot
7
- # Checks for create_list usage.
8
- #
9
- # This cop can be configured using the `EnforcedStyle` option
10
- #
11
- # @example `EnforcedStyle: create_list` (default)
12
- # # bad
13
- # 3.times { create :user }
14
- #
15
- # # good
16
- # create_list :user, 3
17
- #
18
- # # bad
19
- # 3.times { create :user, age: 18 }
20
- #
21
- # # good - index is used to alter the created models attributes
22
- # 3.times { |n| create :user, age: n }
23
- #
24
- # # good - contains a method call, may return different values
25
- # 3.times { create :user, age: rand }
26
- #
27
- # @example `EnforcedStyle: n_times`
28
- # # bad
29
- # create_list :user, 3
30
- #
31
- # # good
32
- # 3.times { create :user }
33
- #
34
- class CreateList < ::RuboCop::Cop::Base
35
- extend AutoCorrector
36
- include ConfigurableEnforcedStyle
37
- include RuboCop::RSpec::FactoryBot::Language
38
-
39
- MSG_CREATE_LIST = 'Prefer create_list.'
40
- MSG_N_TIMES = 'Prefer %<number>s.times.'
41
- RESTRICT_ON_SEND = %i[create_list].freeze
42
-
43
- # @!method array_new_or_n_times_block?(node)
44
- def_node_matcher :array_new_or_n_times_block?, <<-PATTERN
45
- (block
46
- {
47
- (send (const {nil? | cbase} :Array) :new (int _)) |
48
- (send (int _) :times)
49
- }
50
- ...
51
- )
52
- PATTERN
53
-
54
- # @!method block_with_arg_and_used?(node)
55
- def_node_matcher :block_with_arg_and_used?, <<-PATTERN
56
- (block
57
- _
58
- (args (arg _value))
59
- `_value
60
- )
61
- PATTERN
62
-
63
- # @!method arguments_include_method_call?(node)
64
- def_node_matcher :arguments_include_method_call?, <<-PATTERN
65
- (send ${nil? #factory_bot?} :create (sym $_) `$(send ...))
66
- PATTERN
67
-
68
- # @!method factory_call(node)
69
- def_node_matcher :factory_call, <<-PATTERN
70
- (send ${nil? #factory_bot?} :create (sym $_) $...)
71
- PATTERN
72
-
73
- # @!method factory_list_call(node)
74
- def_node_matcher :factory_list_call, <<-PATTERN
75
- (send {nil? #factory_bot?} :create_list (sym _) (int $_) ...)
76
- PATTERN
77
-
78
- def on_block(node) # rubocop:todo InternalAffairs/NumblockHandler
79
- return unless style == :create_list
80
-
81
- return unless array_new_or_n_times_block?(node)
82
- return if block_with_arg_and_used?(node)
83
- return unless node.body
84
- return if arguments_include_method_call?(node.body)
85
- return unless contains_only_factory?(node.body)
86
-
87
- add_offense(node.send_node, message: MSG_CREATE_LIST) do |corrector|
88
- CreateListCorrector.new(node.send_node).call(corrector)
89
- end
90
- end
91
-
92
- def on_send(node)
93
- return unless style == :n_times
94
-
95
- factory_list_call(node) do |count|
96
- message = format(MSG_N_TIMES, number: count)
97
- add_offense(node.loc.selector, message: message) do |corrector|
98
- TimesCorrector.new(node).call(corrector)
99
- end
100
- end
101
- end
102
-
103
- private
104
-
105
- def contains_only_factory?(node)
106
- if node.block_type?
107
- factory_call(node.send_node)
108
- else
109
- factory_call(node)
110
- end
111
- end
112
-
113
- # :nodoc
114
- module Corrector
115
- private
116
-
117
- def build_options_string(options)
118
- options.map(&:source).join(', ')
119
- end
120
-
121
- def format_method_call(node, method, arguments)
122
- if node.block_type? || node.parenthesized?
123
- "#{method}(#{arguments})"
124
- else
125
- "#{method} #{arguments}"
126
- end
127
- end
128
-
129
- def format_receiver(receiver)
130
- return '' unless receiver
131
-
132
- "#{receiver.source}."
133
- end
134
- end
135
-
136
- # :nodoc
137
- class TimesCorrector
138
- include Corrector
139
-
140
- def initialize(node)
141
- @node = node
142
- end
143
-
144
- def call(corrector)
145
- replacement = generate_n_times_block(node)
146
- corrector.replace(node.block_node || node, replacement)
147
- end
148
-
149
- private
150
-
151
- attr_reader :node
152
-
153
- def generate_n_times_block(node)
154
- factory, count, *options = node.arguments
155
-
156
- arguments = factory.source
157
- options = build_options_string(options)
158
- arguments += ", #{options}" unless options.empty?
159
-
160
- replacement = format_receiver(node.receiver)
161
- replacement += format_method_call(node, 'create', arguments)
162
- replacement += " #{factory_call_block_source}" if node.block_node
163
- "#{count.source}.times { #{replacement} }"
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
171
- end
172
-
173
- # :nodoc:
174
- class CreateListCorrector
175
- include Corrector
176
-
177
- def initialize(node)
178
- @node = node.parent
179
- end
180
-
181
- def call(corrector)
182
- replacement = if node.body.block_type?
183
- call_with_block_replacement(node)
184
- else
185
- call_replacement(node)
186
- end
187
-
188
- corrector.replace(node, replacement)
189
- end
190
-
191
- private
192
-
193
- attr_reader :node
194
-
195
- def call_with_block_replacement(node)
196
- block = node.body
197
- arguments = build_arguments(block, count_from(node))
198
- replacement = format_receiver(block.receiver)
199
- replacement += format_method_call(block, 'create_list', arguments)
200
- replacement += format_block(block)
201
- replacement
202
- end
203
-
204
- def build_arguments(node, count)
205
- factory, *options = *node.send_node.arguments
206
-
207
- arguments = ":#{factory.value}, #{count}"
208
- options = build_options_string(options)
209
- arguments += ", #{options}" unless options.empty?
210
- arguments
211
- end
212
-
213
- def call_replacement(node)
214
- block = node.body
215
- factory, *options = *block.arguments
216
-
217
- arguments = "#{factory.source}, #{count_from(node)}"
218
- options = build_options_string(options)
219
- arguments += ", #{options}" unless options.empty?
220
-
221
- replacement = format_receiver(block.receiver)
222
- replacement += format_method_call(block, 'create_list', arguments)
223
- replacement
224
- end
225
-
226
- def count_from(node)
227
- count_node =
228
- if node.receiver.int_type?
229
- node.receiver
230
- else
231
- node.send_node.first_argument
232
- end
233
- count_node.source
234
- end
235
-
236
- def format_block(node)
237
- if node.body.begin_type?
238
- format_multiline_block(node)
239
- else
240
- format_singleline_block(node)
241
- end
242
- end
243
-
244
- def format_multiline_block(node)
245
- indent = ' ' * node.body.loc.column
246
- indent_end = ' ' * node.parent.loc.column
247
- " do #{node.arguments.source}\n" \
248
- "#{indent}#{node.body.source}\n" \
249
- "#{indent_end}end"
250
- end
251
-
252
- def format_singleline_block(node)
253
- " { #{node.arguments.source} #{node.body.source} }"
254
- end
255
- end
256
- end
7
+ # @!parse
8
+ # # Checks for create_list usage.
9
+ # #
10
+ # # This cop can be configured using the `EnforcedStyle` option
11
+ # #
12
+ # # @example `EnforcedStyle: create_list` (default)
13
+ # # # bad
14
+ # # 3.times { create :user }
15
+ # #
16
+ # # # good
17
+ # # create_list :user, 3
18
+ # #
19
+ # # # bad
20
+ # # 3.times { create :user, age: 18 }
21
+ # #
22
+ # # # good - index is used to alter the created models attributes
23
+ # # 3.times { |n| create :user, age: n }
24
+ # #
25
+ # # # good - contains a method call, may return different values
26
+ # # 3.times { create :user, age: rand }
27
+ # #
28
+ # # @example `EnforcedStyle: n_times`
29
+ # # # bad
30
+ # # create_list :user, 3
31
+ # #
32
+ # # # good
33
+ # # 3.times { create :user }
34
+ # #
35
+ # class CreateList < ::RuboCop::Cop::Base; end
36
+ CreateList = ::RuboCop::Cop::FactoryBot::CreateList
257
37
  end
258
38
  end
259
39
  end