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
@@ -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!