rubocop-rspec 2.21.0 → 3.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (123) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +147 -9
  3. data/README.md +2 -2
  4. data/config/default.yml +159 -244
  5. data/config/obsoletion.yml +24 -0
  6. data/lib/rubocop/cop/rspec/around_block.rb +3 -3
  7. data/lib/rubocop/cop/rspec/base.rb +0 -1
  8. data/lib/rubocop/cop/rspec/be.rb +1 -1
  9. data/lib/rubocop/cop/rspec/be_empty.rb +1 -0
  10. data/lib/rubocop/cop/rspec/be_eq.rb +1 -1
  11. data/lib/rubocop/cop/rspec/be_eql.rb +1 -1
  12. data/lib/rubocop/cop/rspec/be_nil.rb +2 -2
  13. data/lib/rubocop/cop/rspec/before_after_all.rb +7 -13
  14. data/lib/rubocop/cop/rspec/change_by_zero.rb +30 -4
  15. data/lib/rubocop/cop/rspec/context_method.rb +2 -2
  16. data/lib/rubocop/cop/rspec/context_wording.rb +1 -1
  17. data/lib/rubocop/cop/rspec/describe_symbol.rb +1 -1
  18. data/lib/rubocop/cop/rspec/described_class.rb +33 -11
  19. data/lib/rubocop/cop/rspec/dialect.rb +13 -0
  20. data/lib/rubocop/cop/rspec/duplicated_metadata.rb +1 -1
  21. data/lib/rubocop/cop/rspec/empty_example_group.rb +4 -1
  22. data/lib/rubocop/cop/rspec/empty_hook.rb +1 -1
  23. data/lib/rubocop/cop/rspec/empty_line_after_example.rb +2 -2
  24. data/lib/rubocop/cop/rspec/empty_metadata.rb +46 -0
  25. data/lib/rubocop/cop/rspec/empty_output.rb +47 -0
  26. data/lib/rubocop/cop/rspec/eq.rb +47 -0
  27. data/lib/rubocop/cop/rspec/example_length.rb +11 -5
  28. data/lib/rubocop/cop/rspec/example_without_description.rb +11 -2
  29. data/lib/rubocop/cop/rspec/example_wording.rb +11 -2
  30. data/lib/rubocop/cop/rspec/excessive_docstring_spacing.rb +14 -5
  31. data/lib/rubocop/cop/rspec/expect_actual.rb +17 -14
  32. data/lib/rubocop/cop/rspec/expect_change.rb +2 -2
  33. data/lib/rubocop/cop/rspec/expect_in_hook.rb +1 -1
  34. data/lib/rubocop/cop/rspec/expect_in_let.rb +42 -0
  35. data/lib/rubocop/cop/rspec/expect_output.rb +1 -4
  36. data/lib/rubocop/cop/rspec/focus.rb +17 -2
  37. data/lib/rubocop/cop/rspec/hook_argument.rb +2 -2
  38. data/lib/rubocop/cop/rspec/hooks_before_examples.rb +1 -1
  39. data/lib/rubocop/cop/rspec/implicit_block_expectation.rb +2 -2
  40. data/lib/rubocop/cop/rspec/implicit_expect.rb +1 -1
  41. data/lib/rubocop/cop/rspec/implicit_subject.rb +2 -2
  42. data/lib/rubocop/cop/rspec/indexed_let.rb +32 -1
  43. data/lib/rubocop/cop/rspec/instance_spy.rb +2 -2
  44. data/lib/rubocop/cop/rspec/instance_variable.rb +4 -4
  45. data/lib/rubocop/cop/rspec/is_expected_specify.rb +45 -0
  46. data/lib/rubocop/cop/rspec/iterated_expectation.rb +3 -3
  47. data/lib/rubocop/cop/rspec/leaky_constant_declaration.rb +2 -2
  48. data/lib/rubocop/cop/rspec/let_before_examples.rb +5 -1
  49. data/lib/rubocop/cop/rspec/let_setup.rb +1 -1
  50. data/lib/rubocop/cop/rspec/message_expectation.rb +1 -2
  51. data/lib/rubocop/cop/rspec/message_spies.rb +0 -2
  52. data/lib/rubocop/cop/rspec/metadata_style.rb +202 -0
  53. data/lib/rubocop/cop/rspec/missing_expectation_target_method.rb +54 -0
  54. data/lib/rubocop/cop/rspec/mixin/file_help.rb +14 -0
  55. data/lib/rubocop/cop/rspec/mixin/metadata.rb +21 -7
  56. data/lib/rubocop/cop/rspec/mixin/skip_or_pending.rb +2 -2
  57. data/lib/rubocop/cop/rspec/multiple_describes.rb +1 -1
  58. data/lib/rubocop/cop/rspec/multiple_expectations.rb +16 -11
  59. data/lib/rubocop/cop/rspec/multiple_memoized_helpers.rb +2 -4
  60. data/lib/rubocop/cop/rspec/named_subject.rb +6 -3
  61. data/lib/rubocop/cop/rspec/pending.rb +12 -2
  62. data/lib/rubocop/cop/rspec/pending_without_reason.rb +1 -1
  63. data/lib/rubocop/cop/rspec/predicate_matcher.rb +10 -10
  64. data/lib/rubocop/cop/rspec/receive_counts.rb +1 -1
  65. data/lib/rubocop/cop/rspec/receive_messages.rb +161 -0
  66. data/lib/rubocop/cop/rspec/redundant_predicate_matcher.rb +67 -0
  67. data/lib/rubocop/cop/rspec/remove_const.rb +39 -0
  68. data/lib/rubocop/cop/rspec/repeated_example.rb +6 -6
  69. data/lib/rubocop/cop/rspec/repeated_example_group_body.rb +1 -1
  70. data/lib/rubocop/cop/rspec/repeated_example_group_description.rb +2 -2
  71. data/lib/rubocop/cop/rspec/repeated_include_example.rb +1 -1
  72. data/lib/rubocop/cop/rspec/repeated_subject_call.rb +125 -0
  73. data/lib/rubocop/cop/rspec/return_from_stub.rb +1 -1
  74. data/lib/rubocop/cop/rspec/scattered_setup.rb +1 -1
  75. data/lib/rubocop/cop/rspec/shared_context.rb +1 -1
  76. data/lib/rubocop/cop/rspec/shared_examples.rb +66 -20
  77. data/lib/rubocop/cop/rspec/single_argument_message_chain.rb +2 -3
  78. data/lib/rubocop/cop/rspec/sort_metadata.rb +3 -2
  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 +4 -2
  82. data/lib/rubocop/cop/rspec/subject_stub.rb +6 -6
  83. data/lib/rubocop/cop/rspec/undescriptive_literals_description.rb +69 -0
  84. data/lib/rubocop/cop/rspec/unspecified_exception.rb +2 -2
  85. data/lib/rubocop/cop/rspec/variable_definition.rb +4 -4
  86. data/lib/rubocop/cop/rspec/verified_double_reference.rb +6 -6
  87. data/lib/rubocop/cop/rspec/verified_doubles.rb +2 -2
  88. data/lib/rubocop/cop/rspec/void_expect.rb +4 -3
  89. data/lib/rubocop/cop/rspec_cops.rb +14 -28
  90. data/lib/rubocop/rspec/concept.rb +0 -1
  91. data/lib/rubocop/rspec/config_formatter.rb +1 -11
  92. data/lib/rubocop/rspec/cop/generator.rb +25 -0
  93. data/lib/rubocop/rspec/language.rb +8 -9
  94. data/lib/rubocop/rspec/node.rb +1 -1
  95. data/lib/rubocop/rspec/shared_contexts/default_rspec_language_config_context.rb +1 -1
  96. data/lib/rubocop/rspec/version.rb +1 -1
  97. data/lib/rubocop/rspec/wording.rb +8 -0
  98. data/lib/rubocop-rspec.rb +2 -16
  99. metadata +27 -49
  100. data/lib/rubocop/cop/rspec/capybara/current_path_expectation.rb +0 -39
  101. data/lib/rubocop/cop/rspec/capybara/feature_methods.rb +0 -104
  102. data/lib/rubocop/cop/rspec/capybara/match_style.rb +0 -38
  103. data/lib/rubocop/cop/rspec/capybara/negation_matcher.rb +0 -33
  104. data/lib/rubocop/cop/rspec/capybara/specific_actions.rb +0 -29
  105. data/lib/rubocop/cop/rspec/capybara/specific_finders.rb +0 -24
  106. data/lib/rubocop/cop/rspec/capybara/specific_matcher.rb +0 -35
  107. data/lib/rubocop/cop/rspec/capybara/visibility_matcher.rb +0 -36
  108. data/lib/rubocop/cop/rspec/factory_bot/attribute_defined_statically.rb +0 -128
  109. data/lib/rubocop/cop/rspec/factory_bot/consistent_parentheses_style.rb +0 -117
  110. data/lib/rubocop/cop/rspec/factory_bot/create_list.rb +0 -260
  111. data/lib/rubocop/cop/rspec/factory_bot/factory_class_name.rb +0 -56
  112. data/lib/rubocop/cop/rspec/factory_bot/factory_name_style.rb +0 -74
  113. data/lib/rubocop/cop/rspec/factory_bot/syntax_methods.rb +0 -89
  114. data/lib/rubocop/cop/rspec/file_path.rb +0 -173
  115. data/lib/rubocop/cop/rspec/rails/avoid_setup_hook.rb +0 -43
  116. data/lib/rubocop/cop/rspec/rails/have_http_status.rb +0 -55
  117. data/lib/rubocop/cop/rspec/rails/http_status.rb +0 -203
  118. data/lib/rubocop/cop/rspec/rails/inferred_spec_type.rb +0 -145
  119. data/lib/rubocop/cop/rspec/rails/minitest_assertions.rb +0 -60
  120. data/lib/rubocop/cop/rspec/rails/travel_around.rb +0 -92
  121. data/lib/rubocop/rspec/factory_bot/language.rb +0 -37
  122. data/lib/rubocop/rspec/factory_bot.rb +0 -64
  123. data/lib/rubocop/rspec/language/node_pattern.rb +0 -48
