rubocop-rspec 2.0.0.pre → 2.3.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (112) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +39 -2
  3. data/README.md +7 -3
  4. data/config/default.yml +159 -73
  5. data/lib/rubocop-rspec.rb +8 -8
  6. data/lib/rubocop/cop/rspec/align_left_let_brace.rb +7 -3
  7. data/lib/rubocop/cop/rspec/align_right_let_brace.rb +7 -3
  8. data/lib/rubocop/cop/rspec/any_instance.rb +6 -10
  9. data/lib/rubocop/cop/rspec/around_block.rb +3 -1
  10. data/lib/rubocop/cop/rspec/base.rb +6 -55
  11. data/lib/rubocop/cop/rspec/be.rb +3 -2
  12. data/lib/rubocop/cop/rspec/be_eql.rb +2 -0
  13. data/lib/rubocop/cop/rspec/before_after_all.rb +6 -3
  14. data/lib/rubocop/cop/rspec/capybara/current_path_expectation.rb +7 -2
  15. data/lib/rubocop/cop/rspec/capybara/feature_methods.rb +6 -2
  16. data/lib/rubocop/cop/rspec/capybara/visibility_matcher.rb +4 -0
  17. data/lib/rubocop/cop/rspec/context_method.rb +1 -0
  18. data/lib/rubocop/cop/rspec/context_wording.rb +7 -1
  19. data/lib/rubocop/cop/rspec/describe_class.rb +5 -2
  20. data/lib/rubocop/cop/rspec/describe_method.rb +3 -2
  21. data/lib/rubocop/cop/rspec/describe_symbol.rb +2 -0
  22. data/lib/rubocop/cop/rspec/described_class.rb +6 -2
  23. data/lib/rubocop/cop/rspec/described_class_module_wrapping.rb +3 -3
  24. data/lib/rubocop/cop/rspec/dialect.rb +2 -1
  25. data/lib/rubocop/cop/rspec/empty_example_group.rb +6 -45
  26. data/lib/rubocop/cop/rspec/empty_hook.rb +2 -1
  27. data/lib/rubocop/cop/rspec/empty_line_after_example.rb +1 -1
  28. data/lib/rubocop/cop/rspec/empty_line_after_example_group.rb +1 -1
  29. data/lib/rubocop/cop/rspec/empty_line_after_final_let.rb +1 -1
  30. data/lib/rubocop/cop/rspec/empty_line_after_hook.rb +1 -1
  31. data/lib/rubocop/cop/rspec/empty_line_after_subject.rb +2 -2
  32. data/lib/rubocop/cop/rspec/example_length.rb +26 -12
  33. data/lib/rubocop/cop/rspec/example_without_description.rb +1 -0
  34. data/lib/rubocop/cop/rspec/example_wording.rb +1 -0
  35. data/lib/rubocop/cop/rspec/expect_actual.rb +3 -1
  36. data/lib/rubocop/cop/rspec/expect_change.rb +3 -0
  37. data/lib/rubocop/cop/rspec/expect_in_hook.rb +2 -1
  38. data/lib/rubocop/cop/rspec/expect_output.rb +1 -1
  39. data/lib/rubocop/cop/rspec/factory_bot/attribute_defined_statically.rb +3 -0
  40. data/lib/rubocop/cop/rspec/factory_bot/create_list.rb +4 -0
  41. data/lib/rubocop/cop/rspec/factory_bot/factory_class_name.rb +2 -0
  42. data/lib/rubocop/cop/rspec/file_path.rb +26 -17
  43. data/lib/rubocop/cop/rspec/focus.rb +46 -8
  44. data/lib/rubocop/cop/rspec/hook_argument.rb +4 -4
  45. data/lib/rubocop/cop/rspec/hooks_before_examples.rb +3 -2
  46. data/lib/rubocop/cop/rspec/implicit_block_expectation.rb +4 -0
  47. data/lib/rubocop/cop/rspec/implicit_expect.rb +2 -1
  48. data/lib/rubocop/cop/rspec/implicit_subject.rb +2 -0
  49. data/lib/rubocop/cop/rspec/instance_spy.rb +3 -1
  50. data/lib/rubocop/cop/rspec/instance_variable.rb +5 -1
  51. data/lib/rubocop/cop/rspec/it_behaves_like.rb +3 -1
  52. data/lib/rubocop/cop/rspec/iterated_expectation.rb +3 -1
  53. data/lib/rubocop/cop/rspec/let_before_examples.rb +3 -2
  54. data/lib/rubocop/cop/rspec/let_setup.rb +10 -4
  55. data/lib/rubocop/cop/rspec/message_chain.rb +4 -10
  56. data/lib/rubocop/cop/rspec/message_expectation.rb +3 -0
  57. data/lib/rubocop/cop/rspec/message_spies.rb +5 -3
  58. data/lib/rubocop/cop/rspec/mixin/comments_help.rb +38 -0
  59. data/lib/rubocop/cop/rspec/mixin/empty_line_separation.rb +51 -0
  60. data/lib/rubocop/cop/rspec/mixin/final_end_location.rb +19 -0
  61. data/lib/rubocop/cop/rspec/mixin/top_level_group.rb +54 -0
  62. data/lib/rubocop/cop/rspec/mixin/variable.rb +21 -0
  63. data/lib/rubocop/cop/rspec/multiple_describes.rb +2 -3
  64. data/lib/rubocop/cop/rspec/multiple_expectations.rb +4 -1
  65. data/lib/rubocop/cop/rspec/multiple_memoized_helpers.rb +3 -1
  66. data/lib/rubocop/cop/rspec/named_subject.rb +11 -12
  67. data/lib/rubocop/cop/rspec/nested_groups.rb +1 -1
  68. data/lib/rubocop/cop/rspec/not_to_not.rb +2 -0
  69. data/lib/rubocop/cop/rspec/overwriting_setup.rb +4 -1
  70. data/lib/rubocop/cop/rspec/pending.rb +17 -5
  71. data/lib/rubocop/cop/rspec/predicate_matcher.rb +8 -3
  72. data/lib/rubocop/cop/rspec/rails/http_status.rb +2 -0
  73. data/lib/rubocop/cop/rspec/receive_counts.rb +4 -0
  74. data/lib/rubocop/cop/rspec/receive_never.rb +2 -0
  75. data/lib/rubocop/cop/rspec/repeated_example_group_body.rb +8 -1
  76. data/lib/rubocop/cop/rspec/repeated_example_group_description.rb +4 -0
  77. data/lib/rubocop/cop/rspec/repeated_include_example.rb +6 -2
  78. data/lib/rubocop/cop/rspec/return_from_stub.rb +6 -0
  79. data/lib/rubocop/cop/rspec/scattered_setup.rb +1 -1
  80. data/lib/rubocop/cop/rspec/shared_context.rb +22 -11
  81. data/lib/rubocop/cop/rspec/shared_examples.rb +4 -1
  82. data/lib/rubocop/cop/rspec/single_argument_message_chain.rb +4 -1
  83. data/lib/rubocop/cop/rspec/stubbed_mock.rb +2 -1
  84. data/lib/rubocop/cop/rspec/subject_stub.rb +17 -6
  85. data/lib/rubocop/cop/rspec/unspecified_exception.rb +2 -0
  86. data/lib/rubocop/cop/rspec/variable_definition.rb +1 -1
  87. data/lib/rubocop/cop/rspec/variable_name.rb +1 -1
  88. data/lib/rubocop/cop/rspec/verified_doubles.rb +2 -0
  89. data/lib/rubocop/cop/rspec/void_expect.rb +3 -0
  90. data/lib/rubocop/cop/rspec/yield.rb +3 -0
  91. data/lib/rubocop/cop/rspec_cops.rb +0 -1
  92. data/lib/rubocop/rspec/align_let_brace.rb +1 -1
  93. data/lib/rubocop/rspec/concept.rb +2 -2
  94. data/lib/rubocop/rspec/config_formatter.rb +5 -3
  95. data/lib/rubocop/rspec/corrector/move_node.rb +7 -10
  96. data/lib/rubocop/rspec/example.rb +5 -0
  97. data/lib/rubocop/rspec/example_group.rb +15 -5
  98. data/lib/rubocop/rspec/hook.rb +2 -1
  99. data/lib/rubocop/rspec/inject.rb +4 -2
  100. data/lib/rubocop/rspec/language.rb +159 -115
  101. data/lib/rubocop/rspec/language/node_pattern.rb +7 -24
  102. data/lib/rubocop/rspec/node.rb +1 -1
  103. data/lib/rubocop/rspec/version.rb +1 -1
  104. metadata +27 -16
  105. data/lib/rubocop/cop/rspec/cop.rb +0 -10
  106. data/lib/rubocop/cop/rspec/invalid_predicate_matcher.rb +0 -41
  107. data/lib/rubocop/rspec.rb +0 -12
  108. data/lib/rubocop/rspec/empty_line_separation.rb +0 -48
  109. data/lib/rubocop/rspec/final_end_location.rb +0 -17
  110. data/lib/rubocop/rspec/top_level_describe.rb +0 -52
  111. data/lib/rubocop/rspec/top_level_group.rb +0 -57
  112. data/lib/rubocop/rspec/variable.rb +0 -16
