rubocop-rspec 2.12.0 → 2.13.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 (103) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +118 -86
  3. data/config/default.yml +44 -6
  4. data/config/obsoletion.yml +14 -0
  5. data/lib/rubocop/cop/rspec/align_left_let_brace.rb +8 -9
  6. data/lib/rubocop/cop/rspec/align_right_let_brace.rb +8 -9
  7. data/lib/rubocop/cop/rspec/any_instance.rb +1 -0
  8. data/lib/rubocop/cop/rspec/around_block.rb +26 -3
  9. data/lib/rubocop/cop/rspec/be.rb +0 -1
  10. data/lib/rubocop/cop/rspec/be_eq.rb +0 -1
  11. data/lib/rubocop/cop/rspec/be_eql.rb +0 -1
  12. data/lib/rubocop/cop/rspec/before_after_all.rb +1 -0
  13. data/lib/rubocop/cop/rspec/capybara/current_path_expectation.rb +9 -3
  14. data/lib/rubocop/cop/rspec/capybara/feature_methods.rb +2 -1
  15. data/lib/rubocop/cop/rspec/capybara/specific_finders.rb +86 -0
  16. data/lib/rubocop/cop/rspec/capybara/specific_matcher.rb +91 -10
  17. data/lib/rubocop/cop/rspec/capybara/visibility_matcher.rb +0 -1
  18. data/lib/rubocop/cop/rspec/change_by_zero.rb +60 -5
  19. data/lib/rubocop/cop/rspec/class_check.rb +101 -0
  20. data/lib/rubocop/cop/rspec/context_method.rb +2 -1
  21. data/lib/rubocop/cop/rspec/context_wording.rb +49 -18
  22. data/lib/rubocop/cop/rspec/describe_class.rb +1 -1
  23. data/lib/rubocop/cop/rspec/describe_method.rb +1 -0
  24. data/lib/rubocop/cop/rspec/described_class.rb +4 -14
  25. data/lib/rubocop/cop/rspec/dialect.rb +1 -0
  26. data/lib/rubocop/cop/rspec/empty_example_group.rb +19 -4
  27. data/lib/rubocop/cop/rspec/empty_hook.rb +2 -1
  28. data/lib/rubocop/cop/rspec/empty_line_after_example.rb +4 -9
  29. data/lib/rubocop/cop/rspec/empty_line_after_example_group.rb +1 -1
  30. data/lib/rubocop/cop/rspec/empty_line_after_final_let.rb +2 -1
  31. data/lib/rubocop/cop/rspec/empty_line_after_hook.rb +32 -2
  32. data/lib/rubocop/cop/rspec/empty_line_after_subject.rb +2 -1
  33. data/lib/rubocop/cop/rspec/example_length.rb +2 -1
  34. data/lib/rubocop/cop/rspec/example_without_description.rb +2 -1
  35. data/lib/rubocop/cop/rspec/example_wording.rb +2 -1
  36. data/lib/rubocop/cop/rspec/excessive_docstring_spacing.rb +1 -0
  37. data/lib/rubocop/cop/rspec/expect_actual.rb +3 -0
  38. data/lib/rubocop/cop/rspec/expect_change.rb +1 -1
  39. data/lib/rubocop/cop/rspec/expect_in_hook.rb +4 -1
  40. data/lib/rubocop/cop/rspec/expect_output.rb +1 -0
  41. data/lib/rubocop/cop/rspec/factory_bot/attribute_defined_statically.rb +2 -1
  42. data/lib/rubocop/cop/rspec/factory_bot/create_list.rb +26 -12
  43. data/lib/rubocop/cop/rspec/factory_bot/factory_class_name.rb +1 -0
  44. data/lib/rubocop/cop/rspec/file_path.rb +6 -3
  45. data/lib/rubocop/cop/rspec/focus.rb +18 -0
  46. data/lib/rubocop/cop/rspec/hook_argument.rb +7 -2
  47. data/lib/rubocop/cop/rspec/hooks_before_examples.rb +10 -9
  48. data/lib/rubocop/cop/rspec/identical_equality_assertion.rb +0 -1
  49. data/lib/rubocop/cop/rspec/implicit_block_expectation.rb +1 -0
  50. data/lib/rubocop/cop/rspec/implicit_expect.rb +0 -2
  51. data/lib/rubocop/cop/rspec/instance_spy.rb +1 -1
  52. data/lib/rubocop/cop/rspec/instance_variable.rb +0 -1
  53. data/lib/rubocop/cop/rspec/it_behaves_like.rb +1 -0
  54. data/lib/rubocop/cop/rspec/iterated_expectation.rb +16 -0
  55. data/lib/rubocop/cop/rspec/leading_subject.rb +15 -15
  56. data/lib/rubocop/cop/rspec/let_before_examples.rb +7 -8
  57. data/lib/rubocop/cop/rspec/let_setup.rb +4 -4
  58. data/lib/rubocop/cop/rspec/message_chain.rb +1 -1
  59. data/lib/rubocop/cop/rspec/missing_example_group_argument.rb +2 -1
  60. data/lib/rubocop/cop/rspec/mixin/css_selector.rb +99 -0
  61. data/lib/rubocop/cop/rspec/mixin/namespace.rb +23 -0
  62. data/lib/rubocop/cop/rspec/multiple_describes.rb +1 -0
  63. data/lib/rubocop/cop/rspec/multiple_expectations.rb +1 -5
  64. data/lib/rubocop/cop/rspec/multiple_memoized_helpers.rb +1 -3
  65. data/lib/rubocop/cop/rspec/multiple_subjects.rb +17 -2
  66. data/lib/rubocop/cop/rspec/named_subject.rb +2 -1
  67. data/lib/rubocop/cop/rspec/nested_groups.rb +45 -25
  68. data/lib/rubocop/cop/rspec/no_expectation_example.rb +64 -0
  69. data/lib/rubocop/cop/rspec/not_to_not.rb +1 -2
  70. data/lib/rubocop/cop/rspec/overwriting_setup.rb +2 -1
  71. data/lib/rubocop/cop/rspec/pending.rb +1 -0
  72. data/lib/rubocop/cop/rspec/predicate_matcher.rb +2 -1
  73. data/lib/rubocop/cop/rspec/rails/avoid_setup_hook.rb +1 -2
  74. data/lib/rubocop/cop/rspec/receive_counts.rb +14 -15
  75. data/lib/rubocop/cop/rspec/receive_never.rb +4 -5
  76. data/lib/rubocop/cop/rspec/repeated_description.rb +25 -26
  77. data/lib/rubocop/cop/rspec/repeated_example.rb +1 -1
  78. data/lib/rubocop/cop/rspec/repeated_example_group_body.rb +28 -29
  79. data/lib/rubocop/cop/rspec/repeated_example_group_description.rb +28 -29
  80. data/lib/rubocop/cop/rspec/repeated_include_example.rb +32 -33
  81. data/lib/rubocop/cop/rspec/return_from_stub.rb +1 -1
  82. data/lib/rubocop/cop/rspec/scattered_let.rb +1 -5
  83. data/lib/rubocop/cop/rspec/scattered_setup.rb +1 -1
  84. data/lib/rubocop/cop/rspec/shared_context.rb +1 -1
  85. data/lib/rubocop/cop/rspec/stubbed_mock.rb +0 -1
  86. data/lib/rubocop/cop/rspec/subject_declaration.rb +0 -1
  87. data/lib/rubocop/cop/rspec/subject_stub.rb +2 -2
  88. data/lib/rubocop/cop/rspec/unspecified_exception.rb +15 -15
  89. data/lib/rubocop/cop/rspec/variable_definition.rb +1 -0
  90. data/lib/rubocop/cop/rspec/variable_name.rb +6 -7
  91. data/lib/rubocop/cop/rspec/verified_doubles.rb +1 -0
  92. data/lib/rubocop/cop/rspec/void_expect.rb +2 -1
  93. data/lib/rubocop/cop/rspec/yield.rb +2 -1
  94. data/lib/rubocop/cop/rspec_cops.rb +3 -0
  95. data/lib/rubocop/rspec/config_formatter.rb +14 -3
  96. data/lib/rubocop/rspec/inject.rb +1 -3
  97. data/lib/rubocop/rspec/language/node_pattern.rb +4 -0
  98. data/lib/rubocop/rspec/language.rb +6 -1
  99. data/lib/rubocop/rspec/version.rb +1 -1
  100. data/lib/rubocop/rspec/wording.rb +2 -2
  101. data/lib/rubocop/rspec.rb +14 -0
  102. data/lib/rubocop-rspec.rb +3 -0
  103. metadata +11 -88
