rubocop-rspec 1.15.1 → 1.16.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (89) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +20 -1
  3. data/Gemfile +0 -1
  4. data/config/default.yml +105 -0
  5. data/lib/rubocop-rspec.rb +27 -0
  6. data/lib/rubocop/cop/rspec/align_left_let_brace.rb +51 -0
  7. data/lib/rubocop/cop/rspec/align_right_let_brace.rb +51 -0
  8. data/lib/rubocop/cop/rspec/any_instance.rb +1 -1
  9. data/lib/rubocop/cop/rspec/cop.rb +4 -2
  10. data/lib/rubocop/cop/rspec/expect_in_hook.rb +61 -0
  11. data/lib/rubocop/cop/rspec/factory_girl/dynamic_attribute_defined_statically.rb +84 -0
  12. data/lib/rubocop/cop/rspec/hook_argument.rb +11 -5
  13. data/lib/rubocop/cop/rspec/invalid_predicate_matcher.rb +42 -0
  14. data/lib/rubocop/cop/rspec/let_before_examples.rb +66 -0
  15. data/lib/rubocop/cop/rspec/multiple_expectations.rb +3 -5
  16. data/lib/rubocop/cop/rspec/multiple_subjects.rb +80 -0
  17. data/lib/rubocop/cop/rspec/named_subject.rb +5 -6
  18. data/lib/rubocop/cop/rspec/overwriting_setup.rb +1 -1
  19. data/lib/rubocop/cop/rspec/predicate_matcher.rb +337 -0
  20. data/lib/rubocop/cop/rspec/return_from_stub.rb +83 -0
  21. data/lib/rubocop/cop/rspec/void_expect.rb +52 -0
  22. data/lib/rubocop/rspec/align_let_brace.rb +64 -0
  23. data/lib/rubocop/rspec/config_formatter.rb +7 -4
  24. data/lib/rubocop/rspec/description_extractor.rb +2 -2
  25. data/lib/rubocop/rspec/example_group.rb +25 -2
  26. data/lib/rubocop/rspec/factory_girl.rb +7 -0
  27. data/lib/rubocop/rspec/language.rb +6 -1
  28. data/lib/rubocop/rspec/version.rb +1 -1
  29. data/rubocop-rspec.gemspec +1 -4
  30. data/spec/project/default_config_spec.rb +8 -4
  31. data/spec/rubocop/cop/rspec/align_left_let_brace_spec.rb +62 -0
  32. data/spec/rubocop/cop/rspec/align_right_let_brace_spec.rb +62 -0
  33. data/spec/rubocop/cop/rspec/any_instance_spec.rb +3 -3
  34. data/spec/rubocop/cop/rspec/around_block_spec.rb +11 -11
  35. data/spec/rubocop/cop/rspec/be_eql_spec.rb +7 -7
  36. data/spec/rubocop/cop/rspec/before_after_all_spec.rb +4 -4
  37. data/spec/rubocop/cop/rspec/cop_spec.rb +7 -7
  38. data/spec/rubocop/cop/rspec/describe_class_spec.rb +18 -18
  39. data/spec/rubocop/cop/rspec/describe_method_spec.rb +4 -4
  40. data/spec/rubocop/cop/rspec/describe_symbol_spec.rb +6 -6
  41. data/spec/rubocop/cop/rspec/described_class_spec.rb +18 -18
  42. data/spec/rubocop/cop/rspec/empty_example_group_spec.rb +5 -5
  43. data/spec/rubocop/cop/rspec/empty_line_after_final_let_spec.rb +9 -9
  44. data/spec/rubocop/cop/rspec/empty_line_after_subject_spec.rb +5 -5
  45. data/spec/rubocop/cop/rspec/example_length_spec.rb +6 -6
  46. data/spec/rubocop/cop/rspec/example_wording_spec.rb +10 -10
  47. data/spec/rubocop/cop/rspec/expect_actual_spec.rb +10 -10
  48. data/spec/rubocop/cop/rspec/expect_in_hook_spec.rb +79 -0
  49. data/spec/rubocop/cop/rspec/expect_output_spec.rb +7 -7
  50. data/spec/rubocop/cop/rspec/factory_girl/dynamic_attribute_defined_statically_spec.rb +87 -0
  51. data/spec/rubocop/cop/rspec/file_path_spec.rb +29 -29
  52. data/spec/rubocop/cop/rspec/focus_spec.rb +6 -6
  53. data/spec/rubocop/cop/rspec/hook_argument_spec.rb +35 -23
  54. data/spec/rubocop/cop/rspec/implicit_expect_spec.rb +10 -10
  55. data/spec/rubocop/cop/rspec/instance_spy_spec.rb +4 -4
  56. data/spec/rubocop/cop/rspec/instance_variable_spec.rb +7 -7
  57. data/spec/rubocop/cop/rspec/invalid_predicate_matcher_spec.rb +37 -0
  58. data/spec/rubocop/cop/rspec/it_behaves_like_spec.rb +4 -4
  59. data/spec/rubocop/cop/rspec/iterated_expectation_spec.rb +8 -8
  60. data/spec/rubocop/cop/rspec/leading_subject_spec.rb +5 -5
  61. data/spec/rubocop/cop/rspec/let_before_examples_spec.rb +83 -0
  62. data/spec/rubocop/cop/rspec/let_setup_spec.rb +4 -4
  63. data/spec/rubocop/cop/rspec/message_chain_spec.rb +2 -2
  64. data/spec/rubocop/cop/rspec/message_expectation_spec.rb +4 -4
  65. data/spec/rubocop/cop/rspec/message_spies_spec.rb +18 -18
  66. data/spec/rubocop/cop/rspec/multiple_describes_spec.rb +3 -3
  67. data/spec/rubocop/cop/rspec/multiple_expectations_spec.rb +45 -9
  68. data/spec/rubocop/cop/rspec/multiple_subjects_spec.rb +96 -0
  69. data/spec/rubocop/cop/rspec/named_subject_spec.rb +4 -4
  70. data/spec/rubocop/cop/rspec/nested_groups_spec.rb +3 -3
  71. data/spec/rubocop/cop/rspec/not_to_not_spec.rb +4 -4
  72. data/spec/rubocop/cop/rspec/overwriting_setup_spec.rb +4 -4
  73. data/spec/rubocop/cop/rspec/predicate_matcher_spec.rb +335 -0
  74. data/spec/rubocop/cop/rspec/repeated_description_spec.rb +5 -5
  75. data/spec/rubocop/cop/rspec/repeated_example_spec.rb +5 -5
  76. data/spec/rubocop/cop/rspec/return_from_stub_spec.rb +85 -0
  77. data/spec/rubocop/cop/rspec/scattered_let_spec.rb +2 -2
  78. data/spec/rubocop/cop/rspec/scattered_setup_spec.rb +8 -8
  79. data/spec/rubocop/cop/rspec/shared_context_spec.rb +10 -10
  80. data/spec/rubocop/cop/rspec/single_argument_message_chain_spec.rb +10 -10
  81. data/spec/rubocop/cop/rspec/subject_stub_spec.rb +9 -9
  82. data/spec/rubocop/cop/rspec/verified_doubles_spec.rb +7 -7
  83. data/spec/rubocop/cop/rspec/void_expect_spec.rb +47 -0
  84. data/spec/rubocop/rspec/config_formatter_spec.rb +2 -0
  85. data/spec/spec_helper.rb +1 -1
  86. data/spec/support/expect_offense.rb +17 -0
  87. metadata +39 -51
  88. data/spec/expect_violation/expectation_spec.rb +0 -85
  89. data/spec/support/expect_violation.rb +0 -170