@@ -23,8 +23,11 @@ module RuboCop
23
23
  class SharedExamples < Base
24
24
  extend AutoCorrector
25
25
 
26
+ # @!method shared_examples(node)
26
27
  def_node_matcher :shared_examples,
27
- (SharedGroups::ALL + Includes::ALL).send_pattern
28
+ send_pattern(
29
+ '{#SharedGroups.all #Includes.all}'
30
+ )
28
31
 
29
32
  def on_send(node)
30
33
  shared_examples(node) do
@@ -19,13 +19,16 @@ module RuboCop
19
19
  class SingleArgumentMessageChain < Base
20
20
  extend AutoCorrector
21
21
 
22
- MSG = 'Use `%<recommended>s` instead of calling '\
22
+ MSG = 'Use `%<recommended>s` instead of calling ' \
23
23
  '`%<called>s` with a single argument.'
24
+ RESTRICT_ON_SEND = %i[receive_message_chain stub_chain].freeze
24
25
 
26
+ # @!method message_chain(node)
25
27
  def_node_matcher :message_chain, <<-PATTERN
26
28
  (send _ {:receive_message_chain :stub_chain} $_)
27
29
  PATTERN
28
30
 
31
+ # @!method single_key_hash?(node)
29
32
  def_node_matcher :single_key_hash?, '(hash pair)'