@@ -6,7 +6,6 @@ module RuboCop
6
6
  # Checks if an example group does not include any tests.
7
7
  #
8
8
  # @example usage
9
- #
10
9
  # # bad
11
10
  # describe Bacon do
12
11
  # let(:bacon) { Bacon.new(chunkiness) }
@@ -35,7 +34,12 @@ module RuboCop
35
34
  # describe Bacon do
36
35
  # pending 'will add tests later'
37
36
  # end
37
+ #
38
38
  class EmptyExampleGroup < Base
39
+ extend AutoCorrector
40
+
41
+ include RangeHelp
42
+
39
43
  MSG = 'Empty example group detected.'
40
44
 
41
45
  # @!method example_group_body(node)
@@ -119,7 +123,7 @@ module RuboCop
119
123
  # describe { it { i_run_as_well } }
120
124
  #
121
125
  # @example source that does not match
122
- # before { it { whatever here wont run anyway } }
126
+ # before { it { whatever here won't run anyway } }
123
127
  #
124
128
  # @param node [RuboCop::AST::Node]
125
129
  # @return [Array<RuboCop::AST::Node>] matching nodes
@@ -130,12 +134,16 @@ module RuboCop
130
134
  }
131
135
  PATTERN
132
136
 
133
- def on_block(node)
137
+ def on_block(node) # rubocop:disable InternalAffairs/NumblockHandler
134
138
  return if node.each_ancestor(:def, :defs).any?