@@ -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 |send_node, class_name, arguments|
54
+ next if !class_name.const_type? || ignore_metadata?(arguments)
55
+
56
+ ensure_correct_file_path(send_node, class_name, arguments)
57
+ end
58
+ end
59
+
60
+ private
61
+
62
+ def ensure_correct_file_path(send_node, 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_offense(send_node, message: 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
@@ -31,7 +31,7 @@ module RuboCop
31
31
  #
32
32
  # @param node [RuboCop::AST::Node]
33
33
  # @return [Array<RuboCop::AST::Node>] matching nodes
34
- def_node_matcher :message_expectation?, <<-PATTERN
34
+ def_node_matcher :message_expectation?, <<~PATTERN
35
35
  {
36
36
  (send nil? { :receive :receive_message_chain } ...) # receive(:foo)
37
37
  (send (send nil? :receive ...) :with ...) # receive(:foo).with('bar')
@@ -136,7 +136,9 @@ module RuboCop
136
136
  RESTRICT_ON_SEND = %i[to].freeze
137
137
 
138
138
  def on_send(node)
139
- expectation(node, &method(:on_expectation))
139
+ expectation(node) do |expectation, method_name, matcher|
140
+ on_expectation(expectation, method_name, matcher)
141
+ end
140
142
  end
141
143
 
142
144
  private
@@ -68,7 +68,7 @@ module RuboCop
68
68
  # @param node [RuboCop::AST::Node]
69
69
  #
70
70
  # @yield [Symbol] subject name
71
- def_node_matcher :subject?, <<-PATTERN
71
+ def_node_matcher :subject?, <<~PATTERN
72
72
  (block
73
73
  (send nil?
74
74
  { #Subjects.all (sym $_) | $#Subjects.all }
@@ -77,7 +77,7 @@ module RuboCop
77
77
 
78
78
  # @!method let?(node)
79
79
  # Find a memoized helper
80
- def_node_matcher :let?, <<-PATTERN
80
+ def_node_matcher :let?, <<~PATTERN
81
81
  (block
82
82
  (send nil? :let (sym $_)
83
83
  ) args ...)
@@ -94,7 +94,7 @@ module RuboCop
94
94
  # expect(foo).to receive(:bar).with(1)
95
95
  # expect(foo).to receive(:bar).with(1).and_return(2)
96
96
  #
97
- def_node_matcher :message_expectation?, <<-PATTERN
97
+ def_node_matcher :message_expectation?, <<~PATTERN
98
98
  (send
99
99
  {
100
100
  (send nil? { :expect :allow } (send nil? %))
@@ -106,15 +106,15 @@ module RuboCop
106
106
  PATTERN
107
107
 
108
108
  # @!method message_expectation_matcher?(node)
109
- def_node_search :message_expectation_matcher?, <<-PATTERN
109
+ def_node_search :message_expectation_matcher?, <<~PATTERN
110
110
  (send nil? {
111
111
  :receive :receive_messages :receive_message_chain :have_received
112
112
  } ...)
113
113
  PATTERN
114
114
 
115
115
  def on_top_level_group(node)
116
- @explicit_subjects = find_all_explicit(node, &method(:subject?))
117
- @subject_overrides = find_all_explicit(node, &method(:let?))
116
+ @explicit_subjects = find_all_explicit(node) { |n| subject?(n) }
117
+ @subject_overrides = find_all_explicit(node) { |n| let?(n) }
118
118
 
119
119
  find_subject_expectations(node) do |stub|
120
120
  add_offense(stub)
@@ -0,0 +1,69 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RuboCop
4
+ module Cop
5
+ module RSpec
6
+ # Description should be descriptive.
7
+ #
8
+ # If example group or example contains only `execute string`, numbers
9
+ # and regular expressions, the description is not clear.
10
+ #
11
+ # @example
12
+ # # bad
13
+ # describe `time` do
14
+ # # ...
15
+ # end
16
+ #
17
+ # # bad
18
+ # context /when foo/ do
19
+ # # ...
20
+ # end
21
+ #
22
+ # # bad
23
+ # it 10000 do
24
+ # # ...
25
+ # end
26
+ #
27
+ # # good
28
+ # describe Foo do
29
+ # # ...
30
+ # end
31
+ #
32
+ # # good
33
+ # describe '#foo' do
34
+ # # ...
35
+ # end
36
+ #
37
+ # # good
38
+ # context "when #{foo} is bar" do
39
+ # # ...
40
+ # end
41
+ #
42
+ # # good
43
+ # it 'does something' do
44
+ # # ...
45
+ # end
46
+ #
47
+ class UndescriptiveLiteralsDescription < Base
48
+ MSG = 'Description should be descriptive.'
49
+
50
+ # @!method example_groups_or_example?(node)
51
+ def_node_matcher :example_groups_or_example?, <<~PATTERN
52
+ (block (send #rspec? {#ExampleGroups.all #Examples.all} $_) ...)
53
+ PATTERN
54
+
55
+ def on_block(node) # rubocop:disable InternalAffairs/NumblockHandler
56
+ example_groups_or_example?(node) do |arg|
57
+ add_offense(arg) if offense?(arg)
58
+ end
59
+ end
60
+
61
+ private
62
+
63
+ def offense?(node)
64
+ %i[xstr int regexp].include?(node.type)
65
+ end
66
+ end
67
+ end
68
+ end
69
+ end
@@ -35,7 +35,7 @@ module RuboCop
35
35
  RESTRICT_ON_SEND = %i[to].freeze
36
36
 
37
37
  # @!method empty_raise_error_or_exception(node)
38
- def_node_matcher :empty_raise_error_or_exception, <<-PATTERN
38
+ def_node_matcher :empty_raise_error_or_exception, <<~PATTERN
39
39
  (send
40
40
  (block
41
41
  (send nil? :expect) ...)
@@ -57,7 +57,7 @@ module RuboCop
57
57
  end
58
58
 
59
59
  def block_with_args?(node)
60
- return unless node&.block_type?
60
+ return false unless node&.block_type?
61
61
 
62
62
  node.arguments?
63
63
  end
@@ -35,7 +35,7 @@ module RuboCop
35
35
  return unless inside_example_group?(node)
36
36
 
37
37
  variable_definition?(node) do |variable|
38
- next unless style_violation?(variable)
38
+ next unless style_offense?(variable)
39
39
 
40
40
  add_offense(
41
41
  variable,
@@ -59,9 +59,9 @@ module RuboCop
59
59
  end
60
60
  end
61
61
 
62
- def style_violation?(variable)
63
- style == :symbols && string?(variable) ||
64
- style == :strings && symbol?(variable)
62
+ def style_offense?(variable)
63
+ (style == :symbols && string?(variable)) ||
64
+ (style == :strings && symbol?(variable))
65
65
  end
66
66
 
67
67
  def string?(node)
@@ -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`.
@@ -79,8 +79,8 @@ module RuboCop
79
79
  expression = class_reference.source_range
80
80
 
81
81
  add_offense(expression, message: message) do |corrector|
82
- violation = class_reference.source
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.gsub(/^['"]|['"]$/, '')
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
@@ -28,7 +28,7 @@ module RuboCop
28
28
  RESTRICT_ON_SEND = %i[double spy].freeze
29
29
 
30
30
  # @!method unverified_double(node)
31
- def_node_matcher :unverified_double, <<-PATTERN
31
+ def_node_matcher :unverified_double, <<~PATTERN
32
32
  {(send nil? {:double :spy} $...)}
33
33
  PATTERN
34
34
 
@@ -18,12 +18,12 @@ module RuboCop
18
18
  RESTRICT_ON_SEND = %i[expect].freeze
19
19
 
20
20
  # @!method expect?(node)
21
- def_node_matcher :expect?, <<-PATTERN
21
+ def_node_matcher :expect?, <<~PATTERN
22
22
  (send nil? :expect ...)
23
23
  PATTERN
24
24
 
25
25
  # @!method expect_block?(node)
26
- def_node_matcher :expect_block?, <<-PATTERN
26
+ def_node_matcher :expect_block?, <<~PATTERN
27
27
  (block #expect? (args) _body)
28
28
  PATTERN
29
29
 
@@ -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
+ parent.block_type? && parent.body == expect
55
56
  end
56
57
  end
57
58
  end
@@ -1,32 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require_relative 'rspec/capybara/current_path_expectation'
4
- require_relative 'rspec/capybara/feature_methods'
5
- require_relative 'rspec/capybara/match_style'
6
- require_relative 'rspec/capybara/negation_matcher'
7
- require_relative 'rspec/capybara/specific_actions'
8
- require_relative 'rspec/capybara/specific_finders'
9
- require_relative 'rspec/capybara/specific_matcher'
10
- require_relative 'rspec/capybara/visibility_matcher'
11
-
12
- require_relative 'rspec/factory_bot/attribute_defined_statically'
13
- require_relative 'rspec/factory_bot/consistent_parentheses_style'
14
- require_relative 'rspec/factory_bot/create_list'
15
- require_relative 'rspec/factory_bot/factory_class_name'
16
- require_relative 'rspec/factory_bot/factory_name_style'
17
- require_relative 'rspec/factory_bot/syntax_methods'
18
-
19
- require_relative 'rspec/rails/avoid_setup_hook'
20
- require_relative 'rspec/rails/have_http_status'
21
- begin
22
- require_relative 'rspec/rails/http_status'
23
- rescue LoadError
24
- # Rails/HttpStatus cannot be loaded if rack/utils is unavailable.
25
- end
26
- require_relative 'rspec/rails/inferred_spec_type'
27
- require_relative 'rspec/rails/minitest_assertions'
28
- require_relative 'rspec/rails/travel_around'
29
-
30
3
  require_relative 'rspec/align_left_let_brace'
31
4
  require_relative 'rspec/align_right_let_brace'
32
5
  require_relative 'rspec/any_instance'
@@ -56,6 +29,9 @@ require_relative 'rspec/empty_line_after_example_group'
56
29
  require_relative 'rspec/empty_line_after_final_let'
57
30
  require_relative 'rspec/empty_line_after_hook'
58
31
  require_relative 'rspec/empty_line_after_subject'
32
+ require_relative 'rspec/empty_metadata'
33
+ require_relative 'rspec/empty_output'
34
+ require_relative 'rspec/eq'
59
35
  require_relative 'rspec/example_length'
60
36
  require_relative 'rspec/example_without_description'
61
37
  require_relative 'rspec/example_wording'
@@ -63,8 +39,8 @@ require_relative 'rspec/excessive_docstring_spacing'
63
39
  require_relative 'rspec/expect_actual'
64
40
  require_relative 'rspec/expect_change'
65
41
  require_relative 'rspec/expect_in_hook'
42
+ require_relative 'rspec/expect_in_let'
66
43
  require_relative 'rspec/expect_output'
67
- require_relative 'rspec/file_path'
68
44
  require_relative 'rspec/focus'
69
45
  require_relative 'rspec/hook_argument'
70
46
  require_relative 'rspec/hooks_before_examples'
@@ -75,6 +51,7 @@ require_relative 'rspec/implicit_subject'
75
51
  require_relative 'rspec/indexed_let'
76
52
  require_relative 'rspec/instance_spy'
77
53
  require_relative 'rspec/instance_variable'
54
+ require_relative 'rspec/is_expected_specify'
78
55
  require_relative 'rspec/it_behaves_like'
79
56
  require_relative 'rspec/iterated_expectation'
80
57
  require_relative 'rspec/leading_subject'
@@ -85,7 +62,9 @@ require_relative 'rspec/match_array'
85
62
  require_relative 'rspec/message_chain'
86
63
  require_relative 'rspec/message_expectation'
87
64
  require_relative 'rspec/message_spies'
65
+ require_relative 'rspec/metadata_style'
88
66
  require_relative 'rspec/missing_example_group_argument'
67
+ require_relative 'rspec/missing_expectation_target_method'
89
68
  require_relative 'rspec/multiple_describes'
90
69
  require_relative 'rspec/multiple_expectations'
91
70
  require_relative 'rspec/multiple_memoized_helpers'
@@ -99,13 +78,17 @@ require_relative 'rspec/pending'
99
78
  require_relative 'rspec/pending_without_reason'
100
79
  require_relative 'rspec/predicate_matcher'
101
80
  require_relative 'rspec/receive_counts'
81
+ require_relative 'rspec/receive_messages'
102
82
  require_relative 'rspec/receive_never'
103
83
  require_relative 'rspec/redundant_around'
84
+ require_relative 'rspec/redundant_predicate_matcher'
85
+ require_relative 'rspec/remove_const'
104
86
  require_relative 'rspec/repeated_description'
105
87
  require_relative 'rspec/repeated_example'
106
88
  require_relative 'rspec/repeated_example_group_body'
107
89
  require_relative 'rspec/repeated_example_group_description'
108
90
  require_relative 'rspec/repeated_include_example'
91
+ require_relative 'rspec/repeated_subject_call'
109
92
  require_relative 'rspec/return_from_stub'
110
93
  require_relative 'rspec/scattered_let'
111
94
  require_relative 'rspec/scattered_setup'
@@ -114,9 +97,12 @@ require_relative 'rspec/shared_examples'
114
97
  require_relative 'rspec/single_argument_message_chain'
115
98
  require_relative 'rspec/skip_block_inside_example'
116
99
  require_relative 'rspec/sort_metadata'
100
+ require_relative 'rspec/spec_file_path_format'
101
+ require_relative 'rspec/spec_file_path_suffix'
117
102
  require_relative 'rspec/stubbed_mock'
118
103
  require_relative 'rspec/subject_declaration'
119
104
  require_relative 'rspec/subject_stub'
105
+ require_relative 'rspec/undescriptive_literals_description'
120
106
  require_relative 'rspec/unspecified_exception'
121
107
  require_relative 'rspec/variable_definition'
122
108
  require_relative 'rspec/variable_name'
@@ -5,7 +5,6 @@ module RuboCop
5
5
  # Wrapper for RSpec DSL methods
6
6
  class Concept
7
7
  extend RuboCop::NodePattern::Macros
8
- extend Language::NodePattern
9
8
  include Language
10
9
 
11
10
  def initialize(node)
@@ -7,16 +7,7 @@ module RuboCop
7
7
  # Builds a YAML config file from two config hashes
8
8
  class ConfigFormatter
9
9
  EXTENSION_ROOT_DEPARTMENT = %r{^(RSpec/)}.freeze
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
- )
10
+ SUBDEPARTMENTS = [].freeze
20
11
  AMENDMENTS = %(Metrics/BlockLength)
21
12
  COP_DOC_BASE_URL = 'https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/'
22
13
 
@@ -38,7 +29,6 @@ module RuboCop
38
29
  def unified_config
39
30
  cops.each_with_object(config.dup) do |cop, unified|
40
31
  next if SUBDEPARTMENTS.include?(cop) || AMENDMENTS.include?(cop)
41
- next if EXTRACTED_COPS.include?(cop)
42
32
 
43
33
  replace_nil(unified[cop])
44
34
  unified[cop].merge!(descriptions.fetch(cop))
@@ -0,0 +1,25 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RuboCop
4
+ module RSpec
5
+ module Cop
6
+ # Source and spec generator for new cops
7
+ #
8
+ # This generator will take a cop name and generate a source file
9
+ # and spec file when given a valid qualified cop name.
10
+ # @api private
11
+ class Generator < RuboCop::Cop::Generator
12
+ def todo
13
+ <<~TODO
14
+ Do 4 steps:
15
+ 1. Modify the description of #{badge} in config/default.yml
16
+ 2. Implement your new cop in the generated file!
17
+ 3. Add an entry about new cop to CHANGELOG.md
18
+ 4. Commit your new cop with a message such as
19
+ e.g. "Add new `#{badge}` cop"
20
+ TODO
21
+ end
22
+ end
23
+ end
24
+ end
25
+ end
@@ -13,7 +13,6 @@ module RuboCop
13
13
  # using the configured aliases.
14
14
  module Language
15
15
  extend RuboCop::NodePattern::Macros
16
- extend NodePattern
17
16
 
18
17
  class << self
19
18
  attr_accessor :config
@@ -42,7 +41,7 @@ module RuboCop
42
41
  PATTERN
43
42
 
44
43
  # @!method example_group_with_body?(node)
45
- def_node_matcher :example_group_with_body?, <<-PATTERN
44
+ def_node_matcher :example_group_with_body?, <<~PATTERN
46
45
  (block (send #rspec? #ExampleGroups.all ...) args !nil?)
47
46
  PATTERN
48
47
 
@@ -50,15 +49,15 @@ module RuboCop
50
49
  def_node_matcher :example?, '(block (send nil? #Examples.all ...) ...)'
51
50
 
52
51
  # @!method hook?(node)
53
- def_node_matcher :hook?, <<-PATTERN
54
- {
55
- (numblock (send nil? #Hooks.all ...) ...)
56
- (block (send nil? #Hooks.all ...) ...)
57
- }
52
+ def_node_matcher :hook?, <<~PATTERN
53
+ {
54
+ (numblock (send nil? #Hooks.all ...) ...)
55
+ (block (send nil? #Hooks.all ...) ...)
56
+ }
58
57
  PATTERN
59
58
 
60
59
  # @!method let?(node)
61
- def_node_matcher :let?, <<-PATTERN
60
+ def_node_matcher :let?, <<~PATTERN
62
61
  {
63
62
  (block (send nil? #Helpers.all ...) ...)
64
63
  (send nil? #Helpers.all _ block_pass)
@@ -66,7 +65,7 @@ module RuboCop
66
65
  PATTERN
67
66
 
68
67
  # @!method include?(node)
69
- def_node_matcher :include?, <<-PATTERN
68
+ def_node_matcher :include?, <<~PATTERN
70
69
  {
71
70
  (block (send nil? #Includes.all ...) ...)
72
71
  (send nil? #Includes.all ...)
@@ -9,7 +9,7 @@ module RuboCop
9
9
  def recursive_literal_or_const?
10
10
  case type
11
11
  when :begin, :pair, *AST::Node::COMPOSITE_LITERALS
12
- children.all?(&:recursive_literal_or_const?)
12
+ children.compact.all?(&:recursive_literal_or_const?)
13
13
  else
14
14
  literal? || const_type?
15
15
  end
@@ -21,7 +21,7 @@ RSpec.shared_context 'with default RSpec/Language config' do
21
21
  when Array
22
22
  object.map { |item| deep_dup(item) }
23
23
  when Hash
24
- object.transform_values(&method(:deep_dup))
24
+ object.transform_values { |value| deep_dup(value) }
25
25
  else
26
26
  object # only collections undergo modifications and need duping
27
27
  end
@@ -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.21.0'
7
+ STRING = '3.0.1'
8
8
  end
9
9
  end
10
10
  end