30
33
 
31
34
  def on_send(node)
@@ -39,6 +39,7 @@ module RuboCop
39
39
  }
40
40
  PATTERN
41
41
 
42
+ # @!method configured_response?(node)
42
43
  def_node_matcher :configured_response?, <<~PATTERN
43
44
  { :and_return :and_raise :and_throw :and_yield
44
45
  :and_call_original :and_wrap_original }
@@ -60,7 +61,7 @@ module RuboCop
60
61
  # @yield [RuboCop::AST::Node] expectation, method name, matcher
61
62
  def_node_matcher :expectation, <<~PATTERN
62
63
  (send
63
- $(send nil? $#{Expectations::ALL.node_pattern_union} ...)
64
+ $(send nil? $#Expectations.all ...)
64
65
  :to $_)
65
66
  PATTERN
66
67
 
@@ -13,16 +13,26 @@ module RuboCop
13
13
  #
14
14
  # @example
15
15
  # # bad
16
- # describe Foo do
17
- # subject(:bar) { baz }
16
+ # describe Article do
17
+ # subject(:article) { Article.new }
18
18
  #
19
- # before do
20
- # allow(bar).to receive(:qux?).and_return(true)
19
+ # it 'indicates that the author is unknown' do
20
+ # allow(article).to receive(:author).and_return(nil)
21
+ # expect(article.description).to include('by an unknown author')
22
+ # end
23
+ # end
24
+ #
25
+ # # good
26
+ # describe Article do
27
+ # subject(:article) { Article.new(author: nil) }
28
+ #
29
+ # it 'indicates that the author is unknown' do
30
+ # expect(article.description).to include('by an unknown author')
21
31
  # end
22
32
  # end
23
33
  #
24
34
  class SubjectStub < Base
25
- include RuboCop::RSpec::TopLevelGroup
35
+ include TopLevelGroup
26
36
 
27
37
  MSG = 'Do not stub methods of the object under test.'
28
38
 
@@ -66,11 +76,12 @@ module RuboCop
66
76
  (send nil? { :expect :allow } (send nil? {% :subject}))
67
77
  (send nil? :is_expected)
68
78
  }
69
- #{Runners::ALL.node_pattern_union}
79
+ #Runners.all
70
80
  #message_expectation_matcher?
71
81
  )
72
82
  PATTERN
73
83
 
84
+ # @!method message_expectation_matcher?(node)
74
85
  def_node_search :message_expectation_matcher?, <<-PATTERN