135
139
  return if node.each_ancestor(:block).any? { |block| example?(block) }
136
140
 
137
141
  example_group_body(node) do |body|
138
- add_offense(node.send_node) if offensive?(body)
142
+ next unless offensive?(body)
143
+
144
+ add_offense(node.send_node) do |corrector|
145
+ corrector.remove(removed_range(node))
146
+ end
139
147
  end
140
148
  end
141
149
 
@@ -163,6 +171,13 @@ module RuboCop
163
171
  def examples_in_branches?(condition_node)
164
172
  condition_node.branches.any? { |branch| examples?(branch) }
165
173
  end
174
+
175
+ def removed_range(node)
176
+ range_by_whole_lines(
177
+ node.location.expression,
178
+ include_final_newline: true
179
+ )
180
+ end
166
181
  end
167
182
  end
168
183
  end
@@ -22,6 +22,7 @@ module RuboCop
22
22
  # create_feed
23
23
  # end
24
24
  # after(:all) { cleanup_feed }
25
+ #
25
26
  class EmptyHook < Base
26
27
  extend AutoCorrector
27
28
  include RuboCop::Cop::RangeHelp
@@ -33,7 +34,7 @@ module RuboCop
33
34
  (block $#{send_pattern('#Hooks.all')} _ nil?)
34
35
  PATTERN
35
36
 
36
- def on_block(node)
37
+ def on_block(node) # rubocop:disable InternalAffairs/NumblockHandler
37
38
  empty_hook?(node) do |hook|
38
39
  add_offense(hook) do |corrector|
39
40
  corrector.remove(
@@ -30,7 +30,6 @@ module RuboCop
30
30
  # end
31
31
  #
32
32
  # @example with AllowConsecutiveOneLiners configuration
33
- #
34
33
  # # rubocop.yml
35
34
  # # RSpec/EmptyLineAfterExample:
36
35
  # # AllowConsecutiveOneLiners: false
@@ -47,7 +46,7 @@ module RuboCop
47
46
 
48
47
  MSG = 'Add an empty line after `%<example>s`.'
49
48
 
50
- def on_block(node)
49
+ def on_block(node) # rubocop:disable InternalAffairs/NumblockHandler
51
50
  return unless example?(node)
52
51
  return if allowed_one_liner?(node)
53
52
 
@@ -65,19 +64,15 @@ module RuboCop
65
64
  end
66
65
 
67
66
  def consecutive_one_liner?(node)
68
- node.line_count == 1 && next_one_line_example?(node)
67
+ node.single_line? && next_one_line_example?(node)
69
68
  end
70
69
 
71
70
  def next_one_line_example?(node)
72
- next_sibling = next_sibling(node)
71
+ next_sibling = node.right_sibling
73
72
  return unless next_sibling
74
73
  return unless example?(next_sibling)
75
74
 
76
- next_sibling.line_count == 1
77
- end
78
-
79
- def next_sibling(node)
80
- node.parent.children[node.sibling_index + 1]
75
+ next_sibling.single_line?
81
76
  end
82
77
  end
83
78
  end
@@ -29,7 +29,7 @@ module RuboCop
29
29
 
30
30
  MSG = 'Add an empty line after `%<example_group>s`.'
31
31
 
32
- def on_block(node)
32
+ def on_block(node) # rubocop:disable InternalAffairs/NumblockHandler
33
33
  return unless example_group?(node)
34
34
 
35
35
  missing_separating_line_offense(node) do |method|
@@ -16,13 +16,14 @@ module RuboCop
16
16
  # let(:something) { other }
17
17
  #
18
18
  # it { does_something }
19
+ #
19
20
  class EmptyLineAfterFinalLet < Base
20
21
  extend AutoCorrector
21
22
  include EmptyLineSeparation
22
23
 
23
24
  MSG = 'Add an empty line after the last `%<let>s`.'
24
25
 
25
- def on_block(node)
26
+ def on_block(node) # rubocop:disable InternalAffairs/NumblockHandler
26
27
  return unless example_group_with_body?(node)
27
28
 
28
29
  final_let = node.body.child_nodes.reverse.find { |child| let?(child) }
@@ -5,6 +5,9 @@ module RuboCop
5
5
  module RSpec
6
6
  # Checks if there is an empty line after hook blocks.
7
7
  #
8
+ # `AllowConsecutiveOneLiners` configures whether adjacent
9
+ # one-line definitions are considered an offense.
10
+ #
8
11
  # @example
9
12
  # # bad
10
13
  # before { do_something }
@@ -19,11 +22,23 @@ module RuboCop
19
22
  # it { does_something }
20
23
  #
21
24
  # # good
22
- # before { do_something }
25
+ # after { do_something }
23
26
  #
24
27
  # it { does_something }
25
28
  #
26
- # # good
29
+ # # fair - it's ok to have non-separated one-liners hooks
30
+ # around { |test| test.run }
31
+ # after { do_something }
32
+ #
33
+ # it { does_something }
34
+ #
35
+ # @example with AllowConsecutiveOneLiners configuration
36
+ # # rubocop.yml
37
+ # # RSpec/EmptyLineAfterHook:
38
+ # # AllowConsecutiveOneLiners: false
39
+ #
40
+ # # bad
41
+ # around { |test| test.run }
27
42
  # after { do_something }
28
43
  #
29
44
  # it { does_something }
@@ -31,21 +46,36 @@ module RuboCop
31
46
  # # good
32
47
  # around { |test| test.run }
33
48
  #
49
+ # after { do_something }
50
+ #
34
51
  # it { does_something }
35
52
  #
36
53
  class EmptyLineAfterHook < Base
37
54
  extend AutoCorrector
55
+ include ConfigurableEnforcedStyle
38
56
  include EmptyLineSeparation
39
57
 
40
58
  MSG = 'Add an empty line after `%<hook>s`.'
41
59
 
42
60
  def on_block(node)
43
61
  return unless hook?(node)
62
+ return if cop_config['AllowConsecutiveOneLiners'] &&
63
+ chained_single_line_hooks?(node)
44
64
 
45
65
  missing_separating_line_offense(node) do |method|
46
66
  format(MSG, hook: method)
47
67
  end
48
68
  end
69
+
70
+ alias on_numblock on_block
71
+
72
+ private
73
+
74
+ def chained_single_line_hooks?(node)
75
+ next_node = node.right_sibling
76
+
77
+ hook?(next_node) && node.single_line? && next_node.single_line?
78
+ end
49
79
  end
50
80
  end
51
81
  end
@@ -14,6 +14,7 @@ module RuboCop
14
14
  # subject(:obj) { described_class }
15
15
  #
16
16
  # let(:foo) { bar }
17
+ #
17
18
  class EmptyLineAfterSubject < Base
18
19
  extend AutoCorrector
19
20
  include EmptyLineSeparation
@@ -21,7 +22,7 @@ module RuboCop
21
22
 
22
23
  MSG = 'Add an empty line after `%<subject>s`.'
23
24
 
24
- def on_block(node)
25
+ def on_block(node) # rubocop:disable InternalAffairs/NumblockHandler
25
26
  return unless subject?(node)
26
27
  return unless inside_example_group?(node)
27
28
 
@@ -47,12 +47,13 @@ module RuboCop
47
47
  # content.
48
48
  # HEREDOC
49
49
  # end # 5 points
50
+ #
50
51
  class ExampleLength < Base
51
52
  include CodeLength
52
53
 
53
54
  LABEL = 'Example'
54
55
 
55
- def on_block(node)
56
+ def on_block(node) # rubocop:disable InternalAffairs/NumblockHandler
56
57
  return unless example?(node)
57
58
 
58
59
  check_code_length(node)
@@ -47,6 +47,7 @@ module RuboCop
47
47
  # result = service.call
48
48
  # expect(result).to be(true)
49
49
  # end
50
+ #
50
51
  class ExampleWithoutDescription < Base
51
52
  include ConfigurableEnforcedStyle
52
53
 
@@ -57,7 +58,7 @@ module RuboCop
57
58
  # @!method example_description(node)
58
59
  def_node_matcher :example_description, '(send nil? _ $(str $_))'
59
60
 
60
- def on_block(node)
61
+ def on_block(node) # rubocop:disable InternalAffairs/NumblockHandler
61
62
  return unless example?(node)
62
63
 
63
64
  check_example_without_description(node.send_node)
@@ -29,6 +29,7 @@ module RuboCop
29
29
  # # good
30
30
  # it 'does things' do
31
31
  # end
32
+ #
32
33
  class ExampleWording < Base
33
34
  extend AutoCorrector
34
35
 
@@ -46,7 +47,7 @@ module RuboCop
46
47
  } ...) ...)
