rubocop-rspec 1.7.0 → 3.0.2

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 (193) hide show
  1. checksums.yaml +5 -5
  2. data/CHANGELOG.md +955 -79
  3. data/CODE_OF_CONDUCT.md +17 -0
  4. data/MIT-LICENSE.md +1 -2
  5. data/README.md +35 -35
  6. data/config/default.yml +940 -52
  7. data/config/obsoletion.yml +30 -0
  8. data/lib/rubocop/cop/rspec/align_left_let_brace.rb +49 -0
  9. data/lib/rubocop/cop/rspec/align_right_let_brace.rb +49 -0
  10. data/lib/rubocop/cop/rspec/any_instance.rb +10 -13
  11. data/lib/rubocop/cop/rspec/around_block.rb +97 -0
  12. data/lib/rubocop/cop/rspec/base.rb +26 -0
  13. data/lib/rubocop/cop/rspec/be.rb +39 -0
  14. data/lib/rubocop/cop/rspec/be_empty.rb +45 -0
  15. data/lib/rubocop/cop/rspec/be_eq.rb +47 -0
  16. data/lib/rubocop/cop/rspec/be_eql.rb +18 -15
  17. data/lib/rubocop/cop/rspec/be_nil.rb +74 -0
  18. data/lib/rubocop/cop/rspec/before_after_all.rb +45 -0
  19. data/lib/rubocop/cop/rspec/change_by_zero.rb +184 -0
  20. data/lib/rubocop/cop/rspec/class_check.rb +101 -0
  21. data/lib/rubocop/cop/rspec/contain_exactly.rb +56 -0
  22. data/lib/rubocop/cop/rspec/context_method.rb +57 -0
  23. data/lib/rubocop/cop/rspec/context_wording.rb +117 -0
  24. data/lib/rubocop/cop/rspec/describe_class.rb +52 -21
  25. data/lib/rubocop/cop/rspec/describe_method.rb +26 -11
  26. data/lib/rubocop/cop/rspec/describe_symbol.rb +37 -0
  27. data/lib/rubocop/cop/rspec/described_class.rb +181 -34
  28. data/lib/rubocop/cop/rspec/described_class_module_wrapping.rb +38 -0
  29. data/lib/rubocop/cop/rspec/dialect.rb +84 -0
  30. data/lib/rubocop/cop/rspec/duplicated_metadata.rb +58 -0
  31. data/lib/rubocop/cop/rspec/empty_example_group.rb +134 -47
  32. data/lib/rubocop/cop/rspec/empty_hook.rb +49 -0
  33. data/lib/rubocop/cop/rspec/empty_line_after_example.rb +82 -0
  34. data/lib/rubocop/cop/rspec/empty_line_after_example_group.rb +42 -0
  35. data/lib/rubocop/cop/rspec/empty_line_after_final_let.rb +40 -0
  36. data/lib/rubocop/cop/rspec/empty_line_after_hook.rb +82 -0
  37. data/lib/rubocop/cop/rspec/empty_line_after_subject.rb +36 -0
  38. data/lib/rubocop/cop/rspec/empty_metadata.rb +46 -0
  39. data/lib/rubocop/cop/rspec/empty_output.rb +47 -0
  40. data/lib/rubocop/cop/rspec/eq.rb +47 -0
  41. data/lib/rubocop/cop/rspec/example_length.rb +38 -20
  42. data/lib/rubocop/cop/rspec/example_without_description.rb +98 -0
  43. data/lib/rubocop/cop/rspec/example_wording.rb +117 -27
  44. data/lib/rubocop/cop/rspec/excessive_docstring_spacing.rb +110 -0
  45. data/lib/rubocop/cop/rspec/expect_actual.rb +46 -20
  46. data/lib/rubocop/cop/rspec/expect_change.rb +86 -0
  47. data/lib/rubocop/cop/rspec/expect_in_hook.rb +50 -0
  48. data/lib/rubocop/cop/rspec/expect_in_let.rb +42 -0
  49. data/lib/rubocop/cop/rspec/expect_output.rb +50 -0
  50. data/lib/rubocop/cop/rspec/focus.rb +79 -25
  51. data/lib/rubocop/cop/rspec/hook_argument.rb +48 -36
  52. data/lib/rubocop/cop/rspec/hooks_before_examples.rb +81 -0
  53. data/lib/rubocop/cop/rspec/identical_equality_assertion.rb +37 -0
  54. data/lib/rubocop/cop/rspec/implicit_block_expectation.rb +68 -0
  55. data/lib/rubocop/cop/rspec/implicit_expect.rb +100 -0
  56. data/lib/rubocop/cop/rspec/implicit_subject.rb +167 -0
  57. data/lib/rubocop/cop/rspec/indexed_let.rb +112 -0
  58. data/lib/rubocop/cop/rspec/instance_spy.rb +74 -0
  59. data/lib/rubocop/cop/rspec/instance_variable.rb +28 -14
  60. data/lib/rubocop/cop/rspec/is_expected_specify.rb +45 -0
  61. data/lib/rubocop/cop/rspec/it_behaves_like.rb +49 -0
  62. data/lib/rubocop/cop/rspec/iterated_expectation.rb +74 -0
  63. data/lib/rubocop/cop/rspec/leading_subject.rb +57 -29
  64. data/lib/rubocop/cop/rspec/leaky_constant_declaration.rb +127 -0
  65. data/lib/rubocop/cop/rspec/let_before_examples.rb +101 -0
  66. data/lib/rubocop/cop/rspec/let_setup.rb +32 -16
  67. data/lib/rubocop/cop/rspec/match_array.rb +59 -0
  68. data/lib/rubocop/cop/rspec/message_chain.rb +10 -15
  69. data/lib/rubocop/cop/rspec/message_expectation.rb +12 -9
  70. data/lib/rubocop/cop/rspec/message_spies.rb +88 -0
  71. data/lib/rubocop/cop/rspec/metadata_style.rb +202 -0
  72. data/lib/rubocop/cop/rspec/missing_example_group_argument.rb +35 -0
  73. data/lib/rubocop/cop/rspec/missing_expectation_target_method.rb +54 -0
  74. data/lib/rubocop/cop/rspec/mixin/comments_help.rb +38 -0
  75. data/lib/rubocop/cop/rspec/mixin/empty_line_separation.rb +59 -0
  76. data/lib/rubocop/cop/rspec/mixin/file_help.rb +14 -0
  77. data/lib/rubocop/cop/rspec/mixin/final_end_location.rb +19 -0
  78. data/lib/rubocop/cop/rspec/mixin/inside_example_group.rb +29 -0
  79. data/lib/rubocop/cop/rspec/mixin/location_help.rb +37 -0
  80. data/lib/rubocop/cop/rspec/mixin/metadata.rb +63 -0
  81. data/lib/rubocop/cop/rspec/mixin/namespace.rb +23 -0
  82. data/lib/rubocop/cop/rspec/mixin/skip_or_pending.rb +39 -0
  83. data/lib/rubocop/cop/rspec/mixin/top_level_group.rb +54 -0
  84. data/lib/rubocop/cop/rspec/mixin/variable.rb +21 -0
  85. data/lib/rubocop/cop/rspec/multiple_describes.rb +14 -12
  86. data/lib/rubocop/cop/rspec/multiple_expectations.rb +86 -26
  87. data/lib/rubocop/cop/rspec/multiple_memoized_helpers.rb +146 -0
  88. data/lib/rubocop/cop/rspec/multiple_subjects.rb +97 -0
  89. data/lib/rubocop/cop/rspec/named_subject.rb +107 -27
  90. data/lib/rubocop/cop/rspec/nested_groups.rb +84 -47
  91. data/lib/rubocop/cop/rspec/no_expectation_example.rb +102 -0
  92. data/lib/rubocop/cop/rspec/not_to_not.rb +30 -27
  93. data/lib/rubocop/cop/rspec/overwriting_setup.rb +74 -0
  94. data/lib/rubocop/cop/rspec/pending.rb +80 -0
  95. data/lib/rubocop/cop/rspec/pending_without_reason.rb +159 -0
  96. data/lib/rubocop/cop/rspec/predicate_matcher.rb +341 -0
  97. data/lib/rubocop/cop/rspec/receive_counts.rb +89 -0
  98. data/lib/rubocop/cop/rspec/receive_messages.rb +161 -0
  99. data/lib/rubocop/cop/rspec/receive_never.rb +41 -0
  100. data/lib/rubocop/cop/rspec/redundant_around.rb +65 -0
  101. data/lib/rubocop/cop/rspec/redundant_predicate_matcher.rb +67 -0
  102. data/lib/rubocop/cop/rspec/remove_const.rb +39 -0
  103. data/lib/rubocop/cop/rspec/repeated_description.rb +98 -0
  104. data/lib/rubocop/cop/rspec/repeated_example.rb +53 -0
  105. data/lib/rubocop/cop/rspec/repeated_example_group_body.rb +100 -0
  106. data/lib/rubocop/cop/rspec/repeated_example_group_description.rb +96 -0
  107. data/lib/rubocop/cop/rspec/repeated_include_example.rb +105 -0
  108. data/lib/rubocop/cop/rspec/repeated_subject_call.rb +125 -0
  109. data/lib/rubocop/cop/rspec/return_from_stub.rb +169 -0
  110. data/lib/rubocop/cop/rspec/scattered_let.rb +59 -0
  111. data/lib/rubocop/cop/rspec/scattered_setup.rb +92 -0
  112. data/lib/rubocop/cop/rspec/shared_context.rb +107 -0
  113. data/lib/rubocop/cop/rspec/shared_examples.rb +125 -0
  114. data/lib/rubocop/cop/rspec/single_argument_message_chain.rb +93 -0
  115. data/lib/rubocop/cop/rspec/skip_block_inside_example.rb +46 -0
  116. data/lib/rubocop/cop/rspec/sort_metadata.rb +71 -0
  117. data/lib/rubocop/cop/rspec/spec_file_path_format.rb +133 -0
  118. data/lib/rubocop/cop/rspec/spec_file_path_suffix.rb +40 -0
  119. data/lib/rubocop/cop/rspec/stubbed_mock.rb +176 -0
  120. data/lib/rubocop/cop/rspec/subject_declaration.rb +46 -0
  121. data/lib/rubocop/cop/rspec/subject_stub.rb +93 -74
  122. data/lib/rubocop/cop/rspec/undescriptive_literals_description.rb +69 -0
  123. data/lib/rubocop/cop/rspec/unspecified_exception.rb +67 -0
  124. data/lib/rubocop/cop/rspec/variable_definition.rb +77 -0
  125. data/lib/rubocop/cop/rspec/variable_name.rb +68 -0
  126. data/lib/rubocop/cop/rspec/verified_double_reference.rb +111 -0
  127. data/lib/rubocop/cop/rspec/verified_doubles.rb +28 -14
  128. data/lib/rubocop/cop/rspec/void_expect.rb +60 -0
  129. data/lib/rubocop/cop/rspec/yield.rb +82 -0
  130. data/lib/rubocop/cop/rspec_cops.rb +112 -0
  131. data/lib/rubocop/rspec/align_let_brace.rb +63 -0
  132. data/lib/rubocop/rspec/concept.rb +33 -0
  133. data/lib/rubocop/rspec/config_formatter.rb +27 -4
  134. data/lib/rubocop/rspec/cop/generator.rb +25 -0
  135. data/lib/rubocop/rspec/corrector/move_node.rb +51 -0
  136. data/lib/rubocop/rspec/description_extractor.rb +60 -18
  137. data/lib/rubocop/rspec/example.rb +37 -0
  138. data/lib/rubocop/rspec/example_group.rb +67 -0
  139. data/lib/rubocop/rspec/hook.rb +79 -0
  140. data/lib/rubocop/rspec/inject.rb +3 -1
  141. data/lib/rubocop/rspec/language.rb +184 -41
  142. data/lib/rubocop/rspec/node.rb +19 -0
  143. data/lib/rubocop/rspec/shared_contexts/default_rspec_language_config_context.rb +29 -0
  144. data/lib/rubocop/rspec/version.rb +1 -1
  145. data/lib/rubocop/rspec/wording.rb +61 -19
  146. data/lib/rubocop/rspec.rb +6 -2
  147. data/lib/rubocop-rspec.rb +45 -34
  148. metadata +130 -195
  149. data/Gemfile +0 -13
  150. data/Rakefile +0 -48
  151. data/lib/rubocop/cop/rspec/file_path.rb +0 -83
  152. data/lib/rubocop/rspec/language/node_pattern.rb +0 -16
  153. data/lib/rubocop/rspec/spec_only.rb +0 -61
  154. data/lib/rubocop/rspec/top_level_describe.rb +0 -61
  155. data/lib/rubocop/rspec/util.rb +0 -19
  156. data/rubocop-rspec.gemspec +0 -42
  157. data/spec/expect_violation/expectation_spec.rb +0 -85
  158. data/spec/project/changelog_spec.rb +0 -81
  159. data/spec/project/default_config_spec.rb +0 -52
  160. data/spec/project/project_requires_spec.rb +0 -8
  161. data/spec/rubocop/cop/rspec/any_instance_spec.rb +0 -30
  162. data/spec/rubocop/cop/rspec/be_eql_spec.rb +0 -59
  163. data/spec/rubocop/cop/rspec/describe_class_spec.rb +0 -113
  164. data/spec/rubocop/cop/rspec/describe_method_spec.rb +0 -32
  165. data/spec/rubocop/cop/rspec/described_class_spec.rb +0 -219
  166. data/spec/rubocop/cop/rspec/empty_example_group_spec.rb +0 -79
  167. data/spec/rubocop/cop/rspec/example_length_spec.rb +0 -117
  168. data/spec/rubocop/cop/rspec/example_wording_spec.rb +0 -82
  169. data/spec/rubocop/cop/rspec/expect_actual_spec.rb +0 -136
  170. data/spec/rubocop/cop/rspec/file_path_spec.rb +0 -236
  171. data/spec/rubocop/cop/rspec/focus_spec.rb +0 -130
  172. data/spec/rubocop/cop/rspec/hook_argument_spec.rb +0 -189
  173. data/spec/rubocop/cop/rspec/instance_variable_spec.rb +0 -75
  174. data/spec/rubocop/cop/rspec/leading_subject_spec.rb +0 -54
  175. data/spec/rubocop/cop/rspec/let_setup_spec.rb +0 -66
  176. data/spec/rubocop/cop/rspec/message_chain_spec.rb +0 -21
  177. data/spec/rubocop/cop/rspec/message_expectation_spec.rb +0 -63
  178. data/spec/rubocop/cop/rspec/multiple_describes_spec.rb +0 -28
  179. data/spec/rubocop/cop/rspec/multiple_expectations_spec.rb +0 -84
  180. data/spec/rubocop/cop/rspec/named_subject_spec.rb +0 -62
  181. data/spec/rubocop/cop/rspec/nested_groups_spec.rb +0 -55
  182. data/spec/rubocop/cop/rspec/not_to_not_spec.rb +0 -57
  183. data/spec/rubocop/cop/rspec/subject_stub_spec.rb +0 -183
  184. data/spec/rubocop/cop/rspec/verified_doubles_spec.rb +0 -71
  185. data/spec/rubocop/rspec/config_formatter_spec.rb +0 -48
  186. data/spec/rubocop/rspec/description_extractor_spec.rb +0 -35
  187. data/spec/rubocop/rspec/language/selector_set_spec.rb +0 -29
  188. data/spec/rubocop/rspec/spec_only_spec.rb +0 -97
  189. data/spec/rubocop/rspec/util/one_spec.rb +0 -21
  190. data/spec/rubocop/rspec/wording_spec.rb +0 -44
  191. data/spec/shared/rspec_only_cop_behavior.rb +0 -68
  192. data/spec/spec_helper.rb +0 -41
  193. data/spec/support/expect_violation.rb +0 -166
