rubocop-rspec 2.24.1 → 2.26.0

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 (67) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +19 -0
  3. data/config/default.yml +19 -2
  4. data/lib/rubocop/cop/rspec/around_block.rb +3 -3
  5. data/lib/rubocop/cop/rspec/be.rb +1 -1
  6. data/lib/rubocop/cop/rspec/be_eq.rb +1 -1
  7. data/lib/rubocop/cop/rspec/be_eql.rb +1 -1
  8. data/lib/rubocop/cop/rspec/be_nil.rb +2 -2
  9. data/lib/rubocop/cop/rspec/before_after_all.rb +7 -13
  10. data/lib/rubocop/cop/rspec/capybara/feature_methods.rb +2 -2
  11. data/lib/rubocop/cop/rspec/change_by_zero.rb +3 -3
  12. data/lib/rubocop/cop/rspec/context_method.rb +2 -2
  13. data/lib/rubocop/cop/rspec/context_wording.rb +1 -1
  14. data/lib/rubocop/cop/rspec/describe_symbol.rb +1 -1
  15. data/lib/rubocop/cop/rspec/described_class.rb +5 -5
  16. data/lib/rubocop/cop/rspec/empty_example_group.rb +2 -2
  17. data/lib/rubocop/cop/rspec/empty_line_after_example.rb +2 -2
  18. data/lib/rubocop/cop/rspec/example_length.rb +11 -5
  19. data/lib/rubocop/cop/rspec/example_wording.rb +11 -2
  20. data/lib/rubocop/cop/rspec/excessive_docstring_spacing.rb +1 -1
  21. data/lib/rubocop/cop/rspec/expect_change.rb +2 -2
  22. data/lib/rubocop/cop/rspec/focus.rb +2 -2
  23. data/lib/rubocop/cop/rspec/hook_argument.rb +2 -2
  24. data/lib/rubocop/cop/rspec/hooks_before_examples.rb +1 -1
  25. data/lib/rubocop/cop/rspec/implicit_block_expectation.rb +2 -2
  26. data/lib/rubocop/cop/rspec/implicit_expect.rb +1 -1
  27. data/lib/rubocop/cop/rspec/implicit_subject.rb +2 -2
  28. data/lib/rubocop/cop/rspec/instance_spy.rb +2 -2
  29. data/lib/rubocop/cop/rspec/instance_variable.rb +2 -2
  30. data/lib/rubocop/cop/rspec/iterated_expectation.rb +3 -3
  31. data/lib/rubocop/cop/rspec/let_before_examples.rb +1 -1
  32. data/lib/rubocop/cop/rspec/let_setup.rb +1 -1
  33. data/lib/rubocop/cop/rspec/message_expectation.rb +1 -1
  34. data/lib/rubocop/cop/rspec/metadata_style.rb +5 -0
  35. data/lib/rubocop/cop/rspec/mixin/metadata.rb +3 -3
  36. data/lib/rubocop/cop/rspec/mixin/skip_or_pending.rb +2 -2
  37. data/lib/rubocop/cop/rspec/multiple_expectations.rb +2 -2
  38. data/lib/rubocop/cop/rspec/pending.rb +1 -1
  39. data/lib/rubocop/cop/rspec/pending_without_reason.rb +1 -1
  40. data/lib/rubocop/cop/rspec/predicate_matcher.rb +6 -6
  41. data/lib/rubocop/cop/rspec/rails/avoid_setup_hook.rb +1 -1
  42. data/lib/rubocop/cop/rspec/rails/have_http_status.rb +1 -1
  43. data/lib/rubocop/cop/rspec/rails/http_status.rb +13 -19
  44. data/lib/rubocop/cop/rspec/rails/minitest_assertions.rb +2 -2
  45. data/lib/rubocop/cop/rspec/receive_counts.rb +1 -1
  46. data/lib/rubocop/cop/rspec/receive_messages.rb +1 -1
  47. data/lib/rubocop/cop/rspec/redundant_predicate_matcher.rb +65 -0
  48. data/lib/rubocop/cop/rspec/remove_const.rb +40 -0
  49. data/lib/rubocop/cop/rspec/repeated_example_group_body.rb +1 -1
  50. data/lib/rubocop/cop/rspec/repeated_example_group_description.rb +2 -2
  51. data/lib/rubocop/cop/rspec/repeated_include_example.rb +1 -1
  52. data/lib/rubocop/cop/rspec/return_from_stub.rb +1 -1
  53. data/lib/rubocop/cop/rspec/shared_context.rb +1 -1
  54. data/lib/rubocop/cop/rspec/shared_examples.rb +63 -16
  55. data/lib/rubocop/cop/rspec/single_argument_message_chain.rb +1 -1
  56. data/lib/rubocop/cop/rspec/spec_file_path_format.rb +5 -5
  57. data/lib/rubocop/cop/rspec/stubbed_mock.rb +1 -1
  58. data/lib/rubocop/cop/rspec/subject_stub.rb +4 -4
  59. data/lib/rubocop/cop/rspec/unspecified_exception.rb +2 -2
  60. data/lib/rubocop/cop/rspec/variable_definition.rb +2 -2
  61. data/lib/rubocop/cop/rspec/verified_doubles.rb +1 -1
  62. data/lib/rubocop/cop/rspec/void_expect.rb +3 -3
  63. data/lib/rubocop/cop/rspec_cops.rb +2 -0
  64. data/lib/rubocop/rspec/language.rb +8 -8
  65. data/lib/rubocop/rspec/version.rb +1 -1
  66. data/lib/rubocop/rspec/wording.rb +8 -0
  67. metadata +10 -8