47
48
  PATTERN
48
49
 
49
- def on_block(node)
50
+ def on_block(node) # rubocop:disable InternalAffairs/NumblockHandler
50
51
  it_description(node) do |description_node, message|
51
52
  if message.match?(SHOULD_PREFIX)
52
53
  add_wording_offense(description_node, MSG_SHOULD)
@@ -22,6 +22,7 @@ module RuboCop
22
22
  # # good
23
23
  # context 'when a condition is met' do
24
24
  # end
25
+ #
25
26
  class ExcessiveDocstringSpacing < Base
26
27
  extend AutoCorrector
27
28
 
@@ -18,6 +18,9 @@ module RuboCop
18
18
  # expect(pattern).to eq(/foo/)
19
19
  # expect(name).to eq("John")
20
20
  #
21
+ # # bad (not supported autocorrection)
22
+ # expect(false).to eq(true)
23
+ #
21
24
  class ExpectActual < Base
22
25
  extend AutoCorrector
23
26
 
@@ -69,7 +69,7 @@ module RuboCop
69
69
  end
70
70
  end
71
71
 
72
- def on_block(node)
72
+ def on_block(node) # rubocop:disable InternalAffairs/NumblockHandler
73
73
  return unless style == :method_call
74
74
 
75
75
  expect_change_with_block(node) do |receiver, message|
