rubocop-rspec 2.0.0 → 2.4.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (85) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +39 -0
  3. data/README.md +3 -3
  4. data/config/default.yml +141 -125
  5. data/lib/rubocop-rspec.rb +1 -0
  6. data/lib/rubocop/cop/rspec/any_instance.rb +6 -10
  7. data/lib/rubocop/cop/rspec/around_block.rb +3 -1
  8. data/lib/rubocop/cop/rspec/be.rb +2 -1
  9. data/lib/rubocop/cop/rspec/be_eql.rb +2 -0
  10. data/lib/rubocop/cop/rspec/before_after_all.rb +6 -3
  11. data/lib/rubocop/cop/rspec/capybara/current_path_expectation.rb +5 -0
  12. data/lib/rubocop/cop/rspec/capybara/feature_methods.rb +3 -0
  13. data/lib/rubocop/cop/rspec/capybara/visibility_matcher.rb +4 -0
  14. data/lib/rubocop/cop/rspec/context_method.rb +1 -0
  15. data/lib/rubocop/cop/rspec/context_wording.rb +7 -1
  16. data/lib/rubocop/cop/rspec/describe_class.rb +4 -1
  17. data/lib/rubocop/cop/rspec/describe_method.rb +2 -1
  18. data/lib/rubocop/cop/rspec/describe_symbol.rb +2 -0
  19. data/lib/rubocop/cop/rspec/described_class.rb +6 -1
  20. data/lib/rubocop/cop/rspec/described_class_module_wrapping.rb +2 -1
  21. data/lib/rubocop/cop/rspec/dialect.rb +1 -0
  22. data/lib/rubocop/cop/rspec/empty_hook.rb +1 -0
  23. data/lib/rubocop/cop/rspec/example_length.rb +26 -12
  24. data/lib/rubocop/cop/rspec/example_without_description.rb +1 -0
  25. data/lib/rubocop/cop/rspec/example_wording.rb +1 -0
  26. data/lib/rubocop/cop/rspec/expect_actual.rb +2 -0
  27. data/lib/rubocop/cop/rspec/expect_change.rb +6 -3
  28. data/lib/rubocop/cop/rspec/expect_in_hook.rb +1 -0
  29. data/lib/rubocop/cop/rspec/expect_output.rb +1 -1
  30. data/lib/rubocop/cop/rspec/factory_bot/attribute_defined_statically.rb +3 -0
  31. data/lib/rubocop/cop/rspec/factory_bot/create_list.rb +4 -0
  32. data/lib/rubocop/cop/rspec/factory_bot/factory_class_name.rb +2 -0
  33. data/lib/rubocop/cop/rspec/file_path.rb +31 -20
  34. data/lib/rubocop/cop/rspec/focus.rb +33 -1
  35. data/lib/rubocop/cop/rspec/hook_argument.rb +2 -0
  36. data/lib/rubocop/cop/rspec/hooks_before_examples.rb +1 -0
  37. data/lib/rubocop/cop/rspec/identical_equality_assertion.rb +38 -0
  38. data/lib/rubocop/cop/rspec/implicit_block_expectation.rb +4 -0
  39. data/lib/rubocop/cop/rspec/implicit_expect.rb +1 -0
  40. data/lib/rubocop/cop/rspec/implicit_subject.rb +19 -1
  41. data/lib/rubocop/cop/rspec/instance_spy.rb +3 -1
  42. data/lib/rubocop/cop/rspec/instance_variable.rb +4 -0
  43. data/lib/rubocop/cop/rspec/it_behaves_like.rb +3 -1
  44. data/lib/rubocop/cop/rspec/iterated_expectation.rb +3 -1
  45. data/lib/rubocop/cop/rspec/let_before_examples.rb +1 -0
  46. data/lib/rubocop/cop/rspec/let_setup.rb +3 -0
  47. data/lib/rubocop/cop/rspec/message_chain.rb +4 -10
  48. data/lib/rubocop/cop/rspec/message_expectation.rb +3 -0
  49. data/lib/rubocop/cop/rspec/message_spies.rb +4 -2
  50. data/lib/rubocop/cop/rspec/mixin/comments_help.rb +38 -0
  51. data/lib/rubocop/cop/rspec/mixin/variable.rb +1 -0
  52. data/lib/rubocop/cop/rspec/multiple_describes.rb +1 -2
  53. data/lib/rubocop/cop/rspec/multiple_expectations.rb +3 -0
  54. data/lib/rubocop/cop/rspec/named_subject.rb +3 -0
  55. data/lib/rubocop/cop/rspec/not_to_not.rb +2 -0
  56. data/lib/rubocop/cop/rspec/overwriting_setup.rb +2 -0
  57. data/lib/rubocop/cop/rspec/pending.rb +4 -0
  58. data/lib/rubocop/cop/rspec/predicate_matcher.rb +5 -0
  59. data/lib/rubocop/cop/rspec/rails/avoid_setup_hook.rb +44 -0
  60. data/lib/rubocop/cop/rspec/rails/http_status.rb +2 -0
  61. data/lib/rubocop/cop/rspec/receive_counts.rb +4 -0
  62. data/lib/rubocop/cop/rspec/receive_never.rb +2 -0
  63. data/lib/rubocop/cop/rspec/repeated_example_group_body.rb +8 -1
  64. data/lib/rubocop/cop/rspec/repeated_example_group_description.rb +4 -0
  65. data/lib/rubocop/cop/rspec/repeated_include_example.rb +3 -0
  66. data/lib/rubocop/cop/rspec/return_from_stub.rb +6 -0
  67. data/lib/rubocop/cop/rspec/scattered_setup.rb +1 -1
  68. data/lib/rubocop/cop/rspec/shared_context.rb +6 -5
  69. data/lib/rubocop/cop/rspec/shared_examples.rb +1 -0
  70. data/lib/rubocop/cop/rspec/single_argument_message_chain.rb +4 -1
  71. data/lib/rubocop/cop/rspec/stubbed_mock.rb +1 -0
  72. data/lib/rubocop/cop/rspec/subject_stub.rb +15 -4
  73. data/lib/rubocop/cop/rspec/unspecified_exception.rb +2 -0
  74. data/lib/rubocop/cop/rspec/verified_doubles.rb +2 -0
  75. data/lib/rubocop/cop/rspec/void_expect.rb +3 -0
  76. data/lib/rubocop/cop/rspec/yield.rb +3 -0
  77. data/lib/rubocop/cop/rspec_cops.rb +2 -0
  78. data/lib/rubocop/rspec/config_formatter.rb +3 -1
  79. data/lib/rubocop/rspec/corrector/move_node.rb +6 -9
  80. data/lib/rubocop/rspec/example.rb +5 -0
  81. data/lib/rubocop/rspec/hook.rb +1 -0
  82. data/lib/rubocop/rspec/language.rb +10 -0
  83. data/lib/rubocop/rspec/node.rb +1 -1
  84. data/lib/rubocop/rspec/version.rb +1 -1
  85. metadata +9 -6