@@ -0,0 +1,30 @@
1
+ #
2
+ # Configuration of obsolete/deprecated cops used by `ConfigObsoletion`.
3
+ #
4
+ # See: https://docs.rubocop.org/rubocop/extensions.html#config-obsoletions
5
+ #
6
+
7
+ # Cop parameters that have been changed
8
+ # Can be treated as a warning instead of a failure with `severity: warning`
9
+ changed_parameters:
10
+ - cops:
11
+ - RSpec/VariableName
12
+ parameters: IgnoredPatterns
13
+ alternative: AllowedPatterns
14
+ severity: warning
15
+
16
+ split:
17
+ RSpec/FilePath:
18
+ alternatives:
19
+ - RSpec/SpecFilePathFormat
20
+ - RSpec/SpecFilePathSuffix
21
+
22
+ removed:
23
+ RSpec/Capybara/FeatureMethods:
24
+ reason: >
25
+ this cop has migrated to `RSpec/Dialect`. Please use `RSpec/Dialect` instead
26
+
27
+ extracted:
28
+ RSpec/Rails/*: rubocop-rspec_rails
29
+ RSpec/FactoryBot/*: rubocop-factory_bot
30
+ RSpec/Capybara/*: rubocop-capybara
@@ -0,0 +1,49 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RuboCop
4
+ module Cop
5
+ module RSpec
6
+ # Checks that left braces for adjacent single line lets are aligned.
7
+ #
8
+ # @example
9
+ # # bad
10
+ # let(:foobar) { blahblah }
11
+ # let(:baz) { bar }
12
+ # let(:a) { b }
13
+ #
14
+ # # good
15
+ # let(:foobar) { blahblah }
16
+ # let(:baz) { bar }
17
+ # let(:a) { b }
18
+ #
19
+ class AlignLeftLetBrace < Base
20
+ extend AutoCorrector
21
+
22
+ MSG = 'Align left let brace'
23
+
24
+ def self.autocorrect_incompatible_with
25
+ [Layout::ExtraSpacing]
26
+ end
27
+
28
+ def on_new_investigation
29
+ super
30
+ return if processed_source.blank?
31
+
32
+ token_aligner.offending_tokens.each do |let|
33
+ add_offense(let.loc.begin) do |corrector|
34
+ corrector.insert_before(
35
+ let.loc.begin, token_aligner.indent_for(let)
36
+ )
37
+ end
38
+ end
39
+ end
40
+
41
+ private
42
+
43
+ def token_aligner
44
+ RuboCop::RSpec::AlignLetBrace.new(processed_source.ast, :begin)
45
+ end
46
+ end
47
+ end
48
+ end
49
+ end
@@ -0,0 +1,49 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RuboCop
4
+ module Cop
5
+ module RSpec
6
+ # Checks that right braces for adjacent single line lets are aligned.
7
+ #
8
+ # @example
9
+ # # bad
10
+ # let(:foobar) { blahblah }
11
+ # let(:baz) { bar }
12
+ # let(:a) { b }
13
+ #
14
+ # # good
15
+ # let(:foobar) { blahblah }
16
+ # let(:baz) { bar }
17
+ # let(:a) { b }
18
+ #
19
+ class AlignRightLetBrace < Base
20
+ extend AutoCorrector
21
+
22
+ MSG = 'Align right let brace'
23
+
24
+ def self.autocorrect_incompatible_with
25
+ [Layout::ExtraSpacing]
26
+ end
27
+
28
+ def on_new_investigation
29
+ super
30
+ return if processed_source.blank?
31
+
32
+ token_aligner.offending_tokens.each do |let|
33
+ add_offense(let.loc.end) do |corrector|
34
+ corrector.insert_before(
35
+ let.loc.end, token_aligner.indent_for(let)
36
+ )
37
+ end
38
+ end
39
+ end
40
+
41
+ private
42
+
43
+ def token_aligner
44
+ RuboCop::RSpec::AlignLetBrace.new(processed_source.ast, :end)
45
+ end
46
+ end
47
+ end
48
+ end
49
+ end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module RuboCop
2
4
  module Cop
3
5
  module RSpec
@@ -20,22 +22,17 @@ module RuboCop
20
22
  # allow(my_instance).to receive(:foo)
21
23
  # end
22
24
  # end
23
- class AnyInstance < Cop
24
- include RuboCop::RSpec::SpecOnly
25
-
26
- MESSAGE = 'Avoid stubbing using `%{method}`'.freeze
27
-
28
- ANY_INSTANCE_METHODS = [
29
- :any_instance,
30
- :allow_any_instance_of,
31
- :expect_any_instance_of
25
+ #
26
+ class AnyInstance < Base
27
+ MSG = 'Avoid stubbing using `%<method>s`.'
28
+ RESTRICT_ON_SEND = %i[
29
+ any_instance
30
+ allow_any_instance_of
31
+ expect_any_instance_of
32
32
  ].freeze
33
33
 
34
34
  def on_send(node)
35
- _receiver, method_name, *_args = *node
36
- return unless ANY_INSTANCE_METHODS.include?(method_name)
37
-
38
- add_offense(node, :expression, MESSAGE % { method: method_name })
35
+ add_offense(node, message: format(MSG, method: node.method_name))
39
36
  end
40
37
  end
41
38
  end
@@ -0,0 +1,97 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RuboCop
4
+ module Cop
5
+ module RSpec
6
+ # Checks that around blocks actually run the test.
7
+ #
8
+ # @example
9
+ # # bad
10
+ # around do
11
+ # some_method
12
+ # end
13
+ #
14
+ # around do |test|
15
+ # some_method
16
+ # end
17
+ #
18
+ # # good
19
+ # around do |test|
20
+ # some_method
21
+ # test.call
22
+ # end
23
+ #
24
+ # around do |test|
25
+ # some_method
26
+ # test.run
27
+ # end
28
+ #
29
+ class AroundBlock < Base
30
+ MSG_NO_ARG = 'Test object should be passed to around block.'
31
+ MSG_UNUSED_ARG = 'You should call `%<arg>s.call` ' \
32
+ 'or `%<arg>s.run`.'
33
+
34
+ # @!method hook_block(node)
35
+ def_node_matcher :hook_block, <<~PATTERN
36
+ (block (send nil? :around sym ?) (args $...) ...)
37
+ PATTERN
38
+
39
+ # @!method hook_numblock(node)
40
+ def_node_matcher :hook_numblock, <<~PATTERN
41
+ (numblock (send nil? :around sym ?) ...)
42
+ PATTERN
43
+
44
+ # @!method find_arg_usage(node)
45
+ def_node_search :find_arg_usage, <<~PATTERN
46
+ {(send $... {:call :run}) (send _ _ $...) (yield $...) (block-pass $...)}
47
+ PATTERN
48
+
49
+ def on_block(node)
50
+ hook_block(node) do |(example_proxy)|
51
+ if example_proxy.nil?
52
+ add_no_arg_offense(node)
53
+ else
54
+ check_for_unused_proxy(node, example_proxy)
55
+ end
56
+ end
57
+ end
58
+
59
+ def on_numblock(node)
60
+ hook_numblock(node) do
61
+ check_for_numblock(node)
62
+ end
63
+ end
64
+
65
+ private
66
+
67
+ def add_no_arg_offense(node)
68
+ add_offense(node, message: MSG_NO_ARG)
69
+ end
70
+
71
+ def check_for_unused_proxy(block, proxy)
72
+ name, = *proxy
73
+
74
+ find_arg_usage(block) do |usage|
75
+ return if usage.include?(s(:lvar, name))
76
+ end
77
+
78
+ add_offense(
79
+ proxy,
80
+ message: format(MSG_UNUSED_ARG, arg: name)
81
+ )
82
+ end
83
+
84
+ def check_for_numblock(block)
85
+ find_arg_usage(block) do |usage|
86
+ return if usage.include?(s(:lvar, :_1))
87
+ end
88
+
89
+ add_offense(
90
+ block.children.last,
91
+ message: format(MSG_UNUSED_ARG, arg: :_1)
92
+ )
93
+ end
94
+ end
95
+ end
96
+ end
97
+ end
@@ -0,0 +1,26 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RuboCop
4
+ module Cop
5
+ module RSpec
6
+ # @abstract parent class to RSpec cops
7
+ class Base < ::RuboCop::Cop::Base
8
+ include RuboCop::RSpec::Language
9
+
10
+ exclude_from_registry
11
+
12
+ # Invoke the original inherited hook so our cops are recognized
13
+ def self.inherited(subclass) # rubocop:disable Lint/MissingSuper
14
+ RuboCop::Cop::Base.inherited(subclass)
15
+ end
16
+
17
+ # Set the config for dynamic DSL configuration-aware helpers
18
+ # that have no other means of accessing the configuration.
19
+ def on_new_investigation
20
+ super
21
+ RuboCop::RSpec::Language.config = config['RSpec']['Language']
22
+ end
23
+ end
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,39 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RuboCop
4
+ module Cop
5
+ module RSpec
6
+ # Check for expectations where `be` is used without argument.
7
+ #
8
+ # The `be` matcher is too generic, as it pass on everything that is not
9
+ # nil or false. If that is the exact intend, use `be_truthy`. In all other
10
+ # cases it's better to specify what exactly is the expected value.
11
+ #
12
+ # @example
13
+ # # bad
14
+ # expect(foo).to be
15
+ #
16
+ # # good
17
+ # expect(foo).to be_truthy
18
+ # expect(foo).to be 1.0
19
+ # expect(foo).to be(true)
20
+ #
21
+ class Be < Base
22
+ MSG = "Don't use `be` without an argument."
23
+
24
+ RESTRICT_ON_SEND = Runners.all
25
+
26
+ # @!method be_without_args(node)
27
+ def_node_matcher :be_without_args, <<~PATTERN
28
+ (send _ #Runners.all $(send nil? :be))
29
+ PATTERN
30
+
31
+ def on_send(node)
32
+ be_without_args(node) do |matcher|
33
+ add_offense(matcher.loc.selector)
34
+ end
35
+ end
36
+ end
37
+ end
38
+ end
39
+ end
@@ -0,0 +1,45 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RuboCop
4
+ module Cop
5
+ module RSpec
6
+ # Prefer using `be_empty` when checking for an empty array.
7
+ #
8
+ # @example
9
+ # # bad
10
+ # expect(array).to contain_exactly
11
+ # expect(array).to match_array([])
12
+ #
13
+ # # good
14
+ # expect(array).to be_empty
15
+ #
16
+ class BeEmpty < Base
17
+ extend AutoCorrector
18
+
19
+ MSG = 'Use `be_empty` matchers for checking an empty array.'
20
+ RESTRICT_ON_SEND = %i[contain_exactly match_array].freeze
21
+
22
+ # @!method expect_array_matcher?(node)
23
+ def_node_matcher :expect_array_matcher?, <<~PATTERN
24
+ (send
25
+ (send nil? :expect _)
26
+ #Runners.all
27
+ ${
28
+ (send nil? :match_array (array))
29
+ (send nil? :contain_exactly)
30
+ }
31
+ _?
32
+ )
33
+ PATTERN
34
+
35
+ def on_send(node)
36
+ expect_array_matcher?(node.parent) do |expect|
37
+ add_offense(expect) do |corrector|
38
+ corrector.replace(expect, 'be_empty')
39
+ end
40
+ end
41
+ end
42
+ end
43
+ end
44
+ end
45
+ end
@@ -0,0 +1,47 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RuboCop
4
+ module Cop
5
+ module RSpec
6
+ # Check for expectations where `be(...)` can replace `eq(...)`.
7
+ #
8
+ # The `be` matcher compares by identity while the `eq` matcher compares
9
+ # using `==`. Booleans and nil can be compared by identity and therefore
10
+ # the `be` matcher is preferable as it is a more strict test.
11
+ #
12
+ # @safety
13
+ # This cop is unsafe because it changes how values are compared.
14
+ #
15
+ # @example
16
+ # # bad
17
+ # expect(foo).to eq(true)
18
+ # expect(foo).to eq(false)
19
+ # expect(foo).to eq(nil)
20
+ #
21
+ # # good
22
+ # expect(foo).to be(true)
23
+ # expect(foo).to be(false)
24
+ # expect(foo).to be(nil)
25
+ #
26
+ class BeEq < Base
27
+ extend AutoCorrector
28
+
29
+ MSG = 'Prefer `be` over `eq`.'
30
+ RESTRICT_ON_SEND = %i[eq].freeze
31
+
32
+ # @!method eq_type_with_identity?(node)
33
+ def_node_matcher :eq_type_with_identity?, <<~PATTERN
34
+ (send nil? :eq {true false nil})
35
+ PATTERN
36
+
37
+ def on_send(node)
38
+ return unless eq_type_with_identity?(node)
39
+
40
+ add_offense(node.loc.selector) do |corrector|
41
+ corrector.replace(node.loc.selector, 'be')
42
+ end
43
+ end
44
+ end
45
+ end
46
+ end
47
+ end
@@ -1,21 +1,26 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module RuboCop
2
4
  module Cop
3
5
  module RSpec
4
6
  # Check for expectations where `be(...)` can replace `eql(...)`.
5
7
  #
6
8
  # The `be` matcher compares by identity while the `eql` matcher
7
- # compares using `eql?`. Integers, floats, booleans, and symbols
9
+ # compares using `eql?`. Integers, floats, booleans, symbols, and nil
8
10
  # can be compared by identity and therefore the `be` matcher is
9
11
  # preferable as it is a more strict test.
10
12
  #
11
- # @example
13
+ # @safety
14
+ # This cop is unsafe because it changes how values are compared.
12
15
  #
16
+ # @example
13
17
  # # bad
14
18
  # expect(foo).to eql(1)
15
19
  # expect(foo).to eql(1.0)
16
20
  # expect(foo).to eql(true)
17
21
  # expect(foo).to eql(false)
18
22
  # expect(foo).to eql(:bar)
23
+ # expect(foo).to eql(nil)
19
24
  #
20
25
  # # good
21
26
  # expect(foo).to be(1)
@@ -23,6 +28,7 @@ module RuboCop
23
28
  # expect(foo).to be(true)
24
29
  # expect(foo).to be(false)
25
30
  # expect(foo).to be(:bar)
31
+ # expect(foo).to be(nil)
26
32
  #
27
33
  # This cop only looks for instances of `expect(...).to eql(...)`. We
28
34
  # do not check `to_not` or `not_to` since `!eql?` is more strict
@@ -31,25 +37,22 @@ module RuboCop
31
37
  # necessarily the same type as `b` since the `#==` operator can
32
38
  # coerce objects for comparison.
33
39
  #
34
- class BeEql < Cop
35
- include RuboCop::RSpec::SpecOnly,
36
- RuboCop::Cop::ConfigurableEnforcedStyle
40
+ class BeEql < Base
41
+ extend AutoCorrector
37
42
 
38
- MSG = 'Prefer `be` over `eql`'.freeze
43
+ MSG = 'Prefer `be` over `eql`.'
44
+ RESTRICT_ON_SEND = %i[to].freeze
39
45
 
40
- def_node_matcher :eql_type_with_identity, <<-PATTERN
41
- (send _ :to $(send nil :eql {true false int float sym}))
46
+ # @!method eql_type_with_identity(node)
47
+ def_node_matcher :eql_type_with_identity, <<~PATTERN
48
+ (send _ :to $(send nil? :eql {true false int float sym nil}))
42
49
  PATTERN
43
50
 
44
51
  def on_send(node)
45
52
  eql_type_with_identity(node) do |eql|
46
- add_offense(eql, :selector, MSG)
47
- end
48
- end
49
-
50
- def autocorrect(node)
51
- lambda do |corrector|
52
- corrector.replace(node.loc.selector, 'be')
53
+ add_offense(eql.loc.selector) do |corrector|
54
+ corrector.replace(eql.loc.selector, 'be')
55
+ end
53
56
  end
54
57
  end
55
58
  end
@@ -0,0 +1,74 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RuboCop
4
+ module Cop
5
+ module RSpec
6
+ # Ensures a consistent style is used when matching `nil`.
7
+ #
8
+ # You can either use the more specific `be_nil` matcher, or the more
9
+ # generic `be` matcher with a `nil` argument.
10
+ #
11
+ # This cop can be configured using the `EnforcedStyle` option
12
+ #
13
+ # @example `EnforcedStyle: be_nil` (default)
14
+ # # bad
15
+ # expect(foo).to be(nil)
16
+ #
17
+ # # good
18
+ # expect(foo).to be_nil
19
+ #
20
+ # @example `EnforcedStyle: be`
21
+ # # bad
22
+ # expect(foo).to be_nil
23
+ #
24
+ # # good
25
+ # expect(foo).to be(nil)
26
+ #
27
+ class BeNil < Base
28
+ extend AutoCorrector
29
+ include ConfigurableEnforcedStyle
30
+
31
+ BE_MSG = 'Prefer `be(nil)` over `be_nil`.'
32
+ BE_NIL_MSG = 'Prefer `be_nil` over `be(nil)`.'
33
+ RESTRICT_ON_SEND = %i[be be_nil].freeze
34
+
35
+ # @!method be_nil_matcher?(node)
36
+ def_node_matcher :be_nil_matcher?, <<~PATTERN
37
+ (send nil? :be_nil)
38
+ PATTERN
39
+
40
+ # @!method nil_value_expectation?(node)
41
+ def_node_matcher :nil_value_expectation?, <<~PATTERN
42
+ (send nil? :be nil)
43
+ PATTERN
44
+
45
+ def on_send(node)
46
+ case style
47
+ when :be
48
+ check_be_style(node)
49
+ when :be_nil
50
+ check_be_nil_style(node)
51
+ end
52
+ end
53
+
54
+ private
55
+
56
+ def check_be_style(node)
57
+ return unless be_nil_matcher?(node)
58
+
59
+ add_offense(node, message: BE_MSG) do |corrector|
60
+ corrector.replace(node, 'be(nil)')
61
+ end
62
+ end
63
+
64
+ def check_be_nil_style(node)
65
+ return unless nil_value_expectation?(node)
66
+
67
+ add_offense(node, message: BE_NIL_MSG) do |corrector|
68
+ corrector.replace(node, 'be_nil')
69
+ end
70
+ end
71
+ end
72
+ end
73
+ end
74
+ end
@@ -0,0 +1,45 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RuboCop
4
+ module Cop
5
+ module RSpec
6
+ # Check that before/after(:all/:context) isn't being used.
7
+ #
8
+ # @example
9
+ # # bad - Faster but risk of state leaking between examples
10
+ # describe MyClass do
11
+ # before(:all) { Widget.create }
12
+ # after(:context) { Widget.delete_all }
13
+ # end
14
+ #
15
+ # # good - Slower but examples are properly isolated
16
+ # describe MyClass do
17
+ # before(:each) { Widget.create }
18
+ # after(:each) { Widget.delete_all }
19
+ # end
20
+ #
21
+ class BeforeAfterAll < Base
22
+ MSG = 'Beware of using `%<hook>s` as it may cause state to leak ' \
23
+ 'between tests. If you are using `rspec-rails`, and ' \
24
+ '`use_transactional_fixtures` is enabled, then records created ' \
25
+ 'in `%<hook>s` are not automatically rolled back.'
26
+
27
+ RESTRICT_ON_SEND = Set[:before, :after].freeze
28
+
29
+ # @!method before_or_after_all(node)
30
+ def_node_matcher :before_or_after_all, <<~PATTERN
31
+ $(send _ RESTRICT_ON_SEND (sym {:all :context}))
32
+ PATTERN
33
+
34
+ def on_send(node)
35
+ before_or_after_all(node) do |hook|
36
+ add_offense(
37
+ node,
38
+ message: format(MSG, hook: hook.source)
39
+ )
40
+ end
41
+ end
42
+ end
43
+ end
44
+ end
45
+ end