@@ -20,13 +20,14 @@ module RuboCop
20
20
  # it do
21
21
  # expect(something).to eq 'foo'
22
22
  # end
23
+ #
23
24
  class ExpectInHook < Base
24
25
  MSG = 'Do not use `%<expect>s` in `%<hook>s` hook'
25
26
 
26
27
  # @!method expectation(node)
27
28
  def_node_search :expectation, send_pattern('#Expectations.all')
28
29
 
29
- def on_block(node)
30
+ def on_block(node) # rubocop:disable InternalAffairs/NumblockHandler
30
31
  return unless hook?(node)
31
32
  return if node.body.nil?
32
33
 
@@ -36,6 +37,8 @@ module RuboCop
36
37
  end
37
38
  end
38
39
 
40
+ alias on_numblock on_block
41
+
39
42
  private
40
43
 
41
44
  def message(expect, hook)
@@ -14,6 +14,7 @@ module RuboCop
14
14
  #
15
15
  # # good
16
16
  # expect { my_app.print_report }.to output('Hello World').to_stdout
17
+ #
17
18
  class ExpectOutput < Base
18
19
  MSG = 'Use `expect { ... }.to output(...).to_%<name>s` ' \
19
20
  'instead of mutating $%<name>s.'
@@ -24,6 +24,7 @@ module RuboCop
24
24
  #
