rubocop-rspec 2.16.0 → 2.24.1

Sign up to get free protection for your applications and to get access to all the features.
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
@@ -0,0 +1,133 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RuboCop
4
+ module Cop
5
+ module RSpec
6
+ # Checks that spec file paths are consistent and well-formed.
7
+ #
8
+ # @example
9
+ # # bad
10
+ # whatever_spec.rb # describe MyClass
11
+ # my_class_spec.rb # describe MyClass, '#method'
12
+ #
13
+ # # good
14
+ # my_class_spec.rb # describe MyClass
15
+ # my_class_method_spec.rb # describe MyClass, '#method'
16
+ # my_class/method_spec.rb # describe MyClass, '#method'
17
+ #
18
+ # @example `CustomTransform: {RuboCop=>rubocop, RSpec=>rspec}` (default)
19
+ # # good
20
+ # rubocop_spec.rb # describe RuboCop
21
+ # rspec_spec.rb # describe RSpec
22
+ #
23
+ # @example `IgnoreMethods: false` (default)
24
+ # # bad
25
+ # my_class_spec.rb # describe MyClass, '#method'
26
+ #
27
+ # @example `IgnoreMethods: true`
28
+ # # good
29
+ # my_class_spec.rb # describe MyClass, '#method'
30
+ #
31
+ # @example `IgnoreMetadata: {type=>routing}` (default)
32
+ # # good
33
+ # whatever_spec.rb # describe MyClass, type: :routing do; end
34
+ #
35
+ class SpecFilePathFormat < Base
36
+ include TopLevelGroup
37
+ include Namespace
38
+ include FileHelp
39
+
40
+ MSG = 'Spec path should end with `%<suffix>s`.'
41
+
42
+ # @!method example_group_arguments(node)
43
+ def_node_matcher :example_group_arguments, <<~PATTERN
44
+ (block (send #rspec? #ExampleGroups.all $_ $...) ...)
45
+ PATTERN
46
+
47
+ # @!method metadata_key_value(node)
48
+ def_node_search :metadata_key_value, '(pair (sym $_key) (sym $_value))'
49
+
50
+ def on_top_level_example_group(node)
51
+ return unless top_level_groups.one?
52
+
53
+ example_group_arguments(node) do |class_name, arguments|
54
+ next if !class_name.const_type? || ignore_metadata?(arguments)
55
+
56
+ ensure_correct_file_path(class_name, arguments)
57
+ end
58
+ end
59
+
60
+ private
61
+
62
+ def ensure_correct_file_path(class_name, arguments)
63
+ pattern = correct_path_pattern(class_name, arguments)
64
+ return if filename_ends_with?(pattern)
65
+
66
+ # For the suffix shown in the offense message, modify the regular
67
+ # expression pattern to resemble a glob pattern for clearer error
68
+ # messages.
69
+ suffix = pattern.sub('.*', '*').sub('[^/]*', '*').sub('\.', '.')
70
+ add_global_offense(format(MSG, suffix: suffix))
71
+ end
72
+
73
+ def ignore_metadata?(arguments)
74
+ arguments.any? do |argument|
75
+ metadata_key_value(argument).any? do |key, value|
76
+ ignore_metadata.values_at(key.to_s).include?(value.to_s)
77
+ end
78
+ end
79
+ end
80
+
81
+ def correct_path_pattern(class_name, arguments)
82
+ path = [expected_path(class_name)]
83
+ path << '.*' unless ignore?(arguments.first)
84
+ path << [name_pattern(arguments.first), '[^/]*_spec\.rb']
85
+ path.join
86
+ end
87
+
88
+ def name_pattern(method_name)
89
+ return if ignore?(method_name)
90
+
91
+ method_name.str_content.gsub(/\s/, '_').gsub(/\W/, '')
92
+ end
93
+
94
+ def ignore?(method_name)
95
+ !method_name&.str_type? || ignore_methods?
96
+ end
97
+
98
+ def expected_path(constant)
99
+ constants = namespace(constant) + constant.const_name.split('::')
100
+
101
+ File.join(
102
+ constants.map do |name|
103
+ custom_transform.fetch(name) { camel_to_snake_case(name) }
104
+ end
105
+ )
106
+ end
107
+
108
+ def camel_to_snake_case(string)
109
+ string
110
+ .gsub(/([^A-Z])([A-Z]+)/, '\1_\2')
111
+ .gsub(/([A-Z])([A-Z][^A-Z\d]+)/, '\1_\2')
112
+ .downcase
113
+ end
114
+
115
+ def custom_transform
116
+ cop_config.fetch('CustomTransform', {})
117
+ end
118
+
119
+ def ignore_methods?
120
+ cop_config['IgnoreMethods']
121
+ end
122
+
123
+ def ignore_metadata
124
+ cop_config.fetch('IgnoreMetadata', {})
125
+ end
126
+
127
+ def filename_ends_with?(pattern)
128
+ expanded_file_path.match?("#{pattern}$")
129
+ end
130
+ end
131
+ end
132
+ end
133
+ end
@@ -0,0 +1,40 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RuboCop
4
+ module Cop
5
+ module RSpec
6
+ # Checks that spec file paths suffix are consistent and well-formed.
7
+ #
8
+ # @example
9
+ # # bad
10
+ # my_class/foo_specorb.rb # describe MyClass
11
+ # spec/models/user.rb # describe User
12
+ # spec/models/user_specxrb # describe User
13
+ #
14
+ # # good
15
+ # my_class_spec.rb # describe MyClass
16
+ #
17
+ # # good - shared examples are allowed
18
+ # spec/models/user.rb # shared_examples_for 'foo'
19
+ #
20
+ class SpecFilePathSuffix < Base
21
+ include TopLevelGroup
22
+ include FileHelp
23
+
24
+ MSG = 'Spec path should end with `_spec.rb`.'
25
+
26
+ def on_top_level_example_group(node)
27
+ example_group?(node) do
28
+ add_global_offense(MSG) unless correct_path?
29
+ end
30
+ end
31
+
32
+ private
33
+
34
+ def correct_path?
35
+ expanded_file_path.end_with?('_spec.rb')
36
+ end
37
+ end
38
+ end
39
+ end
40
+ end
@@ -91,7 +91,7 @@ module RuboCop
91
91
  # @param node [RuboCop::AST::Node]
92
92
  # @yield [RuboCop::AST::Node] matcher
93
93
  def_node_matcher :matcher_with_return_block, <<~PATTERN
94
- (block #message_expectation? args _) # receive(:foo) { 'bar' }
94
+ (block #message_expectation? (args) _) # receive(:foo) { 'bar' }
95
95
  PATTERN
96
96
 
97
97
  # @!method matcher_with_hash(node)
@@ -12,7 +12,6 @@ module RuboCop
12
12
  #
13
13
  # @see https://robots.thoughtbot.com/don-t-stub-the-system-under-test
14
14
  # @see https://penelope.zone/2015/12/27/introducing-rspec-smells-and-where-to-find-them.html#smell-1-stubjec
15
- # @see https://github.com/rubocop-hq/rspec-style-guide#dont-stub-subject
16
15
  #
17
16
  # @example
18
17
  # # bad
@@ -27,12 +27,15 @@ module RuboCop
27
27
  extend AutoCorrector
28
28
  include ConfigurableEnforcedStyle
29
29
  include Variable
30
+ include InsideExampleGroup
30
31
 
31
32
  MSG = 'Use %<style>s for variable names.'
32
33
 
33
34
  def on_send(node)
35
+ return unless inside_example_group?(node)
36
+
34
37
  variable_definition?(node) do |variable|
35
- next unless style_violation?(variable)
38
+ next unless style_offense?(variable)
36
39
 
37
40
  add_offense(
38
41
  variable,
@@ -56,7 +59,7 @@ module RuboCop
56
59
  end
57
60
  end
58
61
 
59
- def style_violation?(variable)
62
+ def style_offense?(variable)
60
63
  style == :symbols && string?(variable) ||
61
64
  style == :strings && symbol?(variable)
62
65
  end
@@ -42,15 +42,18 @@ module RuboCop
42
42
  include ConfigurableNaming
43
43
  include AllowedPattern
44
44
  include Variable
45
+ include InsideExampleGroup
45
46
 
46
47
  MSG = 'Use %<style>s for variable names.'
47
48
 
48
49
  def on_send(node)
50
+ return unless inside_example_group?(node)
51
+
49
52
  variable_definition?(node) do |variable|
50
53
  return if variable.dstr_type? || variable.dsym_type?
51
54
  return if matches_allowed_pattern?(variable.value)
52
55
 
53
- check_name(node, variable.value, variable.loc.expression)
56
+ check_name(node, variable.value, variable.source_range)
54
57
  end
55
58
  end
56
59
 
@@ -7,7 +7,7 @@ module RuboCop
7
7
  #
8
8
  # Only investigates references that are one of the supported styles.
9
9
  #
10
- # @see https://relishapp.com/rspec/rspec-mocks/docs/verifying-doubles
10
+ # @see https://rspec.info/features/3-12/rspec-mocks/verifying-doubles
11
11
  #
12
12
  # This cop can be configured in your configuration using the
13
13
  # `EnforcedStyle` option and supports `--auto-gen-config`.
@@ -76,11 +76,11 @@ module RuboCop
76
76
  break correct_style_detected unless opposing_style?(class_reference)
77
77
 
78
78
  message = format(MSG, style: style)
79
- expression = class_reference.loc.expression
79
+ expression = class_reference.source_range
80
80
 
81
81
  add_offense(expression, message: message) do |corrector|
82
- violation = class_reference.children.last.to_s
83
- corrector.replace(expression, correct_style(violation))
82
+ offense = class_reference.source
83
+ corrector.replace(expression, correct_style(offense))
84
84
 
85
85
  opposite_style_detected
86
86
  end
@@ -98,11 +98,11 @@ module RuboCop
98
98
  class_reference_style != style
99
99
  end
100
100
 
101
- def correct_style(violation)
101
+ def correct_style(offense)
102
102
  if style == :string
103
- "'#{violation}'"
103
+ "'#{offense}'"
104
104
  else
105
- violation
105
+ offense.gsub(/^['"]|['"]$/, '')
106
106
  end
107
107
  end
108
108
  end
@@ -5,7 +5,7 @@ module RuboCop
5
5
  module RSpec
6
6
  # Prefer using verifying doubles over normal doubles.
7
7
  #
8
- # @see https://relishapp.com/rspec/rspec-mocks/docs/verifying-doubles
8
+ # @see https://rspec.info/features/3-12/rspec-mocks/verifying-doubles
9
9
  #
10
10
  # @example
11
11
  # # bad
@@ -51,7 +51,8 @@ module RuboCop
51
51
  parent = expect.parent
52
52
  return true unless parent
53
53
  return true if parent.begin_type?
54
- return true if parent.block_type? && parent.body == expect
54
+
55
+ true if parent.block_type? && parent.body == expect
55
56
  end
56
57
  end
57
58
  end
@@ -2,6 +2,7 @@
2
2
 
3
3
  require_relative 'rspec/capybara/current_path_expectation'
4
4
  require_relative 'rspec/capybara/feature_methods'
5
+ require_relative 'rspec/capybara/match_style'
5
6
  require_relative 'rspec/capybara/negation_matcher'
6
7
  require_relative 'rspec/capybara/specific_actions'
7
8
  require_relative 'rspec/capybara/specific_finders'
@@ -17,24 +18,29 @@ require_relative 'rspec/factory_bot/syntax_methods'
17
18
 
18
19
  require_relative 'rspec/rails/avoid_setup_hook'
19
20
  require_relative 'rspec/rails/have_http_status'
21
+ require_relative 'rspec/rails/negation_be_valid'
20
22
  begin
21
23
  require_relative 'rspec/rails/http_status'
22
24
  rescue LoadError
23
25
  # Rails/HttpStatus cannot be loaded if rack/utils is unavailable.
24
26
  end
25
27
  require_relative 'rspec/rails/inferred_spec_type'
28
+ require_relative 'rspec/rails/minitest_assertions'
29
+ require_relative 'rspec/rails/travel_around'
26
30
 
27
31
  require_relative 'rspec/align_left_let_brace'
28
32
  require_relative 'rspec/align_right_let_brace'
29
33
  require_relative 'rspec/any_instance'
30
34
  require_relative 'rspec/around_block'
31
35
  require_relative 'rspec/be'
36
+ require_relative 'rspec/be_empty'
32
37
  require_relative 'rspec/be_eq'
33
38
  require_relative 'rspec/be_eql'
34
39
  require_relative 'rspec/be_nil'
35
40
  require_relative 'rspec/before_after_all'
36
41
  require_relative 'rspec/change_by_zero'
37
42
  require_relative 'rspec/class_check'
43
+ require_relative 'rspec/contain_exactly'
38
44
  require_relative 'rspec/context_method'
39
45
  require_relative 'rspec/context_wording'
40
46
  require_relative 'rspec/describe_class'
@@ -51,6 +57,8 @@ require_relative 'rspec/empty_line_after_example_group'
51
57
  require_relative 'rspec/empty_line_after_final_let'
52
58
  require_relative 'rspec/empty_line_after_hook'
53
59
  require_relative 'rspec/empty_line_after_subject'
60
+ require_relative 'rspec/empty_metadata'
61
+ require_relative 'rspec/eq'
54
62
  require_relative 'rspec/example_length'
55
63
  require_relative 'rspec/example_without_description'
56
64
  require_relative 'rspec/example_wording'
@@ -67,6 +75,7 @@ require_relative 'rspec/identical_equality_assertion'
67
75
  require_relative 'rspec/implicit_block_expectation'
68
76
  require_relative 'rspec/implicit_expect'
69
77
  require_relative 'rspec/implicit_subject'
78
+ require_relative 'rspec/indexed_let'
70
79
  require_relative 'rspec/instance_spy'
71
80
  require_relative 'rspec/instance_variable'
72
81
  require_relative 'rspec/it_behaves_like'
@@ -75,9 +84,11 @@ require_relative 'rspec/leading_subject'
75
84
  require_relative 'rspec/leaky_constant_declaration'
76
85
  require_relative 'rspec/let_before_examples'
77
86
  require_relative 'rspec/let_setup'
87
+ require_relative 'rspec/match_array'
78
88
  require_relative 'rspec/message_chain'
79
89
  require_relative 'rspec/message_expectation'
80
90
  require_relative 'rspec/message_spies'
91
+ require_relative 'rspec/metadata_style'
81
92
  require_relative 'rspec/missing_example_group_argument'
82
93
  require_relative 'rspec/multiple_describes'
83
94
  require_relative 'rspec/multiple_expectations'
@@ -92,7 +103,9 @@ require_relative 'rspec/pending'
92
103
  require_relative 'rspec/pending_without_reason'
93
104
  require_relative 'rspec/predicate_matcher'
94
105
  require_relative 'rspec/receive_counts'
106
+ require_relative 'rspec/receive_messages'
95
107
  require_relative 'rspec/receive_never'
108
+ require_relative 'rspec/redundant_around'
96
109
  require_relative 'rspec/repeated_description'
97
110
  require_relative 'rspec/repeated_example'
98
111
  require_relative 'rspec/repeated_example_group_body'
@@ -104,7 +117,10 @@ require_relative 'rspec/scattered_setup'
104
117
  require_relative 'rspec/shared_context'
105
118
  require_relative 'rspec/shared_examples'
106
119
  require_relative 'rspec/single_argument_message_chain'
120
+ require_relative 'rspec/skip_block_inside_example'
107
121
  require_relative 'rspec/sort_metadata'
122
+ require_relative 'rspec/spec_file_path_format'
123
+ require_relative 'rspec/spec_file_path_suffix'
108
124
  require_relative 'rspec/stubbed_mock'
109
125
  require_relative 'rspec/subject_declaration'
110
126
  require_relative 'rspec/subject_stub'
@@ -8,6 +8,21 @@ module RuboCop
8
8
  class ConfigFormatter
9
9
  EXTENSION_ROOT_DEPARTMENT = %r{^(RSpec/)}.freeze
10
10
  SUBDEPARTMENTS = %(RSpec/Capybara RSpec/FactoryBot RSpec/Rails)
11
+ EXTRACTED_COPS = %(
12
+ RSpec/Capybara/CurrentPathExpectation
13
+ RSpec/Capybara/MatchStyle
14
+ RSpec/Capybara/NegationMatcher
15
+ RSpec/Capybara/SpecificActions
16
+ RSpec/Capybara/SpecificFinders
17
+ RSpec/Capybara/SpecificMatcher
18
+ RSpec/Capybara/VisibilityMatcher
19
+ RSpec/FactoryBot/AttributeDefinedStatically
20
+ RSpec/FactoryBot/ConsistentParenthesesStyle
21
+ RSpec/FactoryBot/CreateList
22
+ RSpec/FactoryBot/FactoryClassName
23
+ RSpec/FactoryBot/FactoryNameStyle
24
+ RSpec/FactoryBot/SyntaxMethods
25
+ )
11
26
  AMENDMENTS = %(Metrics/BlockLength)
12
27
  COP_DOC_BASE_URL = 'https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/'
13
28
 
@@ -29,6 +44,7 @@ module RuboCop
29
44
  def unified_config
30
45
  cops.each_with_object(config.dup) do |cop, unified|
31
46
  next if SUBDEPARTMENTS.include?(cop) || AMENDMENTS.include?(cop)
47
+ next if EXTRACTED_COPS.include?(cop)
32
48
 
33
49
  replace_nil(unified[cop])
34
50
  unified[cop].merge!(descriptions.fetch(cop))
@@ -10,14 +10,12 @@ module RuboCop
10
10
  #
11
11
  # Selectors which indicate that we should stop searching
12
12
  #
13
- def_node_matcher :scope_change?,
14
- block_pattern(<<~PATTERN)
15
- {
16
- #SharedGroups.all
17
- #ExampleGroups.all
18
- #Includes.all
19
- }
20
- PATTERN
13
+ def_node_matcher :scope_change?, <<~PATTERN
14
+ (block {
15
+ (send #rspec? {#SharedGroups.all #ExampleGroups.all} ...)
16
+ (send nil? #Includes.all ...)
17
+ } ...)
18
+ PATTERN
21
19
 
22
20
  def lets
23
21
  find_all_in_scope(node, :let?)
@@ -4,18 +4,44 @@ module RuboCop
4
4
  module RSpec
5
5
  module Language
6
6
  # Helper methods to detect RSpec DSL used with send and block
7
+ # @deprecated Prefer using Node Pattern directly
8
+ # Use `'(block (send nil? #Example.all ...) ...)'` instead of
9
+ # `block_pattern('#Example.all')`
7
10
  module NodePattern
11
+ # @deprecated Prefer using Node Pattern directly
8
12
  def send_pattern(string)
13
+ deprecation_warning __method__
9
14
  "(send #rspec? #{string} ...)"
10
15
  end
11
16
 
17
+ # @deprecated Prefer using Node Pattern directly
12
18
  def block_pattern(string)
19
+ deprecation_warning __method__
13
20
  "(block #{send_pattern(string)} ...)"
14
21
  end
15
22
 
23
+ # @deprecated Prefer using Node Pattern directly
16
24
  def numblock_pattern(string)
25
+ deprecation_warning __method__
17
26
  "(numblock #{send_pattern(string)} ...)"
18
27
  end
28
+
29
+ # @deprecated Prefer using Node Pattern directly
30
+ def block_or_numblock_pattern(string)
31
+ deprecation_warning __method__
32
+ "{#{block_pattern(string)} #{numblock_pattern(string)}}"
33
+ end
34
+
35
+ private
36
+
37
+ def deprecation_warning(method)
38
+ # Only warn in derived extensions' specs
39
+ return unless defined?(::RSpec)
40
+
41
+ Kernel.warn <<~MESSAGE, uplevel: 2
42
+ Usage of #{method} is deprecated. Use node pattern explicitly.
43
+ MESSAGE
44
+ end
19
45
  end
20
46
  end
21
47
  end
@@ -20,52 +20,61 @@ module RuboCop
20
20
  end
21
21
 
22
22
  # @!method rspec?(node)
23
- def_node_matcher :rspec?, '{(const {nil? cbase} :RSpec) nil?}'
23
+ def_node_matcher :rspec?, '{#explicit_rspec? nil?}'
24
+
25
+ # @!method explicit_rspec?(node)
26
+ def_node_matcher :explicit_rspec?, '(const {nil? cbase} :RSpec)'
24
27
 
25
28
  # @!method example_group?(node)
26
- def_node_matcher :example_group?, block_pattern('#ExampleGroups.all')
29
+ def_node_matcher :example_group?, <<~PATTERN
30
+ ({block numblock} (send #rspec? #ExampleGroups.all ...) ...)
31
+ PATTERN
27
32
 
28
33
  # @!method shared_group?(node)
29
- def_node_matcher :shared_group?, block_pattern('#SharedGroups.all')
34
+ def_node_matcher :shared_group?,
35
+ '(block (send #rspec? #SharedGroups.all ...) ...)'
30
36
 
31
37
  # @!method spec_group?(node)
32
- def_node_matcher :spec_group?,
33
- block_pattern('{#SharedGroups.all #ExampleGroups.all}')
38
+ def_node_matcher :spec_group?, <<~PATTERN
39
+ ({block numblock} (send #rspec?
40
+ {#SharedGroups.all #ExampleGroups.all}
41
+ ...) ...)
42
+ PATTERN
34
43
 
35
44
  # @!method example_group_with_body?(node)
36
45
  def_node_matcher :example_group_with_body?, <<-PATTERN
37
- (block #{send_pattern('#ExampleGroups.all')} args !nil?)
46
+ (block (send #rspec? #ExampleGroups.all ...) args !nil?)
38
47
  PATTERN
39
48
 
40
49
  # @!method example?(node)
41
- def_node_matcher :example?, block_pattern('#Examples.all')
50
+ def_node_matcher :example?, '(block (send nil? #Examples.all ...) ...)'
42
51
 
43
52
  # @!method hook?(node)
44
53
  def_node_matcher :hook?, <<-PATTERN
45
- {
46
- #{block_pattern('#Hooks.all')}
47
- #{numblock_pattern('#Hooks.all')}
48
- }
54
+ {
55
+ (numblock (send nil? #Hooks.all ...) ...)
56
+ (block (send nil? #Hooks.all ...) ...)
57
+ }
49
58
  PATTERN
50
59
 
51
60
  # @!method let?(node)
52
61
  def_node_matcher :let?, <<-PATTERN
53
62
  {
54
- #{block_pattern('#Helpers.all')}
55
- (send #rspec? #Helpers.all _ block_pass)
63
+ (block (send nil? #Helpers.all ...) ...)
64
+ (send nil? #Helpers.all _ block_pass)
56
65
  }
57
66
  PATTERN
58
67
 
59
68
  # @!method include?(node)
60
69
  def_node_matcher :include?, <<-PATTERN
61
70
  {
62
- #{send_pattern('#Includes.all')}
63
- #{block_pattern('#Includes.all')}
71
+ (block (send nil? #Includes.all ...) ...)
72
+ (send nil? #Includes.all ...)
64
73
  }
65
74
  PATTERN
66
75
 
67
76
  # @!method subject?(node)
68
- def_node_matcher :subject?, block_pattern('#Subjects.all')
77
+ def_node_matcher :subject?, '(block (send nil? #Subjects.all ...) ...)'
69
78
 
70
79
  module ExampleGroups # :nodoc:
71
80
  class << self
@@ -4,7 +4,7 @@ module RuboCop
4
4
  module RSpec
5
5
  # Version information for the RSpec RuboCop plugin.
6
6
  module Version
7
- STRING = '2.16.0'
7
+ STRING = '2.24.1'
8
8
  end
9
9
  end
10
10
  end
data/lib/rubocop-rspec.rb CHANGED
@@ -4,6 +4,8 @@ require 'pathname'
4
4
  require 'yaml'
5
5
 
6
6
  require 'rubocop'
7
+ require 'rubocop-capybara'
8
+ require 'rubocop-factory_bot'
7
9
 
8
10
  require_relative 'rubocop/rspec'
9
11
  require_relative 'rubocop/rspec/inject'
@@ -15,12 +17,10 @@ require_relative 'rubocop/rspec/wording'
15
17
  # Dependent on `RuboCop::RSpec::Language::NodePattern`.
16
18
  require_relative 'rubocop/rspec/language'
17
19
 
18
- require_relative 'rubocop/rspec/factory_bot/language'
19
-
20
- require_relative 'rubocop/cop/rspec/mixin/capybara_help'
21
- require_relative 'rubocop/cop/rspec/mixin/css_selector'
20
+ require_relative 'rubocop/cop/rspec/mixin/file_help'
22
21
  require_relative 'rubocop/cop/rspec/mixin/final_end_location'
23
22
  require_relative 'rubocop/cop/rspec/mixin/inside_example_group'
23
+ require_relative 'rubocop/cop/rspec/mixin/location_help'
24
24
  require_relative 'rubocop/cop/rspec/mixin/metadata'
25
25
  require_relative 'rubocop/cop/rspec/mixin/namespace'
26
26
  require_relative 'rubocop/cop/rspec/mixin/skip_or_pending'
@@ -37,7 +37,6 @@ require_relative 'rubocop/rspec/concept'
37
37
  require_relative 'rubocop/rspec/corrector/move_node'
38
38
  require_relative 'rubocop/rspec/example'
39
39
  require_relative 'rubocop/rspec/example_group'
40
- require_relative 'rubocop/rspec/factory_bot'
41
40
  require_relative 'rubocop/rspec/hook'
42
41
 
43
42
  RuboCop::RSpec::Inject.defaults!