@@ -15,18 +15,12 @@ module RuboCop
15
15
  #
16
16
  class MessageChain < Base
17
17
  MSG = 'Avoid stubbing using `%<method>s`.'
18
-
19
- def_node_matcher :message_chain, <<-PATTERN
20
- (send _ {:receive_message_chain :stub_chain} ...)
21
- PATTERN
18
+ RESTRICT_ON_SEND = %i[receive_message_chain stub_chain].freeze
22
19
 
23
20
  def on_send(node)
24
- message_chain(node) do
25
- add_offense(
26
- node.loc.selector,
27
- message: format(MSG, method: node.method_name)
28
- )
29
- end
21
+ add_offense(
22
+ node.loc.selector, message: format(MSG, method: node.method_name)
23
+ )
30
24
  end
31
25
  end
32
26
  end
@@ -30,11 +30,14 @@ module RuboCop
30
30
  MSG = 'Prefer `%<style>s` for setting message expectations.'
31
31
 
32
32
  SUPPORTED_STYLES = %w[allow expect].freeze
33
+ RESTRICT_ON_SEND = %i[to].freeze
33
34
 
35
+ # @!method message_expectation(node)
34
36
  def_node_matcher :message_expectation, <<-PATTERN
35
37
  (send $(send nil? {:expect :allow} ...) :to #receive_message?)
36
38
  PATTERN
37
39
 
40
+ # @!method receive_message?(node)
38
41
  def_node_search :receive_message?, '(send nil? :receive ...)'
39
42
 
40
43
  def on_send(node)
@@ -29,16 +29,18 @@ module RuboCop
29
29
 
30
30
  MSG_RECEIVE = 'Prefer `receive` for setting message expectations.'
31
31
 
32
- MSG_HAVE_RECEIVED = 'Prefer `have_received` for setting message '\
33
- 'expectations. Setup `%<source>s` as a spy using '\
32
+ MSG_HAVE_RECEIVED = 'Prefer `have_received` for setting message ' \
33
+ 'expectations. Setup `%<source>s` as a spy using ' \
34
34
  '`allow` or `instance_spy`.'
35
35
 
36
36
  SUPPORTED_STYLES = %w[have_received receive].freeze
37
37
 
38
+ # @!method message_expectation(node)
38
39
  def_node_matcher :message_expectation, %(
39
40
  (send (send nil? :expect $_) #Runners.all ...)
40
41
  )
41
42
 
43
+ # @!method receive_message(node)
42
44
  def_node_search :receive_message, %(
43
45
  $(send nil? {:receive :have_received} ...)
44
46
  )
@@ -0,0 +1,38 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RuboCop
4
+ module Cop
5
+ module RSpec
6
+ # Help methods for working with nodes containing comments.
7
+ module CommentsHelp
8
+ include FinalEndLocation
9
+
10
+ def source_range_with_comment(node)
11
+ begin_pos = begin_pos_with_comment(node).begin_pos
12
+ end_pos = end_line_position(node).end_pos
13
+
14
+ Parser::Source::Range.new(buffer, begin_pos, end_pos)
15
+ end
16
+
17
+ def begin_pos_with_comment(node)
18
+ first_comment = processed_source.ast_with_comments[node].first
19
+
20
+ start_line_position(first_comment || node)
21
+ end
22
+
23
+ def start_line_position(node)
24
+ buffer.line_range(node.loc.line)
25
+ end
26
+
27
+ def end_line_position(node)
28
+ end_line = buffer.line_for_position(final_end_location(node).end_pos)
29
+ buffer.line_range(end_line)
30
+ end
31
+
32
+ def buffer
33
+ processed_source.buffer
34
+ end
35
+ end
36
+ end
37
+ end
38
+ end
@@ -10,6 +10,7 @@ module RuboCop
10
10
  Subjects = RuboCop::RSpec::Language::Subjects
11
11
  Helpers = RuboCop::RSpec::Language::Helpers
12
12
 
13
+ # @!method variable_definition?(node)
13
14
  def_node_matcher :variable_definition?, <<~PATTERN
14
15
  (send nil? {#Subjects.all #Helpers.all}
15
16
  $({sym str dsym dstr} ...) ...)
@@ -25,8 +25,7 @@ module RuboCop
25
25
  class MultipleDescribes < Base
26
26
  include TopLevelGroup
27
27
 
28
- MSG = 'Do not use multiple top-level example groups - '\
29
- 'try to nest them.'
28
+ MSG = 'Do not use multiple top-level example groups - try to nest them.'
30
29
 
31
30
  def on_top_level_group(node)
32
31
  top_level_example_groups =
@@ -53,6 +53,7 @@ module RuboCop
53
53
  ANYTHING = ->(_node) { true }
54
54
  TRUE = ->(node) { node.true_type? }
55
55
 
56
+ # @!method aggregate_failures?(node)
56
57
  def_node_matcher :aggregate_failures?, <<-PATTERN
57
58
  (block {
58
59
  (send _ _ <(sym :aggregate_failures) ...>)
@@ -60,7 +61,9 @@ module RuboCop
60
61
  } ...)
61
62
  PATTERN
62
63
 
64
+ # @!method expect?(node)
63
65
  def_node_matcher :expect?, send_pattern('#Expectations.all')
66
+ # @!method aggregate_failures_block?(node)
64
67
  def_node_matcher :aggregate_failures_block?, <<-PATTERN
65
68
  (block (send nil? :aggregate_failures ...) ...)
66
69
  PATTERN
@@ -44,12 +44,15 @@ module RuboCop
44
44
  class NamedSubject < Base
45
45
  MSG = 'Name your test subject if you need to reference it explicitly.'
46
46
 
47
+ # @!method example_or_hook_block?(node)
47
48
  def_node_matcher :example_or_hook_block?,
48
49
  block_pattern('{#Examples.all #Hooks.all}')
49
50
 
51
+ # @!method shared_example?(node)
50
52
  def_node_matcher :shared_example?,
51
53
  block_pattern('#SharedGroups.examples')
52
54
 
55
+ # @!method subject_usage(node)
53
56
  def_node_search :subject_usage, '$(send nil? :subject)'
54
57
 
55
58
  def on_block(node)
@@ -20,7 +20,9 @@ module RuboCop
20
20
  include ConfigurableEnforcedStyle
21
21
 
22
22
  MSG = 'Prefer `%<replacement>s` over `%<original>s`.'
23
+ RESTRICT_ON_SEND = %i[not_to to_not].freeze
23
24
 
25
+ # @!method not_to_not_offense(node)
24
26
  def_node_matcher :not_to_not_offense, '(send _ % ...)'
25
27
 
26
28
  def on_send(node)
@@ -24,8 +24,10 @@ module RuboCop
24
24
  class OverwritingSetup < Base
25
25
  MSG = '`%<name>s` is already defined.'
26
26
 
27
+ # @!method setup?(node)
27
28
  def_node_matcher :setup?, block_pattern('{#Helpers.all #Subjects.all}')
28
29
 
30
+ # @!method first_argument_name(node)
29
31
  def_node_matcher :first_argument_name, '(send _ _ ({str sym} $_))'
30
32
 
31
33
  def on_block(node)
@@ -34,11 +34,13 @@ module RuboCop
34
34
  class Pending < Base
35
35
  MSG = 'Pending spec found.'
36
36
 
37
+ # @!method skippable?(node)
37
38
  def_node_matcher :skippable?,
38
39
  send_pattern(<<~PATTERN)
39
40
  {#ExampleGroups.regular #Examples.regular}
40
41
  PATTERN
41
42
 
43
+ # @!method skipped_in_metadata?(node)
42
44
  def_node_matcher :skipped_in_metadata?, <<-PATTERN
43
45
  {
44
46
  (send _ _ <#skip_or_pending? ...>)
@@ -46,8 +48,10 @@ module RuboCop
46
48
  }
47
49
  PATTERN
48
50
 
51
+ # @!method skip_or_pending?(node)
49
52
  def_node_matcher :skip_or_pending?, '{(sym :skip) (sym :pending)}'
50
53
 
54
+ # @!method pending_block?(node)
51
55
  def_node_matcher :pending_block?,
52
56
  send_pattern(<<~PATTERN)
53
57
  {
@@ -25,6 +25,7 @@ module RuboCop
25
25
  end
26
26
  end
27
27
 
28
+ # @!method predicate_in_actual?(node)
28
29
  def_node_matcher :predicate_in_actual?, <<-PATTERN
29
30
  (send
30
31
  (send nil? :expect {
@@ -34,10 +35,12 @@ module RuboCop
34
35
  $#boolean_matcher?)
35
36
  PATTERN
36
37
 
38
+ # @!method be_bool?(node)
37
39
  def_node_matcher :be_bool?, <<-PATTERN
38
40
  (send nil? {:be :eq :eql :equal} {true false})
39
41
  PATTERN
40
42
 
43
+ # @!method be_boolthy?(node)
41
44
  def_node_matcher :be_boolthy?, <<-PATTERN
42
45
  (send nil? {:be_truthy :be_falsey :be_falsy :a_truthy_value :a_falsey_value :a_falsy_value})
43
46
  PATTERN
@@ -152,6 +155,7 @@ module RuboCop
152
155
  end
153
156
  end
154
157
 
158
+ # @!method predicate_matcher?(node)
155
159
  def_node_matcher :predicate_matcher?, <<-PATTERN
156
160
  (send
157
161
  (send nil? :expect $!nil?)
@@ -160,6 +164,7 @@ module RuboCop
160
164
  (block $(send nil? #predicate_matcher_name? ...) ...)})
161
165
  PATTERN
162
166
 
167
+ # @!method predicate_matcher_block?(node)
163
168
  def_node_matcher :predicate_matcher_block?, <<-PATTERN
164
169
  (block
165
170
  (send
@@ -0,0 +1,44 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RuboCop
4
+ module Cop
5
+ module RSpec
6
+ module Rails
7
+ # Checks that tests use RSpec `before` hook over Rails `setup` method.
8
+ #
9
+ # @example
10
+ #
11
+ # # bad
12
+ # setup do
13
+ # allow(foo).to receive(:bar)
14
+ # end
15
+ #
16
+ # # good
17
+ # before do
18
+ # allow(foo).to receive(:bar)
19
+ # end
20
+ #
21
+ class AvoidSetupHook < Base
22
+ extend AutoCorrector
23
+
24
+ MSG = 'Use `before` instead of `setup`.'
25
+
26
+ # @!method setup_call(node)
27
+ def_node_matcher :setup_call, <<-PATTERN
28
+ (block
29
+ $(send nil? :setup)
30
+ (args) _)
31
+ PATTERN
32
+
33
+ def on_block(node)
34
+ setup_call(node) do |setup|
35
+ add_offense(node) do |corrector|
36
+ corrector.replace setup, 'before'
37
+ end
38
+ end
39
+ end
40
+ end
41
+ end
42
+ end
43
+ end
44
+ end
@@ -33,7 +33,9 @@ module RuboCop
33
33
  class HttpStatus < Base
34
34
  extend AutoCorrector
35
35
  include ConfigurableEnforcedStyle
36
+ RESTRICT_ON_SEND = %i[have_http_status].freeze
36
37
 
38
+ # @!method http_status(node)
37
39
  def_node_matcher :http_status, <<-PATTERN
38
40
  (send nil? :have_http_status ${int sym})
39
41
  PATTERN
@@ -28,10 +28,14 @@ module RuboCop
28
28
 
29
29
  MSG = 'Use `%<alternative>s` instead of `%<original>s`.'
30
30
 
31
+ RESTRICT_ON_SEND = %i[times].freeze
32
+
33
+ # @!method receive_counts(node)
31
34
  def_node_matcher :receive_counts, <<-PATTERN
32
35
  (send $(send _ {:exactly :at_least :at_most} (int {1 2})) :times)
33
36
  PATTERN
34
37
 
38
+ # @!method stub?(node)
35
39
  def_node_search :stub?, '(send nil? :receive ...)'
36
40
 
37
41
  def on_send(node)
@@ -16,7 +16,9 @@ module RuboCop
16
16
  class ReceiveNever < Base
17
17
  extend AutoCorrector
18
18
  MSG = 'Use `not_to receive` instead of `never`.'
19
+ RESTRICT_ON_SEND = %i[never].freeze
19
20
 
21
+ # @!method method_on_stub?(node)
20
22
  def_node_search :method_on_stub?, '(send nil? :receive ...)'
21
23
 
22
24
  def on_send(node)
@@ -46,16 +46,23 @@ module RuboCop
46
46
  class RepeatedExampleGroupBody < Base
47
47
  MSG = 'Repeated %<group>s block body on line(s) %<loc>s'
48
48
 
49
+ # @!method several_example_groups?(node)
49
50
  def_node_matcher :several_example_groups?, <<-PATTERN
50
51
  (begin <#example_group_with_body? #example_group_with_body? ...>)
51
52
  PATTERN
52
53
 
54
+ # @!method metadata(node)
53
55
  def_node_matcher :metadata, '(block (send _ _ _ $...) ...)'
56
+
57
+ # @!method body(node)
54
58
  def_node_matcher :body, '(block _ args $...)'
59
+
60
+ # @!method const_arg(node)
55
61
  def_node_matcher :const_arg, '(block (send _ _ $const ...) ...)'
56
62
 
63
+ # @!method skip_or_pending?(node)
57
64
  def_node_matcher :skip_or_pending?, <<-PATTERN
58
- (block <(send nil? {:skip :pending}) ...>)
65
+ (block <(send nil? {:skip :pending} ...) ...>)
59
66
  PATTERN
60
67
 
61
68
  def on_begin(node)
@@ -46,18 +46,22 @@ module RuboCop
46
46
  class RepeatedExampleGroupDescription < Base
47
47
  MSG = 'Repeated %<group>s block description on line(s) %<loc>s'
48
48
 
49
+ # @!method several_example_groups?(node)
49
50
  def_node_matcher :several_example_groups?, <<-PATTERN
50
51
  (begin <#example_group? #example_group? ...>)
51
52
  PATTERN
52
53
 
54
+ # @!method doc_string_and_metadata(node)
53
55
  def_node_matcher :doc_string_and_metadata, <<-PATTERN
54
56
  (block (send _ _ $_ $...) ...)
55
57
  PATTERN
56
58
 
59
+ # @!method skip_or_pending?(node)
57
60
  def_node_matcher :skip_or_pending?, <<-PATTERN
58
61
  (block <(send nil? {:skip :pending}) ...>)
59
62
  PATTERN
60
63
 
64
+ # @!method empty_description?(node)
61
65
  def_node_matcher :empty_description?, '(block (send _ _) ...)'
62
66
 
63
67
  def on_begin(node)
@@ -50,13 +50,16 @@ module RuboCop
50
50
  MSG = 'Repeated include of shared_examples %<name>s ' \
51
51
  'on line(s) %<repeat>s'
52
52
 
53
+ # @!method several_include_examples?(node)
53
54
  def_node_matcher :several_include_examples?, <<-PATTERN
54
55
  (begin <#include_examples? #include_examples? ...>)
55
56
  PATTERN
56
57
 
58
+ # @!method include_examples?(node)
57
59
  def_node_matcher :include_examples?,
58
60
  send_pattern('#Includes.examples')
59
61
 
62
+ # @!method shared_examples_name(node)
60
63
  def_node_matcher :shared_examples_name, <<-PATTERN
61
64
  (send _ #Includes.examples $_ ...)
62
65
  PATTERN
@@ -39,9 +39,15 @@ module RuboCop
39
39
 
40
40
  MSG_AND_RETURN = 'Use `and_return` for static values.'
41
41
  MSG_BLOCK = 'Use block for static values.'
42
+ RESTRICT_ON_SEND = %i[and_return].freeze
42
43
 
44
+ # @!method contains_stub?(node)
43
45
  def_node_search :contains_stub?, '(send nil? :receive (...))'
46
+
47
+ # @!method stub_with_block?(node)
44
48
  def_node_matcher :stub_with_block?, '(block #contains_stub? ...)'
49
+
50
+ # @!method and_return_value(node)
45
51
  def_node_search :and_return_value, <<-PATTERN
46
52
  $(send _ :and_return $(...))
47
53
  PATTERN
@@ -23,7 +23,7 @@ module RuboCop
23
23
  # end
24
24
  #
25
25
  class ScatteredSetup < Base
26
- MSG = 'Do not define multiple `%<hook_name>s` hooks in the same '\
26
+ MSG = 'Do not define multiple `%<hook_name>s` hooks in the same ' \
27
27
  'example group (also defined on %<lines>s).'
28
28
 
29
29
  def on_block(node)
@@ -53,15 +53,14 @@ module RuboCop
53
53
  class SharedContext < Base
54
54
  extend AutoCorrector
55
55
 
56
- MSG_EXAMPLES = "Use `shared_examples` when you don't "\
57
- 'define context.'
58
-
59
- MSG_CONTEXT = "Use `shared_context` when you don't "\
60
- 'define examples.'
56
+ MSG_EXAMPLES = "Use `shared_examples` when you don't define context."
57
+ MSG_CONTEXT = "Use `shared_context` when you don't define examples."
61
58
 
59
+ # @!method examples?(node)
62
60
  def_node_search :examples?,
63
61
  send_pattern('{#Includes.examples #Examples.all}')
64
62
 
63
+ # @!method context?(node)
65
64
  def_node_search :context?, <<-PATTERN
66
65
  (
67
66
  send #rspec? {
@@ -73,8 +72,10 @@ module RuboCop
73
72
  )
74
73
  PATTERN
75
74
 
75
+ # @!method shared_context(node)
76
76
  def_node_matcher :shared_context,
77
77
  block_pattern('#SharedGroups.context')
78
+ # @!method shared_example(node)
78
79
  def_node_matcher :shared_example,
79
80
  block_pattern('#SharedGroups.examples')
80
81