25
25
  # # good
26
26
  # count { 1 }
27
+ #
27
28
  class AttributeDefinedStatically < Base
28
29
  extend AutoCorrector
29
30
 
@@ -39,7 +40,7 @@ module RuboCop
39
40
  (block (send _ #attribute_defining_method? ...) _ { (begin $...) $(send ...) } )
40
41
  PATTERN
41
42
 
42
- def on_block(node)
43
+ def on_block(node) # rubocop:disable InternalAffairs/NumblockHandler
43
44
  attributes = factory_attributes(node) || []
44
45
  attributes = [attributes] unless attributes.is_a?(Array) # rubocop:disable Style/ArrayCoercion, Lint/RedundantCopDisableDirective
45
46
 
@@ -30,6 +30,7 @@ module RuboCop
30
30
  #
31
31
  # # good
32
32
  # 3.times { create :user }
33
+ #
33
34
  class CreateList < Base
34
35
  extend AutoCorrector
35
36
  include ConfigurableEnforcedStyle
@@ -39,20 +40,23 @@ module RuboCop
39
40
  MSG_N_TIMES = 'Prefer %<number>s.times.'
40
41
  RESTRICT_ON_SEND = %i[create_list].freeze
41
42
 
42
- # @!method n_times_block?(node)
43
- def_node_matcher :n_times_block?, <<-PATTERN
43
+ # @!method array_new_or_n_times_block?(node)
44
+ def_node_matcher :array_new_or_n_times_block?, <<-PATTERN
44
45
  (block
45
- (send (int _) :times)
46
+ {
47
+ (send (const {nil? | cbase} :Array) :new (int _)) |
48
+ (send (int _) :times)
49
+ }
46
50
  ...
47
51
  )
48
52
  PATTERN
49
53
 
50
- # @!method n_times_block_with_arg_and_used?(node)
51
- def_node_matcher :n_times_block_with_arg_and_used?, <<-PATTERN
54
+ # @!method block_with_arg_and_used?(node)
55
+ def_node_matcher :block_with_arg_and_used?, <<-PATTERN
52
56
  (block
53
- (send (int _) :times)
57
+ _
54
58
  (args (arg _value))
55
- `_value
59
+ `_value
56
60
  )
57
61
  PATTERN
58
62
 
@@ -71,11 +75,11 @@ module RuboCop
71
75
  (send {nil? #factory_bot?} :create_list (sym _) (int $_) ...)
72
76
  PATTERN
73
77
 
74
- def on_block(node)
78
+ def on_block(node) # rubocop:todo InternalAffairs/NumblockHandler
75
79
  return unless style == :create_list
76
80
 
77
- return unless n_times_block?(node)
78
- return if n_times_block_with_arg_and_used?(node)
81
+ return unless array_new_or_n_times_block?(node)
82
+ return if block_with_arg_and_used?(node)
79
83
  return unless node.body
80
84
  return if arguments_include_method_call?(node.body)
81
85
  return unless contains_only_factory?(node.body)
@@ -183,7 +187,7 @@ module RuboCop
183
187
 
184
188
  def call_with_block_replacement(node)
185
189
  block = node.body
186
- arguments = build_arguments(block, node.receiver.source)
190
+ arguments = build_arguments(block, count_from(node))
187
191
  replacement = format_receiver(block.receiver)
188
192
  replacement += format_method_call(block, 'create_list', arguments)
189
193
  replacement += format_block(block)
@@ -203,7 +207,7 @@ module RuboCop
203
207
  block = node.body
204
208
  factory, *options = *block.arguments
205
209
 
206
- arguments = "#{factory.source}, #{node.receiver.source}"
210
+ arguments = "#{factory.source}, #{count_from(node)}"
207
211
  options = build_options_string(options)
208
212
  arguments += ", #{options}" unless options.empty?
209
213
 
@@ -212,6 +216,16 @@ module RuboCop
212
216
  replacement
213
217
  end
214
218
 
219
+ def count_from(node)
220
+ count_node =
221
+ if node.receiver.int_type?
222
+ node.receiver
223
+ else
224
+ node.send_node.first_argument
225
+ end
226
+ count_node.source
227
+ end
228
+
215
229
  def format_block(node)
216
230
  if node.body.begin_type?
217
231
  format_multiline_block(node)
@@ -19,6 +19,7 @@ module RuboCop
19
19
  # # good
20
20
  # factory :foo, class: 'Foo' do
21
21
  # end
22
+ #
22
23
  class FactoryClassName < Base
23
24
  extend AutoCorrector
24
25
 
@@ -58,6 +58,7 @@ module RuboCop
58
58
  #
59
59
  class FilePath < Base
60
60
  include TopLevelGroup
61
+ include Namespace
61
62
 
62
63
  MSG = 'Spec path should end with `%<suffix>s`.'
63
64
 
@@ -101,7 +102,7 @@ module RuboCop
101
102
 
102
103
  def pattern_for(example_group, method_name)
103
104
  if spec_suffix_only? || !example_group.const_type?
104
- return pattern_for_spec_suffix_only?
105
+ return pattern_for_spec_suffix_only
105
106
  end
106
107
 
107
108
  [
@@ -111,7 +112,7 @@ module RuboCop
111
112
  ].join
112
113
  end
113
114
 
114
- def pattern_for_spec_suffix_only?
115
+ def pattern_for_spec_suffix_only
115
116
  '.*_spec\.rb'
116
117
  end
117
118
 
@@ -123,8 +124,10 @@ module RuboCop
123
124
  end
124
125
 
125
126
  def expected_path(constant)
127
+ constants = namespace(constant) + constant.const_name.split('::')
128
+
126
129
  File.join(
127
- constant.const_name.split('::').map do |name|
130
+ constants.map do |name|
128
131
  custom_transform.fetch(name) { camel_to_snake_case(name) }
129
132
  end
130
133
  )
@@ -5,6 +5,8 @@ module RuboCop
5
5
  module RSpec
6
6
  # Checks if examples are focused.
7
7
  #
8
+ # This cop does not support autocorrection in some cases.
9
+ #
8
10
  # @example
9
11
  # # bad
10
12
  # describe MyClass, focus: true do
@@ -19,6 +21,22 @@ module RuboCop
19
21
  # # good
20
22
  # describe MyClass do
21
23
  # end
24
+ #
25
+ # # bad
26
+ # fdescribe 'test' do; end
27
+ #
28
+ # # good
29
+ # describe 'test' do; end
30
+ #
31
+ # # bad
32
+ # fdescribe 'test' do; end
33
+ #
34
+ # # good
35
+ # describe 'test' do; end
36
+ #
37
+ # # bad (does not support autocorrection)
38
+ # focus 'test' do; end
39
+ #
22
40
  class Focus < Base
23
41
  extend AutoCorrector
24
42
  include RangeHelp
@@ -57,6 +57,7 @@ module RuboCop
57
57
  # before(:example) do
58
58
  # # ...
59
59
  # end
60
+ #
60
61
  class HookArgument < Base
61
62
  extend AutoCorrector
62
63
  include ConfigurableEnforcedStyle
@@ -66,11 +67,13 @@ module RuboCop
66
67
 
67
68
  # @!method scoped_hook(node)
68
69
  def_node_matcher :scoped_hook, <<-PATTERN
69
- (block $(send _ #Hooks.all (sym ${:each :example})) ...)
70
+ ({block numblock} $(send _ #Hooks.all (sym ${:each :example})) ...)
70
71
  PATTERN
71
72
 
72
73
  # @!method unscoped_hook(node)
73
- def_node_matcher :unscoped_hook, '(block $(send _ #Hooks.all) ...)'
74
+ def_node_matcher :unscoped_hook, <<-PATTERN
75
+ ({block numblock} $(send _ #Hooks.all) ...)
76
+ PATTERN
74
77
 
75
78
  def on_block(node)
76
79
  hook(node) do |method_send, scope_name|
@@ -86,6 +89,8 @@ module RuboCop
86
89
  end
87
90
  end
88
91
 
92
+ alias on_numblock on_block
93
+
89
94
  private
90
95
 
91
96
  def check_implicit(method_send)
@@ -6,8 +6,7 @@ module RuboCop
6
6
  # Checks for before/around/after hooks that come after an example.
7
7
  #
8
8
  # @example
9
- # # Bad
10
- #
9
+ # # bad
11
10
  # it 'checks what foo does' do
12
11
  # expect(foo).to be
13
12
  # end
@@ -15,7 +14,7 @@ module RuboCop
15
14
  # before { prepare }
16
15
  # after { clean_up }
17
16
  #
18
- # # Good
17
+ # # good
19
18
  # before { prepare }
20
19
  # after { clean_up }
21
20
  #
@@ -32,6 +31,7 @@ module RuboCop
32
31
  def_node_matcher :example_or_group?, <<-PATTERN
33
32
  {
34
33
  #{block_pattern('{#ExampleGroups.all #Examples.all}')}
34
+ #{numblock_pattern('{#ExampleGroups.all #Examples.all}')}
35
35
  #{send_pattern('#Includes.examples')}
36
36
  }
37
37
  PATTERN
@@ -42,6 +42,8 @@ module RuboCop
42
42
  check_hooks(node.body) if multiline_block?(node.body)
43
43
  end
44
44
 
45
+ alias on_numblock on_block
46
+
45
47
  private
46
48
 
47
49
  def multiline_block?(block)
@@ -52,13 +54,12 @@ module RuboCop
52
54
  first_example = find_first_example(node)
53
55
  return unless first_example
54
56
 
55
- node.each_child_node do |child|
56
- next if child.sibling_index < first_example.sibling_index
57
- next unless hook?(child)
57
+ first_example.right_siblings.each do |sibling|
58
+ next unless hook?(sibling)
58
59
 
59
- msg = format(MSG, hook: child.method_name)
60
- add_offense(child, message: msg) do |corrector|
61
- autocorrect(corrector, child, first_example)
60
+ msg = format(MSG, hook: sibling.method_name)
61
+ add_offense(sibling, message: msg) do |corrector|
62
+ autocorrect(corrector, sibling, first_example)
62
63
  end
63
64
  end
64
65
  end
@@ -6,7 +6,6 @@ module RuboCop
6
6
  # Checks for equality assertions with identical expressions on both sides.
7
7
  #
8
8
  # @example
9
- #
10
9
  # # bad
11
10
  # expect(foo.bar).to eq(foo.bar)
12
11
  # expect(foo.bar).to eql(foo.bar)
@@ -16,6 +16,7 @@ module RuboCop
16
16
  # it 'changes something to a new value' do
17
17
  # expect { do_something }.to change(something).to(new_value)
18
18
  # end
19
+ #
19
20
  class ImplicitBlockExpectation < Base
20
21
  MSG = 'Avoid implicit block expectations.'
21
22
  RESTRICT_ON_SEND = %i[is_expected should should_not].freeze
@@ -9,7 +9,6 @@ module RuboCop
9
9
  # and supports the `--auto-gen-config` flag.
10
10
  #
11
11
  # @example `EnforcedStyle: is_expected` (default)
12
- #
13
12
  # # bad
14
13
  # it { should be_truthy }
15
14
  #
@@ -17,7 +16,6 @@ module RuboCop
17
16
  # it { is_expected.to be_truthy }
18
17
  #
19
18
  # @example `EnforcedStyle: should`
20
- #
21
19
  # # bad
22
20
  # it { is_expected.to be_truthy }
23
21
  #
@@ -42,7 +42,7 @@ module RuboCop
42
42
  ...)
43
43
  PATTERN
44
44
 
45
- def on_block(node)
45
+ def on_block(node) # rubocop:disable InternalAffairs/NumblockHandler
46
46
  return unless example?(node)
47
47
 
48
48
  null_double(node) do |var, receiver|
@@ -24,7 +24,6 @@ module RuboCop
24
24
  # end
25
25
  #
26
26
  # @example with AssignmentOnly configuration
27
- #
28
27
  # # rubocop.yml
29
28
  # # RSpec/InstanceVariable:
30
29
  # # AssignmentOnly: false