@@ -0,0 +1,52 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RuboCop
4
+ module Cop
5
+ module RSpec
6
+ # This cop checks void `expect()`.
7
+ #
8
+ # @example
9
+ # # bad
10
+ # expect(something)
11
+ #
12
+ # # good
13
+ # expect(something).to be(1)
14
+ class VoidExpect < Cop
15
+ MSG = 'Do not use `expect()` without `.to` or `.not_to`. ' \
16
+ 'Chain the methods or remove it.'.freeze
17
+
18
+ def_node_matcher :expect?, <<-PATTERN
19
+ (send nil :expect ...)
20
+ PATTERN
21
+
22
+ def_node_matcher :expect_block?, <<-PATTERN
23
+ (block #expect? (args) _body)
24
+ PATTERN
25
+
26
+ def on_send(node)
27
+ return unless expect?(node)
28
+ check_expect(node)
29
+ end
30
+
31
+ def on_block(node)
32
+ return unless expect_block?(node)
33
+ check_expect(node)
34
+ end
35
+
36
+ private
37
+
38
+ def check_expect(node)
39
+ return unless void?(node)
40
+ add_offense(node, :expression)
41
+ end
42
+
43
+ def void?(expect)
44
+ parent = expect.parent
45
+ return true unless parent
46
+ return true if parent.begin_type?
47
+ return true if parent.block_type? && parent.children[2] == expect
48
+ end
49
+ end
50
+ end
51
+ end
52
+ end
@@ -0,0 +1,64 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RuboCop
4
+ module RSpec
5
+ # Shared behavior for aligning braces for single line lets
6
+ class AlignLetBrace
7
+ extend NodePattern::Macros
8
+
9
+ def_node_matcher :let?, Language::Helpers::ALL.block_pattern.freeze
10
+
11
+ def initialize(root, token)
12
+ @root = root
13
+ @token = token
14
+ end
15
+
16
+ def offending_tokens
17
+ single_line_lets.reject do |let|
18
+ target_column_for(let) == let_token(let).column
19
+ end
20
+ end
21
+
22
+ def indent_for(node)
23
+ ' ' * (target_column_for(node) - let_token(node).column)
24
+ end
25
+
26
+ private
27
+
28
+ def let_token(node)
29
+ node.loc.public_send(token)
30
+ end
31
+
32
+ def target_column_for(let)
33
+ let_group_for(let).map { |member| let_token(member).column }.max
34
+ end
35
+
36
+ def let_group_for(let)
37
+ adjacent_let_chunks.detect do |chunk|
38
+ chunk.any? do |member|
39
+ member == let && member.loc.line == let.loc.line
40
+ end
41
+ end
42
+ end
43
+
44
+ def adjacent_let_chunks
45
+ last_line = nil
46
+
47
+ single_line_lets.chunk do |node|
48
+ line = node.loc.line
49
+ last_line = (line if last_line.nil? || last_line + 1 == line)
50
+ last_line.nil?
51
+ end.map(&:last)
52
+ end
53
+
54
+ def single_line_lets
55
+ @single_line_lets ||=
56
+ root.each_node(:block).select do |node|
57
+ let?(node) && node.single_line?
58
+ end
59
+ end
60
+
61
+ attr_reader :root, :token
62
+ end
63
+ end
64
+ end
@@ -4,7 +4,8 @@ module RuboCop
4
4
  module RSpec
5
5
  # Builds a YAML config file from two config hashes
6
6
  class ConfigFormatter
7
- NAMESPACE = 'RSpec'.freeze
7
+ NAMESPACES = /^(#{Regexp.union('RSpec', 'FactoryGirl')})/
8
+ STYLE_GUIDE_BASE_URL = 'http://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/'.freeze
8
9
 
9
10
  def initialize(config, descriptions)
10
11
  @config = config
@@ -12,19 +13,21 @@ module RuboCop
12
13
  end
13
14
 
14
15
  def dump
15
- YAML.dump(unified_config).gsub(/^#{NAMESPACE}/, "\n#{NAMESPACE}")
16
+ YAML.dump(unified_config).gsub(NAMESPACES, "\n\\1")
16
17
  end
17
18
 
18
19
  private
19
20
 
20
21
  def unified_config
21
22
  cops.each_with_object(config.dup) do |cop, unified|
22
- unified[cop] = config.fetch(cop).merge(descriptions.fetch(cop))
23
+ unified[cop] = config.fetch(cop)
24
+ .merge(descriptions.fetch(cop))
25
+ .merge('StyleGuide' => STYLE_GUIDE_BASE_URL + cop)
23
26
  end
24
27
  end
25
28
 
26
29
  def cops
27
- (descriptions.keys + config.keys).uniq.grep(/\A#{NAMESPACE}/)
30
+ (descriptions.keys | config.keys).grep(NAMESPACES)
28
31
  end
29
32
 
30
33
  attr_reader :config, :descriptions
@@ -19,7 +19,7 @@ module RuboCop
19
19
 
20
20
  # Decorator of a YARD code object for working with documented rspec cops
21
21
  class CodeObject
22
- COP_NAMESPACE = 'RuboCop::Cop::RSpec'.freeze
22
+ RSPEC_NAMESPACE = 'RuboCop::Cop::RSpec'.freeze
23
23
 
24
24
  def initialize(yardoc)
25
25
  @yardoc = yardoc
@@ -54,7 +54,7 @@ module RuboCop
54
54
  end
55
55
 
56
56
  def rspec_cop_namespace?
57
- documented_constant.start_with?(COP_NAMESPACE)
57
+ documented_constant.start_with?(RSPEC_NAMESPACE)
58
58
  end
59
59
 
60
60
  def documented_constant
@@ -10,8 +10,9 @@ 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).block_pattern
13
+ def_node_matcher :scope_change?, (
14
+ ExampleGroups::ALL + SharedGroups::ALL + Includes::ALL
15
+ ).block_pattern
15
16
 
16
17
  # @!method hook(node)
17
18
  #
@@ -20,6 +21,12 @@ module RuboCop
20
21
  (block {$(send nil #{Hooks::ALL.node_pattern_union} ...)} ...)
21
22
  PATTERN
22
23
 
24
+ def_node_matcher :subject, Subject::ALL.block_pattern
25
+
26
+ def subjects
27
+ subjects_in_scope(node)
28
+ end
29
+
23
30
  def examples
24
31
  examples_in_scope(node).map(&Example.public_method(:new))
25
32
  end
@@ -30,6 +37,22 @@ module RuboCop
30
37
 
31
38
  private
32
39
 
40
+ def subjects_in_scope(node)
41
+ node.each_child_node.flat_map do |child|
42
+ find_subjects(child)
43
+ end
44
+ end
45
+
46
+ def find_subjects(node)
47
+ return [] if scope_change?(node)
48
+
49
+ if subject(node)
50
+ [node]
51
+ else
52
+ subjects_in_scope(node)
53
+ end
54
+ end
55
+
33
56
  def hooks_in_scope(node)
34
57
  node.each_child_node.flat_map do |child|
35
58
  find_hooks(child)
@@ -0,0 +1,7 @@
1
+ module RuboCop
2
+ module RSpec
3
+ # RuboCop FactoryGirl project namespace
4
+ module FactoryGirl
5
+ end
6
+ end
7
+ end
@@ -106,13 +106,18 @@ module RuboCop
106
106
  ALL = SelectorSet.new(%i[subject subject!])
107
107
  end
108
108
 
109
+ module Expectations
110
+ ALL = SelectorSet.new(%i[expect is_expected expect_any_instance_of])
111
+ end
112
+
109
113
  ALL =
110
114
  ExampleGroups::ALL +
111
115
  SharedGroups::ALL +
112
116
  Examples::ALL +
113
117
  Hooks::ALL +
114
118
  Helpers::ALL +
115
- Subject::ALL
119
+ Subject::ALL +
120
+ Expectations::ALL
116
121
  end
117
122
  end
118
123
  end
@@ -4,7 +4,7 @@ module RuboCop
4
4
  module RSpec
5
5
  # Version information for the RSpec RuboCop plugin.
6
6
  module Version
7
- STRING = '1.15.1'.freeze
7
+ STRING = '1.16.0'.freeze
8
8
  end
9
9
  end
10
10
  end
@@ -34,13 +34,10 @@ Gem::Specification.new do |spec|
34
34
  spec.test_files = spec.files.grep(%r{^spec/})
35
35
  spec.extra_rdoc_files = ['MIT-LICENSE.md', 'README.md']
36
36
 
37
- spec.add_runtime_dependency 'rubocop', '>= 0.42.0'
37
+ spec.add_runtime_dependency 'rubocop', '>= 0.49.0'
38
38
 
39
39
  spec.add_development_dependency 'rake'
40
40
  spec.add_development_dependency 'rspec', '>= 3.4'
41
41
  spec.add_development_dependency 'simplecov'
42
- spec.add_development_dependency 'anima'
43
- spec.add_development_dependency 'concord'
44
- spec.add_development_dependency 'adamantium'
45
42
  spec.add_development_dependency 'yard'
46
43
  end
@@ -4,14 +4,18 @@ RSpec.describe 'config/default.yml' do
4
4
  end
5
5
 
6
6
  let(:cop_names) do
7
- glob = SpecHelper::ROOT.join('lib', 'rubocop', 'cop', 'rspec', '*.rb')
8
-
7
+ namespaces = {
8
+ 'rspec' => 'RSpec',
9
+ 'factory_girl' => 'FactoryGirl'
10
+ }
11
+ glob = SpecHelper::ROOT.join('lib', 'rubocop', 'cop',
12
+ 'rspec', '{,factory_girl/}*.rb')
9
13
  cop_names =
10
14
  Pathname.glob(glob).map do |file|
11
15
  file_name = file.basename('.rb').to_s
12
16
  cop_name = file_name.gsub(/(^|_)(.)/) { Regexp.last_match(2).upcase }
13
-
14
- "RSpec/#{cop_name}"
17
+ namespace = namespaces[file.dirname.basename.to_s]
18
+ "#{namespace}/#{cop_name}"
15
19
  end
16
20
 
17
21
  cop_names - %w[RSpec/Cop]
@@ -0,0 +1,62 @@
1
+ RSpec.describe RuboCop::Cop::RSpec::AlignLeftLetBrace do
2
+ subject(:cop) { described_class.new }
3
+
4
+ it 'registers offense for unaligned braces' do
5
+ expect_offense(<<-RUBY)
6
+ let(:foo) { bar }
7
+ ^ Align left let brace
8
+ let(:hi) { baz }
9
+ ^ Align left let brace
10
+ let(:blahblah) { baz }
11
+
12
+ let(:thing) { ignore_this }
13
+ let(:other) {
14
+ ignore_this_too
15
+ }
16
+
17
+ describe 'blah' do
18
+ let(:blahblah) { baz }
19
+ let(:blah) { thing }
20
+ ^ Align left let brace
21
+ let(:a) { thing }
22
+ ^ Align left let brace
23
+ end
24
+ RUBY
25
+ end
26
+
27
+ offensive_source = <<-RUBY
28
+ let(:foo) { bar }
29
+ let(:hi) { baz }
30
+ let(:blahblah) { baz }
31
+
32
+ let(:thing) { ignore_this }
33
+ let(:other) {
34
+ ignore_this_too
35
+ }
36
+
37
+ describe 'blah' do
38
+ let(:long_name) { thing }
39
+ let(:blah) { thing }
40
+ let(:a) { thing }
41
+ end
42
+ RUBY
43
+
44
+ corrected_source = <<-RUBY
45
+ let(:foo) { bar }
46
+ let(:hi) { baz }
47
+ let(:blahblah) { baz }
48
+
49
+ let(:thing) { ignore_this }
50
+ let(:other) {
51
+ ignore_this_too
52
+ }
53
+
54
+ describe 'blah' do
55
+ let(:long_name) { thing }
56
+ let(:blah) { thing }
57
+ let(:a) { thing }
58
+ end
59
+ RUBY
60
+
61
+ include_examples 'autocorrect', offensive_source, corrected_source
62
+ end
@@ -0,0 +1,62 @@
1
+ RSpec.describe RuboCop::Cop::RSpec::AlignRightLetBrace do
2
+ subject(:cop) { described_class.new }
3
+
4
+ it 'registers offense for unaligned braces' do
5
+ expect_offense(<<-RUBY)
6
+ let(:foo) { a }
7
+ ^ Align right let brace
8
+ let(:hi) { ab }
9
+ ^ Align right let brace
10
+ let(:blahblah) { abcd }
11
+
12
+ let(:thing) { ignore_this }
13
+ let(:other) {
14
+ ignore_this_too
15
+ }
16
+
17
+ describe 'blah' do
18
+ let(:blahblah) { a }
19
+ ^ Align right let brace
20
+ let(:blah) { bc }
21
+ ^ Align right let brace
22
+ let(:a) { abc }
23
+ end
24
+ RUBY
25
+ end
26
+
27
+ offensive_source = <<-RUBY
28
+ let(:foo) { a }
29
+ let(:hi) { ab }
30
+ let(:blahblah) { abcd }
31
+
32
+ let(:thing) { ignore_this }
33
+ let(:other) {
34
+ ignore_this_too
35
+ }
36
+
37
+ describe 'blah' do
38
+ let(:blahblah) { a }
39
+ let(:blah) { bc }
40
+ let(:a) { abc }
41
+ end
42
+ RUBY
43
+
44
+ corrected_source = <<-RUBY
45
+ let(:foo) { a }
46
+ let(:hi) { ab }
47
+ let(:blahblah) { abcd }
48
+
49
+ let(:thing) { ignore_this }
50
+ let(:other) {
51
+ ignore_this_too
52
+ }
53
+
54
+ describe 'blah' do
55
+ let(:blahblah) { a }
56
+ let(:blah) { bc }
57
+ let(:a) { abc }
58
+ end
59
+ RUBY
60
+
61
+ include_examples 'autocorrect', offensive_source, corrected_source
62
+ end
@@ -2,7 +2,7 @@ RSpec.describe RuboCop::Cop::RSpec::AnyInstance do
2
2
  subject(:cop) { described_class.new }
3
3
 
4
4
  it 'finds `allow_any_instance_of` instead of an instance double' do
5
- expect_violation(<<-RUBY)
5
+ expect_offense(<<-RUBY)
6
6
  before do
7
7
  allow_any_instance_of(Object).to receive(:foo)
8
8
  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Avoid stubbing using `allow_any_instance_of`.
@@ -11,7 +11,7 @@ RSpec.describe RuboCop::Cop::RSpec::AnyInstance do
11
11
  end
12
12
 
13
13
  it 'finds `expect_any_instance_of` instead of an instance double' do
14
- expect_violation(<<-RUBY)
14
+ expect_offense(<<-RUBY)
15
15
  before do
16
16
  expect_any_instance_of(Object).to receive(:foo)
17
17
  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Avoid stubbing using `expect_any_instance_of`.
@@ -20,7 +20,7 @@ RSpec.describe RuboCop::Cop::RSpec::AnyInstance do
20
20
  end
21
21
 
22
22
  it 'finds old `any_instance` syntax instead of an instance double' do
23
- expect_violation(<<-RUBY)
23
+ expect_offense(<<-RUBY)
24
24
  before do
25
25
  Object.any_instance.should_receive(:foo)
26
26
  ^^^^^^^^^^^^^^^^^^^ Avoid stubbing using `any_instance`.