75
86
  (send nil? {
76
87
  :receive :receive_messages :receive_message_chain :have_received
@@ -32,7 +32,9 @@ module RuboCop
32
32
  # expect { do_something }.not_to raise_error
33
33
  class UnspecifiedException < Base
34
34
  MSG = 'Specify the exception being captured'
35
+ RESTRICT_ON_SEND = %i[to].freeze
35
36
 
37
+ # @!method empty_raise_error_or_exception(node)
36
38
  def_node_matcher :empty_raise_error_or_exception, <<-PATTERN
37
39
  (send
38
40
  (block
@@ -24,7 +24,7 @@ module RuboCop
24
24
  # let('user_name') { 'Adam' }
25
25
  class VariableDefinition < Base
26
26
  include ConfigurableEnforcedStyle
27
- include RuboCop::RSpec::Variable
27
+ include Variable
28
28
 
29
29
  MSG = 'Use %<style>s for variable names.'
30
30
 
@@ -42,7 +42,7 @@ module RuboCop
42
42
  class VariableName < Base
43
43
  include ConfigurableNaming
44
44
  include IgnoredPattern
45
- include RuboCop::RSpec::Variable
45
+ include Variable
46
46
 
47
47
  MSG = 'Use %<style>s for variable names.'
48
48
 
@@ -24,7 +24,9 @@ module RuboCop
24
24
  # end
25
25
  class VerifiedDoubles < Base
26
26
  MSG = 'Prefer using verifying doubles over normal doubles.'
27
+ RESTRICT_ON_SEND = %i[double spy].freeze
27
28
 
29
+ # @!method unverified_double(node)
28
30
  def_node_matcher :unverified_double, <<-PATTERN
29
31
  {(send nil? {:double :spy} $...)}
30
32
  PATTERN
@@ -14,11 +14,14 @@ module RuboCop
14
14
  class VoidExpect < Base
15
15
  MSG = 'Do not use `expect()` without `.to` or `.not_to`. ' \
16
16
  'Chain the methods or remove it.'
17
+ RESTRICT_ON_SEND = %i[expect].freeze
17
18
 
19
+ # @!method expect?(node)
18
20
  def_node_matcher :expect?, <<-PATTERN
19
21
  (send nil? :expect ...)
20
22
  PATTERN
21
23
 
24
+ # @!method expect_block?(node)
22
25
  def_node_matcher :expect_block?, <<-PATTERN
23
26
  (block #expect? (args) _body)
24
27
  PATTERN
@@ -17,10 +17,13 @@ module RuboCop
17
17
 
18
18
  MSG = 'Use `.and_yield`.'
19
19
 
20
+ # @!method method_on_stub?(node)
20
21
  def_node_search :method_on_stub?, '(send nil? :receive ...)'
21
22
 
23
+ # @!method block_arg(node)
22
24
  def_node_matcher :block_arg, '(args (blockarg $_))'
23
25
 
26
+ # @!method block_call?(node)
24
27
  def_node_matcher :block_call?, '(send (lvar %) :call ...)'
25
28
 
26
29
  def on_block(node)
@@ -52,7 +52,6 @@ require_relative 'rspec/implicit_expect'
52
52
  require_relative 'rspec/implicit_subject'
53
53
  require_relative 'rspec/instance_spy'
54
54
  require_relative 'rspec/instance_variable'
55
- require_relative 'rspec/invalid_predicate_matcher'
56
55
  require_relative 'rspec/it_behaves_like'
57
56
  require_relative 'rspec/iterated_expectation'
58
57
  require_relative 'rspec/leading_subject'
@@ -4,7 +4,7 @@ module RuboCop
4
4
  module RSpec
5
5
  # Shared behavior for aligning braces for single line lets
6
6
  class AlignLetBrace
7
- include RuboCop::RSpec::Language::NodePattern
7
+ include RuboCop::RSpec::Language
8
8
 
9
9
  def initialize(root, token)
10
10
  @root = root
@@ -4,9 +4,9 @@ module RuboCop
4
4
  module RSpec
5
5
  # Wrapper for RSpec DSL methods
6
6
  class Concept
7
+ extend RuboCop::NodePattern::Macros
8
+ extend Language::NodePattern
7
9
  include Language
8
- include Language::NodePattern
9
- extend NodePattern::Macros
10
10
 
11
11
  def initialize(node)
12
12
  @node = node
@@ -6,7 +6,7 @@ module RuboCop
6
6
  module RSpec
7
7
  # Builds a YAML config file from two config hashes
8
8
  class ConfigFormatter
9
- NAMESPACES = /^(RSpec|Capybara|FactoryBot|Rails)/.freeze
9
+ EXTENSION_ROOT_DEPARTMENT = %r{^(RSpec/)}.freeze
10
10
  STYLE_GUIDE_BASE_URL = 'https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/'
11
11
 
12
12
  def initialize(config, descriptions)
@@ -15,7 +15,9 @@ module RuboCop
15
15
  end
16
16
 
17
17
  def dump
18
- YAML.dump(unified_config).gsub(NAMESPACES, "\n\\1")
18
+ YAML.dump(unified_config)
19
+ .gsub(EXTENSION_ROOT_DEPARTMENT, "\n\\1")
20
+ .gsub(/^(\s+)- /, '\1 - ')
19
21
  end
20
22
 
21
23
  private
@@ -29,7 +31,7 @@ module RuboCop
29
31
  end
30
32
 
31
33
  def cops
32
- (descriptions.keys | config.keys).grep(NAMESPACES)
34
+ (descriptions.keys | config.keys).grep(EXTENSION_ROOT_DEPARTMENT)
33
35
  end
34
36
 
35
37
  attr_reader :config, :descriptions
@@ -6,7 +6,8 @@ module RuboCop
6
6
  # Helper methods to move a node
7
7
  class MoveNode
8
8
  include RuboCop::Cop::RangeHelp
9
- include RuboCop::RSpec::FinalEndLocation
9
+ include RuboCop::Cop::RSpec::CommentsHelp
10
+ include RuboCop::Cop::RSpec::FinalEndLocation
10
11
 
11
12
  attr_reader :original, :corrector, :processed_source
12
13
 
@@ -17,20 +18,16 @@ module RuboCop
17
18
  end
18
19
 
19
20
  def move_before(other)
20
- position = other.loc.expression
21
- indent = ' ' * other.loc.column
22
- newline_indent = "\n#{indent}"
21
+ position = start_line_position(other)
23
22
 
24
- corrector.insert_before(position, source(original) + newline_indent)
23
+ corrector.insert_before(position, "#{source(original)}\n")
25
24
  corrector.remove(node_range_with_surrounding_space(original))
26
25
  end
27
26
 
28
27
  def move_after(other)
29
- position = final_end_location(other)
30
- indent = ' ' * other.loc.column
31
- newline_indent = "\n#{indent}"
28
+ position = end_line_position(other)
32
29
 
33
- corrector.insert_after(position, newline_indent + source(original))
30
+ corrector.insert_after(position, "\n#{source(original)}")
34
31
  corrector.remove(node_range_with_surrounding_space(original))
35
32
  end
36
33
 
@@ -41,7 +38,7 @@ module RuboCop
41
38
  end
42
39
 
43
40
  def node_range(node)
44
- node.loc.expression.with(end_pos: final_end_location(node).end_pos)
41
+ source_range_with_comment(node)
45
42
  end
46
43
 
47
44
  def node_range_with_surrounding_space(node)
@@ -4,8 +4,13 @@ module RuboCop
4
4
  module RSpec
5
5
  # Wrapper for RSpec examples
6
6
  class Example < Concept
7
+ # @!method extract_doc_string(node)
7
8
  def_node_matcher :extract_doc_string, '(send _ _ $_ ...)'
9
+
10
+ # @!method extract_metadata(node)
8
11
  def_node_matcher :extract_metadata, '(send _ _ _ $...)'
12
+
13
+ # @!method extract_implementation(node)
9
14
  def_node_matcher :extract_implementation, '(block send args $_)'
10
15
 
11
16
  def doc_string
@@ -10,9 +10,14 @@ module RuboCop
10
10
  #
11
11
  # Selectors which indicate that we should stop searching
12
12
  #
13
- def_node_matcher :scope_change?, (
14
- ExampleGroups::ALL + SharedGroups::ALL + Includes::ALL
15
- ).block_pattern
13
+ def_node_matcher :scope_change?,
14
+ block_pattern(<<~PATTERN)
15
+ {
16
+ #SharedGroups.all
17
+ #ExampleGroups.all
18
+ #Includes.all
19
+ }
20
+ PATTERN
16
21
 
17
22
  def lets
18
23
  find_all_in_scope(node, :let?)
@@ -23,11 +28,15 @@ module RuboCop
23
28
  end
24
29
 
25
30
  def examples
26
- find_all_in_scope(node, :example?).map(&Example.public_method(:new))
31
+ find_all_in_scope(node, :example?).map do |node|
32
+ Example.new(node)
33
+ end
27
34
  end
28
35
 
29
36
  def hooks
30
- find_all_in_scope(node, :hook?).map(&Hook.public_method(:new))
37
+ find_all_in_scope(node, :hook?).map do |node|
38
+ Hook.new(node)
39
+ end
31
40
  end
32
41
 
33
42
  private
@@ -37,6 +46,7 @@ module RuboCop
37
46
  # Searches node and halts when a scope change is detected
38
47
  #
39
48
  # @param node [RuboCop::AST::Node] node to recursively search
49
+ # @param predicate [Symbol] method to call with node as argument
40
50
  #
41
51
  # @return [Array<RuboCop::AST::Node>] discovered nodes
42
52
  def find_all_in_scope(node, predicate)
@@ -4,6 +4,7 @@ module RuboCop
4
4
  module RSpec
5
5
  # Wrapper for RSpec hook
6
6
  class Hook < Concept
7
+ # @!method extract_metadata(node)
7
8
  def_node_matcher :extract_metadata, <<~PATTERN
8
9
  (block
9
10
  (send _ _ #valid_scope? ? $...) ...
@@ -44,7 +45,7 @@ module RuboCop
44
45
  private
45
46
 
46
47
  def valid_scope?(node)
47
- node&.sym_type? && Hooks::Scopes::ALL.include?(node.value)
48
+ node&.sym_type? && Language::HookScopes.all(node.value)
48
49
  end
49
50
 
50
51
  def transform_metadata(meta)
@@ -6,9 +6,11 @@ module RuboCop
6
6
  # bit of our configuration.
7
7
  module Inject
8
8
  def self.defaults!
9
- path = CONFIG_DEFAULT.to_s
9
+ project_root = Pathname.new(__dir__).parent.parent.parent.expand_path
10
+ config_default = project_root.join('config', 'default.yml')
11
+ path = config_default.to_s
10
12
  hash = ConfigLoader.send(:load_yaml_configuration, path)
11
- config = Config.new(hash, path)
13
+ config = RuboCop::Config.new(hash, path)
12
14
  puts "configuration from #{path}" if ConfigLoader.debug?
13
15
  config = ConfigLoader.merge_with_default(config, path)
14
16
  ConfigLoader.instance_variable_set(:@default_configuration, config)
@@ -2,152 +2,196 @@
2
2
 
3
3
  module RuboCop
4
4
  module RSpec
5
- # RSpec public API methods that are commonly used in cops
5
+ # Contains node matchers for common RSpec DSL.
6
+ #
7
+ # RSpec allows for configuring aliases for commonly used DSL elements, e.g.
8
+ # example groups and hooks. It is possible to configure RuboCop RSpec to
9
+ # be able to properly detect these elements in the `RSpec/Language` section
10
+ # of the RuboCop YAML configuration file.
11
+ #
12
+ # In addition to providing useful matchers, this class is responsible for
13
+ # using the configured aliases.
6
14
  module Language
7
- # Set of method selectors
8
- class SelectorSet
9
- def initialize(selectors)
10
- @selectors = selectors.freeze
11
- freeze
12
- end
13
-
14
- def ==(other)
15
- selectors.eql?(other.selectors)
16
- end
17
-
18
- def +(other)
19
- self.class.new(selectors + other.selectors)
20
- end
21
-
22
- def include?(selector)
23
- selectors.include?(selector)
24
- end
15
+ extend RuboCop::NodePattern::Macros
16
+ extend NodePattern
25
17
 
26
- def block_pattern
27
- "(block #{send_pattern} ...)"
28
- end
29
-
30
- def block_pass_pattern
31
- "(send #rspec? #{node_pattern_union} _ block_pass)"
32
- end
18
+ class << self
19
+ attr_accessor :config
20
+ end
33
21
 
34
- def block_or_block_pass_pattern
35
- "{#{block_pattern} #{block_pass_pattern}}"
22
+ # @!method rspec?(node)
23
+ def_node_matcher :rspec?, '{(const {nil? cbase} :RSpec) nil?}'
24
+
25
+ # @!method example_group?(node)
26
+ def_node_matcher :example_group?, block_pattern('#ExampleGroups.all')
27
+
28
+ # @!method shared_group?(node)
29
+ def_node_matcher :shared_group?, block_pattern('#SharedGroups.all')
30
+
31
+ # @!method spec_group?(node)
32
+ def_node_matcher :spec_group?,
33
+ block_pattern('{#SharedGroups.all #ExampleGroups.all}')
34
+
35
+ # @!method example_group_with_body?(node)
36
+ def_node_matcher :example_group_with_body?, <<-PATTERN
37
+ (block #{send_pattern('#ExampleGroups.all')} args !nil?)
38
+ PATTERN
39
+
40
+ # @!method example?(node)
41
+ def_node_matcher :example?, block_pattern('#Examples.all')
42
+
43
+ # @!method hook?(node)
44
+ def_node_matcher :hook?, block_pattern('#Hooks.all')
45
+
46
+ # @!method let?(node)
47
+ def_node_matcher :let?, <<-PATTERN
48
+ {
49
+ #{block_pattern('#Helpers.all')}
50
+ (send #rspec? #Helpers.all _ block_pass)
51
+ }
52
+ PATTERN
53
+
54
+ # @!method include?(node)
55
+ def_node_matcher :include?, <<-PATTERN
56
+ {
57
+ #{send_pattern('#Includes.all')}
58
+ #{block_pattern('#Includes.all')}
59
+ }
60
+ PATTERN
61
+
62
+ # @!method subject?(node)
63
+ def_node_matcher :subject?, block_pattern('#Subjects.all')
64
+
65
+ module ExampleGroups # :nodoc:
66
+ class << self
67
+ def all(element)
68
+ regular(element) ||
69
+ skipped(element) ||
70
+ focused(element)
71
+ end
72
+
73
+ def regular(element)
74
+ Language.config['ExampleGroups']['Regular'].include?(element.to_s)
75
+ end
76
+
77
+ def focused(element)
78
+ Language.config['ExampleGroups']['Focused'].include?(element.to_s)
79
+ end
80
+
81
+ def skipped(element)
82
+ Language.config['ExampleGroups']['Skipped'].include?(element.to_s)
83
+ end
36
84
  end
85
+ end
37
86
 
38
- def send_pattern
39
- "(send #rspec? #{node_pattern_union} ...)"
87
+ module Examples # :nodoc:
88
+ class << self
89
+ def all(element)
90
+ regular(element) ||
91
+ focused(element) ||
92
+ skipped(element) ||
93
+ pending(element)
94
+ end
95
+
96
+ def regular(element)
97
+ Language.config['Examples']['Regular'].include?(element.to_s)
98
+ end
99
+
100
+ def focused(element)
101
+ Language.config['Examples']['Focused'].include?(element.to_s)
102
+ end
103
+
104
+ def skipped(element)
105
+ Language.config['Examples']['Skipped'].include?(element.to_s)
106
+ end
107
+
108
+ def pending(element)
109
+ Language.config['Examples']['Pending'].include?(element.to_s)
110
+ end
40
111
  end
112
+ end
41
113
 
42
- def send_or_block_or_block_pass_pattern
43
- "{#{send_pattern} #{block_pattern} #{block_pass_pattern}}"
114
+ module Expectations # :nodoc:
115
+ def self.all(element)
116
+ Language.config['Expectations'].include?(element.to_s)
44
117
  end
118
+ end
45
119
 
46
- def node_pattern_union
47
- "{#{node_pattern}}"
120
+ module Helpers # :nodoc:
121
+ def self.all(element)
122
+ Language.config['Helpers'].include?(element.to_s)
48
123
  end
124
+ end
49
125
 
50
- def node_pattern
51
- selectors.map(&:inspect).join(' ')
126
+ module Hooks # :nodoc:
127
+ def self.all(element)
128
+ Language.config['Hooks'].include?(element.to_s)
52
129
  end
130
+ end
53
131
 
54
- def to_a
55
- selectors
132
+ module HookScopes # :nodoc:
133
+ def self.all(element)
134
+ Language.config['HookScopes'].include?(element.to_s)
56
135
  end
57
-
58
- protected
59
-
60
- attr_reader :selectors
61
136
  end
62
137
 
63
- module ExampleGroups
64
- GROUPS = SelectorSet.new(%i[describe context feature example_group])
65
- SKIPPED = SelectorSet.new(%i[xdescribe xcontext xfeature])
66
- FOCUSED = SelectorSet.new(%i[fdescribe fcontext ffeature])
138
+ module Includes # :nodoc:
139
+ class << self
140
+ def all(element)
141
+ examples(element) ||
142
+ context(element)
143
+ end
67
144
 
68
- ALL = GROUPS + SKIPPED + FOCUSED
69
- end
145
+ def examples(element)
146
+ Language.config['Includes']['Examples'].include?(element.to_s)
147
+ end
70
148
 
71
- module SharedGroups
72
- EXAMPLES = SelectorSet.new(%i[shared_examples shared_examples_for])
73
- CONTEXT = SelectorSet.new(%i[shared_context])
74
-
75
- ALL = EXAMPLES + CONTEXT
149
+ def context(element)
150
+ Language.config['Includes']['Context'].include?(element.to_s)
151
+ end
152
+ end
76
153
  end
77
154
 
78
- module Includes
79
- EXAMPLES = SelectorSet.new(
80
- %i[
81
- it_behaves_like
82
- it_should_behave_like
83
- include_examples
84
- ]
85
- )
86
- CONTEXT = SelectorSet.new(%i[include_context])
87
-
88
- ALL = EXAMPLES + CONTEXT
155
+ module Runners # :nodoc:
156
+ def self.all(element)
157
+ Language.config['Runners'].include?(element.to_s)
158
+ end
89
159
  end
90
160
 
91
- module Examples
92
- EXAMPLES = SelectorSet.new(%i[it specify example scenario its])
93
- FOCUSED = SelectorSet.new(%i[fit fspecify fexample fscenario focus])
94
- SKIPPED = SelectorSet.new(%i[xit xspecify xexample xscenario skip])
95
- PENDING = SelectorSet.new(%i[pending])
161
+ module SharedGroups # :nodoc:
162
+ class << self
163
+ def all(element)
164
+ examples(element) ||
165
+ context(element)
166
+ end
96
167
 
97
- ALL = EXAMPLES + FOCUSED + SKIPPED + PENDING
98
- end
168
+ def examples(element)
169
+ Language.config['SharedGroups']['Examples'].include?(element.to_s)
170
+ end
99
171
 
100
- module Hooks
101
- ALL = SelectorSet.new(
102
- %i[
103
- prepend_before
104
- before
105
- append_before
106
- around
107
- prepend_after
108
- after
109
- append_after
110
- ]
111
- )
112
-
113
- module Scopes
114
- ALL = SelectorSet.new(
115
- %i[
116
- each
117
- example
118
- context
119
- all
120
- suite
121
- ]
122
- )
172
+ def context(element)
173
+ Language.config['SharedGroups']['Context'].include?(element.to_s)
174
+ end
123
175
  end
124
176
  end
125
177
 
126
- module Helpers
127
- ALL = SelectorSet.new(%i[let let!])
128
- end
129
-
130
- module Subject
131
- ALL = SelectorSet.new(%i[subject subject!])
132
- end
133
-
134
- module Expectations
135
- ALL = SelectorSet.new(%i[expect is_expected expect_any_instance_of])
178
+ module Subjects # :nodoc:
179
+ def self.all(element)
180
+ Language.config['Subjects'].include?(element.to_s)
181
+ end
136
182
  end
137
183
 
138
- module Runners
139
- ALL = SelectorSet.new(%i[to to_not not_to])
184
+ # This is used in Dialect and DescribeClass cops to detect RSpec blocks.
185
+ module ALL # :nodoc:
186
+ def self.all(element)
187
+ [ExampleGroups, Examples, Expectations, Helpers, Hooks, Includes,
188
+ Runners, SharedGroups, Subjects]
189
+ .find { |concept| concept.all(element) }
190
+ end
140
191
  end
141
192
 
142
- ALL =
143
- ExampleGroups::ALL +
144
- SharedGroups::ALL +
145
- Examples::ALL +
146
- Hooks::ALL +
147
- Helpers::ALL +
148
- Subject::ALL +
149
- Expectations::ALL +
150
- Runners::ALL
193
+ private_constant :ExampleGroups, :Examples, :Expectations, :Hooks,
194
+ :Includes, :Runners, :SharedGroups, :ALL
151
195
  end
152
196
  end
153
197
  end