@@ -37,7 +37,7 @@ module RuboCop
37
37
  PATTERN
38
38
 
39
39
  # @!method let_bang(node)
40
- def_node_matcher :let_bang, <<-PATTERN
40
+ def_node_matcher :let_bang, <<~PATTERN
41
41
  {
42
42
  (block $(send nil? :let! {(sym $_) (str $_)}) ...)
43
43
  $(send nil? :let! {(sym $_) (str $_)} block_pass)
@@ -33,7 +33,7 @@ module RuboCop
33
33
  RESTRICT_ON_SEND = %i[to].freeze
34
34
 
35
35
  # @!method message_expectation(node)
36
- def_node_matcher :message_expectation, <<-PATTERN
36
+ def_node_matcher :message_expectation, <<~PATTERN
37
37
  (send $(send nil? {:expect :allow} ...) :to #receive_message?)
38
38
  PATTERN
39
39
 
@@ -45,6 +45,11 @@ module RuboCop
45
45
  PATTERN
46
46
 
47
47
  def on_metadata(symbols, hash)
48
+ # RSpec example groups accept two string arguments. In such a case,
49
+ # the rspec_metadata matcher will interpret the second string
50
+ # argument as a metadata symbol.
51
+ symbols.shift if symbols.first&.str_type?
52
+
48
53
  symbols.each do |symbol|
49
54
  on_metadata_symbol(symbol)
50
55
  end
@@ -30,12 +30,12 @@ module RuboCop
30
30
  def on_block(node)
31
31
  rspec_configure(node) do |block_var|
32
32
  metadata_in_block(node, block_var) do |metadata_arguments|
33
- on_matadata_arguments(metadata_arguments)
33
+ on_metadata_arguments(metadata_arguments)
34
34
  end
35
35
  end
36
36
 
37
37
  rspec_metadata(node) do |metadata_arguments|
38
- on_matadata_arguments(metadata_arguments)
38
+ on_metadata_arguments(metadata_arguments)
39
39
  end
40
40
  end
41
41
  alias on_numblock on_block
@@ -46,7 +46,7 @@ module RuboCop
46
46
 
47
47
  private
48
48
 
49
- def on_matadata_arguments(metadata_arguments)
49
+ def on_metadata_arguments(metadata_arguments)
50
50
  *symbols, last = metadata_arguments
51
51
  hash = nil
52
52
  case last&.type
@@ -8,7 +8,7 @@ module RuboCop
8
8
  extend RuboCop::NodePattern::Macros
9
9
 
10
10
  # @!method skipped_in_metadata?(node)
11
- def_node_matcher :skipped_in_metadata?, <<-PATTERN
11
+ def_node_matcher :skipped_in_metadata?, <<~PATTERN
12
12
  {
13
13
  (send _ _ <(sym {:skip :pending}) ...>)
14
14
  (send _ _ ... (hash <(pair (sym {:skip :pending}) { true str dstr }) ...>))
@@ -30,7 +30,7 @@ module RuboCop
30
30
  #
31
31
  # @param node [RuboCop::AST::Node]
32
32
  # @return [Array<RuboCop::AST::Node>] matching nodes
33
- def_node_matcher :skip_or_pending_inside_block?, <<-PATTERN
33
+ def_node_matcher :skip_or_pending_inside_block?, <<~PATTERN
34
34
  (block <(send nil? {:skip :pending} ...) ...>)
35
35
  PATTERN
36
36
  end
@@ -70,7 +70,7 @@ module RuboCop
70
70
  TRUE = ->(node) { node.true_type? }
71
71
 
72
72
  # @!method aggregate_failures?(node)
73
- def_node_matcher :aggregate_failures?, <<-PATTERN
73
+ def_node_matcher :aggregate_failures?, <<~PATTERN
74
74
  (block {
75
75
  (send _ _ <(sym :aggregate_failures) ...>)
76
76
  (send _ _ ... (hash <(pair (sym :aggregate_failures) %1) ...>))
@@ -81,7 +81,7 @@ module RuboCop
81
81
  def_node_matcher :expect?, '(send nil? #Expectations.all ...)'
82
82
 
83
83
  # @!method aggregate_failures_block?(node)
84
- def_node_matcher :aggregate_failures_block?, <<-PATTERN
84
+ def_node_matcher :aggregate_failures_block?, <<~PATTERN
85
85
  (block (send nil? :aggregate_failures ...) ...)
86
86
  PATTERN
87
87
 
@@ -67,7 +67,7 @@ module RuboCop
67
67
  private
68
68
 
69
69
  def skipped?(node)
70
- skippable?(node) && skipped_in_metadata?(node) ||
70
+ (skippable?(node) && skipped_in_metadata?(node)) ||
71
71
  skipped_regular_example_without_body?(node)
72
72
  end
73
73
 
@@ -103,7 +103,7 @@ module RuboCop
103
103
  on_pending_by_metadata(node)
104
104
  return unless (parent = parent_node(node))
105
105
 
106
- if example_group?(parent) || block_node_example_group?(node)
106
+ if spec_group?(parent) || block_node_example_group?(node)
107
107
  on_skipped_by_example_method(node)
108
108
  on_skipped_by_example_group_method(node)
109
109
  elsif example?(parent)
@@ -26,7 +26,7 @@ module RuboCop
26
26
  end
27
27
 
28
28
  # @!method predicate_in_actual?(node)
29
- def_node_matcher :predicate_in_actual?, <<-PATTERN
29
+ def_node_matcher :predicate_in_actual?, <<~PATTERN
30
30
  (send
31
31
  (send nil? :expect {
32
32
  (block $(send !nil? #predicate? ...) ...)
@@ -36,12 +36,12 @@ module RuboCop
36
36
  PATTERN
37
37
 
38
38
  # @!method be_bool?(node)
39
- def_node_matcher :be_bool?, <<-PATTERN
39
+ def_node_matcher :be_bool?, <<~PATTERN
40
40
  (send nil? {:be :eq :eql :equal} {true false})
41
41
  PATTERN
42
42
 
43
43
  # @!method be_boolthy?(node)
44
- def_node_matcher :be_boolthy?, <<-PATTERN
44
+ def_node_matcher :be_boolthy?, <<~PATTERN
45
45
  (send nil? {:be_truthy :be_falsey :be_falsy :a_truthy_value :a_falsey_value :a_falsy_value})
46
46
  PATTERN
47
47
 
@@ -179,7 +179,7 @@ module RuboCop
179
179
  end
180
180
 
181
181
  # @!method predicate_matcher?(node)
182
- def_node_matcher :predicate_matcher?, <<-PATTERN
182
+ def_node_matcher :predicate_matcher?, <<~PATTERN
183
183
  (send
184
184
  (send nil? :expect $!nil?)
185
185
  #Runners.all
@@ -188,7 +188,7 @@ module RuboCop
188
188
  PATTERN
189
189
 
190
190
  # @!method predicate_matcher_block?(node)
191
- def_node_matcher :predicate_matcher_block?, <<-PATTERN
191
+ def_node_matcher :predicate_matcher_block?, <<~PATTERN
192
192
  (block
193
193
  (send
194
194
  (send nil? :expect $!nil?)
@@ -202,7 +202,7 @@ module RuboCop
202
202
 
203
203
  return false if allowed_explicit_matchers.include?(name)
204
204
 
205
- name.start_with?('be_', 'have_') && !name.end_with?('?') ||
205
+ (name.start_with?('be_', 'have_') && !name.end_with?('?')) ||
206
206
  %w[include respond_to].include?(name)
207
207
  end
208
208
 
@@ -23,7 +23,7 @@ module RuboCop
23
23
  MSG = 'Use `before` instead of `setup`.'
24
24
 
25
25
  # @!method setup_call(node)
26
- def_node_matcher :setup_call, <<-PATTERN
26
+ def_node_matcher :setup_call, <<~PATTERN
27
27
  (block
28
28
  $(send nil? :setup)
29
29
  (args) _)
@@ -25,7 +25,7 @@ module RuboCop
25
25
  RESTRICT_ON_SEND = RUNNERS
26
26
 
27
27
  # @!method match_status(node)
28
- def_node_matcher :match_status, <<-PATTERN
28
+ def_node_matcher :match_status, <<~PATTERN
29
29
  (send
30
30
  (send nil? :expect
31
31
  $(send (send nil? :response) {:status :code})
@@ -60,12 +60,14 @@ module RuboCop
60
60
  RESTRICT_ON_SEND = %i[have_http_status].freeze
61
61
 
62
62
  # @!method http_status(node)
63
- def_node_matcher :http_status, <<-PATTERN
63
+ def_node_matcher :http_status, <<~PATTERN
64
64
  (send nil? :have_http_status ${int sym str})
65
65
  PATTERN
66
66
 
67
67
  def on_send(node)
68
68
  http_status(node) do |arg|
69
+ return if arg.str_type? && arg.heredoc?
70
+
69
71
  checker = checker_class.new(arg)
70
72
  return unless checker.offensive?
71
73
 
@@ -105,6 +107,10 @@ module RuboCop
105
107
  format(MSG, prefer: prefer, current: current)
106
108
  end
107
109
 
110
+ def current
111
+ offense_range.source
112
+ end
113
+
108
114
  def offense_range
109
115
  node
110
116
  end
@@ -129,10 +135,6 @@ module RuboCop
129
135
  symbol.inspect
130
136
  end
131
137
 
132
- def current
133
- node.value.inspect
134
- end
135
-
136
138
  private
137
139
 
138
140
  def symbol
@@ -140,7 +142,7 @@ module RuboCop
140
142
  end
141
143
 
142
144
  def number
143
- node.source.delete('"').to_i
145
+ node.value.to_i
144
146
  end
145
147
  end
146
148
 
@@ -154,10 +156,6 @@ module RuboCop
154
156
  number.to_s
155
157
  end
156
158
 
157
- def current
158
- symbol.inspect
159
- end
160
-
161
159
  private
162
160
 
163
161
  def symbol
@@ -190,10 +188,6 @@ module RuboCop
190
188
  end
191
189
  end
192
190
 
193
- def current
194
- offense_range.source
195
- end
196
-
197
191
  private
198
192
 
199
193
  def symbol
@@ -201,15 +195,15 @@ module RuboCop
201
195
  end
202
196
 
203
197
  def number
204
- node.source.to_i
198
+ node.value.to_i
205
199
  end
206
200
 
207
201
  def normalize_str
208
- normalized = node.source.delete('"')
209
- if normalized.match?(/\A\d+\z/)
210
- ::Rack::Utils::SYMBOL_TO_STATUS_CODE.key(normalized.to_i)
202
+ str = node.value.to_s
203
+ if str.match?(/\A\d+\z/)
204
+ ::Rack::Utils::SYMBOL_TO_STATUS_CODE.key(str.to_i)
211
205
  else
212
- normalized
206
+ str
213
207
  end
214
208
  end
215
209
  end
@@ -24,8 +24,8 @@ module RuboCop
24
24
  RESTRICT_ON_SEND = %i[assert_equal refute_equal].freeze
25
25
 
26
26
  # @!method minitest_assertion(node)
27
- def_node_matcher :minitest_assertion, <<-PATTERN
28
- (send nil? {:assert_equal :refute_equal} $_ $_ $_?)
27
+ def_node_matcher :minitest_assertion, <<~PATTERN
28
+ (send nil? {:assert_equal :refute_equal} $_ $_ $_?)
29
29
  PATTERN
30
30
 
31
31
  def on_send(node)
@@ -30,7 +30,7 @@ module RuboCop
30
30
  RESTRICT_ON_SEND = %i[times].freeze
31
31
 
32
32
  # @!method receive_counts(node)
33
- def_node_matcher :receive_counts, <<-PATTERN
33
+ def_node_matcher :receive_counts, <<~PATTERN
34
34
  (send $(send _ {:exactly :at_least :at_most} (int {1 2})) :times)
35
35
  PATTERN
36
36
 
@@ -148,7 +148,7 @@ module RuboCop
148
148
  end
149
149
 
150
150
  def heredoc_or_splat?(node)
151
- (node.str_type? || node.dstr_type?) && node.heredoc? ||
151
+ ((node.str_type? || node.dstr_type?) && node.heredoc?) ||
152
152
  node.splat_type?
153
153
  end
154
154
 
@@ -0,0 +1,65 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RuboCop
4
+ module Cop
5
+ module RSpec
6
+ # Checks for redundant predicate matcher.
7
+ #
8
+ # @example
9
+ # # bad
10
+ # expect(foo).to be_exist(bar)
11
+ # expect(foo).not_to be_include(bar)
12
+ #
13
+ # # good
14
+ # expect(foo).to exist(bar)
15
+ # expect(foo).not_to include(bar)
16
+ #
17
+ class RedundantPredicateMatcher < Base
18
+ extend AutoCorrector
19
+
20
+ MSG = 'Use `%<good>s` instead of `%<bad>s`.'
21
+ RESTRICT_ON_SEND =
22
+ %i[be_all be_cover be_end_with be_eql be_equal
23
+ be_exist be_exists be_include be_match
24
+ be_respond_to be_start_with].freeze
25
+
26
+ def on_send(node)
27
+ return if node.parent.block_type? || node.arguments.empty?
28
+ return unless replacable_arguments?(node)
29
+
30
+ method_name = node.method_name.to_s
31
+ replaced = replaced_method_name(method_name)
32
+ add_offense(node, message: message(method_name,
33
+ replaced)) do |corrector|
34
+ unless node.method?(:be_all)
35
+ corrector.replace(node.loc.selector, replaced)
36
+ end
37
+ end
38
+ end
39
+
40
+ private
41
+
42
+ def message(bad_method, good_method)
43
+ format(MSG, bad: bad_method, good: good_method)
44
+ end
45
+
46
+ def replacable_arguments?(node)
47
+ if node.method?(:be_all)
48
+ node.first_argument.send_type?
49
+ else
50
+ true
51
+ end
52
+ end
53
+
54
+ def replaced_method_name(method_name)
55
+ name = method_name.to_s.delete_prefix('be_')
56
+ if name == 'exists'
57
+ 'exist'
58
+ else
59
+ name
60
+ end
61
+ end
62
+ end
63
+ end
64
+ end
65
+ end
@@ -0,0 +1,40 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RuboCop
4
+ module Cop
5
+ module RSpec
6
+ # Checks that `remove_const` is not used in specs.
7
+ #
8
+ # @example
9
+ # # bad
10
+ # it 'does something' do
11
+ # Object.send(:remove_const, :SomeConstant)
12
+ # end
13
+ #
14
+ # before do
15
+ # SomeClass.send(:remove_const, :SomeConstant)
16
+ # end
17
+ #
18
+ class RemoveConst < Base
19
+ include RuboCop::RSpec::Language
20
+ extend RuboCop::RSpec::Language::NodePattern
21
+
22
+ MSG = 'Do not use remove_const in specs. ' \
23
+ 'Consider using e.g. `stub_const`.'
24
+ RESTRICT_ON_SEND = %i[send __send__].freeze
25
+
26
+ # @!method remove_const(node)
27
+ def_node_matcher :remove_const, <<~PATTERN
28
+ (send _ {:send | :__send__} (sym :remove_const) _)
29
+ PATTERN
30
+
31
+ # Check for offenses
32
+ def on_send(node)
33
+ remove_const(node) do
34
+ add_offense(node)
35
+ end
36
+ end
37
+ end
38
+ end
39
+ end
40
+ end
@@ -48,7 +48,7 @@ module RuboCop
48
48
  MSG = 'Repeated %<group>s block body on line(s) %<loc>s'
49
49
 
50
50
  # @!method several_example_groups?(node)
51
- def_node_matcher :several_example_groups?, <<-PATTERN
51
+ def_node_matcher :several_example_groups?, <<~PATTERN
52
52
  (begin <#example_group_with_body? #example_group_with_body? ...>)
53
53
  PATTERN
54
54
 
@@ -48,12 +48,12 @@ module RuboCop
48
48
  MSG = 'Repeated %<group>s block description on line(s) %<loc>s'
49
49
 
50
50
  # @!method several_example_groups?(node)
51
- def_node_matcher :several_example_groups?, <<-PATTERN
51
+ def_node_matcher :several_example_groups?, <<~PATTERN
52
52
  (begin <#example_group? #example_group? ...>)
53
53
  PATTERN
54
54
 
55
55
  # @!method doc_string_and_metadata(node)
56
- def_node_matcher :doc_string_and_metadata, <<-PATTERN
56
+ def_node_matcher :doc_string_and_metadata, <<~PATTERN
57
57
  (block (send _ _ $_ $...) ...)
58
58
  PATTERN
59
59
 
@@ -50,7 +50,7 @@ module RuboCop
50
50
  'on line(s) %<repeat>s'
51
51
 
52
52
  # @!method several_include_examples?(node)
53
- def_node_matcher :several_include_examples?, <<-PATTERN
53
+ def_node_matcher :several_include_examples?, <<~PATTERN
54
54
  (begin <#include_examples? #include_examples? ...>)
55
55
  PATTERN
56
56
 
@@ -48,7 +48,7 @@ module RuboCop
48
48
  def_node_matcher :stub_with_block?, '(block #contains_stub? ...)'
49
49
 
50
50
  # @!method and_return_value(node)
51
- def_node_search :and_return_value, <<-PATTERN
51
+ def_node_search :and_return_value, <<~PATTERN
52
52
  $(send _ :and_return $(...))
53
53
  PATTERN
54
54
 
@@ -62,7 +62,7 @@ module RuboCop
62
62
  PATTERN
63
63
 
64
64
  # @!method context?(node)
65
- def_node_search :context?, <<-PATTERN
65
+ def_node_search :context?, <<~PATTERN
66
66
  (send nil?
67
67
  {#Subjects.all #Helpers.all #Includes.context #Hooks.all} ...
68
68
  )
@@ -3,9 +3,13 @@
3
3
  module RuboCop
4
4
  module Cop
5
5
  module RSpec
6
- # Enforces use of string to titleize shared examples.
6
+ # Checks for consistent style for shared example names.
7
7
  #
8
- # @example
8
+ # Enforces either `string` or `symbol` for shared example names.
9
+ #
10
+ # This cop can be configured using the `EnforcedStyle` option
11
+ #
12
+ # @example `EnforcedStyle: string` (default)
9
13
  # # bad
10
14
  # it_behaves_like :foo_bar_baz
11
15
  # it_should_behave_like :foo_bar_baz
@@ -20,8 +24,24 @@ module RuboCop
20
24
  # shared_examples_for 'foo bar baz'
21
25
  # include_examples 'foo bar baz'
22
26
  #
27
+ # @example `EnforcedStyle: symbol`
28
+ # # bad
29
+ # it_behaves_like 'foo bar baz'
30
+ # it_should_behave_like 'foo bar baz'
31
+ # shared_examples 'foo bar baz'
32
+ # shared_examples_for 'foo bar baz'
33
+ # include_examples 'foo bar baz'
34
+ #
35
+ # # good
36
+ # it_behaves_like :foo_bar_baz
37
+ # it_should_behave_like :foo_bar_baz
38
+ # shared_examples :foo_bar_baz
39
+ # shared_examples_for :foo_bar_baz
40
+ # include_examples :foo_bar_baz
41
+ #
23
42
  class SharedExamples < Base
24
43
  extend AutoCorrector
44
+ include ConfigurableEnforcedStyle
25
45
 
26
46
  # @!method shared_examples(node)
27
47
  def_node_matcher :shared_examples, <<~PATTERN
@@ -34,19 +54,37 @@ module RuboCop
34
54
  def on_send(node)
35
55
  shared_examples(node) do
36
56
  ast_node = node.first_argument
37
- next unless ast_node&.sym_type?
57
+ next unless offense?(ast_node)
38
58
 
39
- checker = Checker.new(ast_node)
40
- add_offense(checker.node, message: checker.message) do |corrector|
41
- corrector.replace(checker.node, checker.preferred_style)
59
+ checker = new_checker(ast_node)
60
+ add_offense(ast_node, message: checker.message) do |corrector|
61
+ corrector.replace(ast_node, checker.preferred_style)
42
62
  end
43
63
  end
44
64
  end
45
65
 
66
+ private
67
+
68
+ def offense?(ast_node)
69
+ if style == :symbol
70
+ ast_node.str_type?
71
+ else # string
72
+ ast_node.sym_type?
73
+ end
74
+ end
75
+
76
+ def new_checker(ast_node)
77
+ if style == :symbol
78
+ SymbolChecker.new(ast_node)
79
+ else # string
80
+ StringChecker.new(ast_node)
81
+ end
82
+ end
83
+
46
84
  # :nodoc:
47
- class Checker
85
+ class SymbolChecker
48
86
  MSG = 'Prefer %<prefer>s over `%<current>s` ' \
49
- 'to titleize shared examples.'
87
+ 'to symbolize shared examples.'
50
88
 
51
89
  attr_reader :node
52
90
 
@@ -55,22 +93,31 @@ module RuboCop
55
93
  end
56
94
 
57
95
  def message
58
- format(MSG, prefer: preferred_style, current: symbol.inspect)
96
+ format(MSG, prefer: preferred_style, current: node.value.inspect)
59
97
  end
60
98
 
61
99
  def preferred_style
62
- string = symbol.to_s.tr('_', ' ')
63
- wrap_with_single_quotes(string)
100
+ ":#{node.value.to_s.downcase.tr(' ', '_')}"
64
101
  end
102
+ end
103
+
104
+ # :nodoc:
105
+ class StringChecker
106
+ MSG = 'Prefer %<prefer>s over `%<current>s` ' \
107
+ 'to titleize shared examples.'
65
108
 
66
- private
109
+ attr_reader :node
67
110
 
68
- def symbol
69
- node.value
111
+ def initialize(node)
112
+ @node = node
70
113
  end
71
114
 
72
- def wrap_with_single_quotes(string)
73
- "'#{string}'"
115
+ def message
116
+ format(MSG, prefer: preferred_style, current: node.value.inspect)
117
+ end
118
+
119
+ def preferred_style
120
+ "'#{node.value.to_s.tr('_', ' ')}'"
74
121
  end
75
122
  end
76
123
  end
@@ -24,7 +24,7 @@ module RuboCop
24
24
  RESTRICT_ON_SEND = %i[receive_message_chain stub_chain].freeze
25
25
 
26
26
  # @!method message_chain(node)
27
- def_node_matcher :message_chain, <<-PATTERN
27
+ def_node_matcher :message_chain, <<~PATTERN
28
28
  (send _ {:receive_message_chain :stub_chain} $_)
29
29
  PATTERN
30
30
 
@@ -41,7 +41,7 @@ module RuboCop
41
41
 
42
42
  # @!method example_group_arguments(node)
43
43
  def_node_matcher :example_group_arguments, <<~PATTERN
44
- (block (send #rspec? #ExampleGroups.all $_ $...) ...)
44
+ (block $(send #rspec? #ExampleGroups.all $_ $...) ...)
45
45
  PATTERN
46
46
 
47
47
  # @!method metadata_key_value(node)
@@ -50,16 +50,16 @@ module RuboCop
50
50
  def on_top_level_example_group(node)
51
51
  return unless top_level_groups.one?
52
52
 
53
- example_group_arguments(node) do |class_name, arguments|
53
+ example_group_arguments(node) do |send_node, class_name, arguments|
54
54
  next if !class_name.const_type? || ignore_metadata?(arguments)
55
55
 
56
- ensure_correct_file_path(class_name, arguments)
56
+ ensure_correct_file_path(send_node, class_name, arguments)
57
57
  end
58
58
  end
59
59
 
60
60
  private
61
61
 
62
- def ensure_correct_file_path(class_name, arguments)
62
+ def ensure_correct_file_path(send_node, class_name, arguments)
63
63
  pattern = correct_path_pattern(class_name, arguments)
64
64
  return if filename_ends_with?(pattern)
65
65
 
@@ -67,7 +67,7 @@ module RuboCop
67
67
  # expression pattern to resemble a glob pattern for clearer error
68
68
  # messages.
69
69
  suffix = pattern.sub('.*', '*').sub('[^/]*', '*').sub('\.', '.')
70
- add_global_offense(format(MSG, suffix: suffix))
70
+ add_offense(send_node, message: format(MSG, suffix: suffix))
71
71
  end
72
72
 
73
73
  def ignore_metadata?(arguments)
@@ -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')