rubocop-rspec 1.4.1 → 1.5.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 4af4076d3a91d5fdb416fa1fec36c74e07998744
4
- data.tar.gz: e9bd1905617f520629969606be3a7d7228415b3b
3
+ metadata.gz: 7f7a58ee16af46402f371a3a3be9ae83752a7555
4
+ data.tar.gz: 15ecddf6c683fe294fb914faeadd45eabbbabba6
5
5
  SHA512:
6
- metadata.gz: 98850f3ef7a136727655aaf9eaaab8e889e8944f71762760def61d32c89e2690f6c6e3d519d1c82e9d7cd364796119105b82dfb7d2c17e58a9d4449fc9e6889d
7
- data.tar.gz: dff8cba69accc6a345a681a47a8529a3830821d5a1d09b12f81250c3bc1c513c6409c9267dc658c59a11af04421bf9f42ce029239097cb14ee1915a9b170ab4e
6
+ metadata.gz: ca7b87e0e9210d37795f29ebba6b5398c5e5583b9b68e3a1519c4f9208d18228d99378fba6114a6381c8bf579bf21cf755a3b9ef438765065965b381d9a1e3ca
7
+ data.tar.gz: f515ccc02aace366c6ec987aaf258450d8d7f0d2e740382d303a4480633b031de8150ca198369b2059c5856cb94d121afe7161bb10dfe1e70f7bdc1a60ed6f5d
data/CHANGELOG.md CHANGED
@@ -2,13 +2,26 @@
2
2
 
3
3
  ## master (unreleased)
4
4
 
5
- ## 1.4.1 (03/04/2016)
5
+ ## 1.5.0 (2016-05-17)
6
+
7
+ * Expand `VerifiedDoubles` cop to check for `spy` as well as `double`. ([@andyw8][])
8
+ * Enable `VerifiedDoubles` cop by default. ([@andyw8][])
9
+ * Add `IgnoreSymbolicNames` option for `VerifiedDoubles` cop. ([@andyw8][])
10
+ * Add `RSpec::ExampleLength` cop. ([@andyw8][])
11
+ * Handle alphanumeric class names in `FilePath` cop. ([@andyw8][])
12
+ * Skip `DescribeClass` cop for view specs. ([@andyw8][])
13
+ * Skip `FilePath` cop for Rails routing specs. ([@andyw8][])
14
+ * Add cop to check for focused specs. ([@renanborgescampos][], [@jaredmoody][])
15
+ * Clean-up `RSpec::NotToNot` to use same configuration semantics as other Rubocop cops, add autocorrect support for `RSpec::NotToNot`. ([@baberthal][])
16
+ * Update to rubocop 0.40.0. ([@nijikon][])
17
+
18
+ ## 1.4.1 (2016-04-03)
6
19
 
7
20
  * Ignore routing specs for DescribeClass cop. ([@nijikon][])
8
21
  * Move rubocop dependency to runtime. ([@nijikon][])
9
22
  * Update to rubocop 0.39.0. ([@nijikon][])
10
23
 
11
- ## 1.4.0 (15/02/2016)
24
+ ## 1.4.0 (2016-02-15)
12
25
 
13
26
  * Update to rubocop 0.37.2. ([@nijikon][])
14
27
  * Update ruby versions we test against. ([@nijikon][])
@@ -73,7 +86,7 @@
73
86
 
74
87
  <!-- Contributors -->
75
88
 
76
- [@andyw8]: https://github.com/andyw8i
89
+ [@andyw8]: https://github.com/andyw8
77
90
  [@bquorning]: https://github.com/bquorning
78
91
  [@deivid-rodriguez]: https://github.com/deivid-rodriguez
79
92
  [@geniou]: https://github.com/geniou
@@ -83,3 +96,6 @@
83
96
  [@pstengel]: https://github.com/pstengel
84
97
  [@miguelfteixeira]: https://github.com/miguelfteixeira
85
98
  [@mlarraz]: https://github.com/mlarraz
99
+ [@renanborgescampos]: https://github.com/renanborgescampos
100
+ [@jaredmoody]: https://github.com/jaredmoody
101
+ [@baberthal]: https://github.com/baberthal
data/README.md CHANGED
@@ -85,7 +85,7 @@ This means that in order to run the specs locally, you need a (shallow) clone
85
85
  of the RuboCop repository:
86
86
 
87
87
  ```bash
88
- git submodule update --init --depth 1 vendor/rubocop
88
+ git submodule update --init vendor/rubocop
89
89
  ```
90
90
 
91
91
  ## License
data/config/default.yml CHANGED
@@ -41,9 +41,21 @@ RSpec/FilePath:
41
41
 
42
42
  RSpec/VerifiedDoubles:
43
43
  Description: 'Prefer using verifying doubles over normal doubles.'
44
- Enabled: false
44
+ Enabled: true
45
45
 
46
46
  RSpec/NotToNot:
47
47
  Description: 'Enforces the usage of the same method on all negative message expectations.'
48
+ EnforcedStyle: not_to
49
+ SupportedStyles:
50
+ - not_to
51
+ - to_not
52
+ Enabled: true
53
+
54
+ RSpec/Focus:
55
+ Description: 'Checks if there are focused specs.'
56
+ Enabled: true
57
+
58
+ RSpec/ExampleLength:
59
+ Description: 'Checks for long example'
48
60
  Enabled: true
49
- AcceptedMethod: 'not_to'
61
+ Max: 5
data/lib/rubocop-rspec.rb CHANGED
@@ -15,7 +15,9 @@ require 'rubocop/cop/rspec/describe_method'
15
15
  require 'rubocop/cop/rspec/described_class'
16
16
  require 'rubocop/cop/rspec/example_wording'
17
17
  require 'rubocop/cop/rspec/file_path'
18
+ require 'rubocop/cop/rspec/focus'
18
19
  require 'rubocop/cop/rspec/instance_variable'
20
+ require 'rubocop/cop/rspec/example_length'
19
21
  require 'rubocop/cop/rspec/multiple_describes'
20
22
  require 'rubocop/cop/rspec/not_to_not'
21
23
  require 'rubocop/cop/rspec/verified_doubles'
@@ -33,11 +33,14 @@ module RuboCop
33
33
  _receiver, method_name, *_args = *node
34
34
  return unless ANY_INSTANCE_METHODS.include?(method_name)
35
35
 
36
- add_offense(node, :expression,
37
- format(MESSAGE % { method: method_name },
38
- node.loc.expression.source
39
- )
40
- )
36
+ add_offense(
37
+ node,
38
+ :expression,
39
+ format(
40
+ MESSAGE % { method: method_name },
41
+ node.loc.expression.source
42
+ )
43
+ )
41
44
  end
42
45
  end
43
46
  end
@@ -24,6 +24,7 @@ module RuboCop
24
24
  REQUEST_PAIR = s(:pair, s(:sym, :type), s(:sym, :request))
25
25
  FEATURE_PAIR = s(:pair, s(:sym, :type), s(:sym, :feature))
26
26
  ROUTING_PAIR = s(:pair, s(:sym, :type), s(:sym, :routing))
27
+ VIEW_PAIR = s(:pair, s(:sym, :type), s(:sym, :view))
27
28
 
28
29
  MESSAGE = 'The first argument to describe should be the class or ' \
29
30
  'module being tested.'.freeze
@@ -34,7 +35,7 @@ module RuboCop
34
35
  return if args[1..-1].any? do |arg|
35
36
  next unless arg.hash_type?
36
37
  arg.children.any? do |n|
37
- [REQUEST_PAIR, FEATURE_PAIR, ROUTING_PAIR].include?(n)
38
+ [REQUEST_PAIR, FEATURE_PAIR, ROUTING_PAIR, VIEW_PAIR].include?(n)
38
39
  end
39
40
  end
40
41
 
@@ -0,0 +1,60 @@
1
+ # encoding: utf-8
2
+ # frozen_string_literal: true
3
+
4
+ module RuboCop
5
+ module Cop
6
+ module RSpec
7
+ # A long example is usually more difficult to understand. Consider
8
+ # extracting out some behaviour, e.g. with a `let` block, or a helper
9
+ # method.
10
+ #
11
+ # @example
12
+ # # bad
13
+ # it do
14
+ # service = described_class.new
15
+ # more_setup
16
+ # more_setup
17
+ # result = service.call
18
+ # expect(result).to be(true)
19
+ # end
20
+ #
21
+ # # good
22
+ # it do
23
+ # service = described_class.new
24
+ # result = service.call
25
+ # expect(result).to be(true)
26
+ # end
27
+ class ExampleLength < Cop
28
+ include CodeLength
29
+ EXAMPLE_BLOCKS = [:it, :specify].freeze
30
+
31
+ def on_block(node)
32
+ method, _args, _body = *node
33
+ _receiver, method_name, _object = *method
34
+ return unless EXAMPLE_BLOCKS.include?(method_name)
35
+
36
+ length = code_length(node)
37
+
38
+ return unless length > max
39
+ add_offense(node, :expression, message(length, max))
40
+ end
41
+
42
+ private
43
+
44
+ def max
45
+ cop_config['Max']
46
+ end
47
+
48
+ def code_length(node)
49
+ lines = node.source.lines.to_a[1..-2] || []
50
+
51
+ lines.count { |line| !irrelevant_line(line) }
52
+ end
53
+
54
+ def message(length, max_length)
55
+ format('Example has too many lines. [%d/%d]', length, max_length)
56
+ end
57
+ end
58
+ end
59
+ end
60
+ end
@@ -7,8 +7,8 @@ module RuboCop
7
7
  # Checks the path of the spec file and enforces that it reflects the
8
8
  # described class/module and its optionally called out method.
9
9
  #
10
- # With the configuration option `CustomTransform` modules or clases can be
11
- # specified that should not as usual be transformed from CamelCase to
10
+ # With the configuration option `CustomTransform` modules or classes can
11
+ # be specified that should not as usual be transformed from CamelCase to
12
12
  # snake_case (e.g. 'RuboCop' => 'rubocop' ).
13
13
  #
14
14
  # @example
@@ -20,8 +20,11 @@ module RuboCop
20
20
 
21
21
  MESSAGE = 'Spec path should end with `%s`'.freeze
22
22
  METHOD_STRING_MATCHER = /^[\#\.].+/
23
+ ROUTING_PAIR = s(:pair, s(:sym, :type), s(:sym, :routing))
23
24
 
24
25
  def on_top_level_describe(node, args)
26
+ return if routing_spec?(args)
27
+
25
28
  return unless single_top_level_describe?
26
29
  object = args.first.const_name
27
30
  return unless object
@@ -34,6 +37,13 @@ module RuboCop
34
37
 
35
38
  private
36
39
 
40
+ def routing_spec?(args)
41
+ args[1..-1].any? do |arg|
42
+ next unless arg.hash_type?
43
+ arg.children.include?(ROUTING_PAIR)
44
+ end
45
+ end
46
+
37
47
  def matcher(object, method)
38
48
  path = File.join(parts(object))
39
49
  if method && method.type == :str
@@ -56,7 +66,7 @@ module RuboCop
56
66
  def camel_to_underscore(string)
57
67
  string.dup.tap do |result|
58
68
  result.gsub!(/([^A-Z])([A-Z]+)/, '\\1_\\2')
59
- result.gsub!(/([A-Z])([A-Z][^A-Z]+)/, '\\1_\\2')
69
+ result.gsub!(/([A-Z])([A-Z\d][^A-Z\d]+)/, '\\1_\\2')
60
70
  result.downcase!
61
71
  end
62
72
  end
@@ -0,0 +1,67 @@
1
+ # encoding: utf-8
2
+ # frozen_string_literal: true
3
+
4
+ module RuboCop
5
+ module Cop
6
+ module RSpec
7
+ # Checks if test is focused.
8
+ #
9
+ # @example
10
+ # # bad
11
+ # describe MyClass, focus: true do
12
+ # end
13
+ #
14
+ # describe MyClass, :focus do
15
+ # end
16
+ #
17
+ # fdescribe MyClass do
18
+ # end
19
+ #
20
+ # # good
21
+ # describe MyClass do
22
+ # end
23
+ class Focus < Cop
24
+ MESSAGE = 'Focused spec found.'.freeze
25
+
26
+ FOCUSABLE_BLOCKS = [
27
+ :example_group, :describe, :context, :xdescribe, :xcontext,
28
+ :it, :example, :specify, :xit, :xexample, :xspecify,
29
+ :feature, :scenario, :xfeature, :xscenario
30
+ ].freeze
31
+
32
+ FOCUSED_BLOCKS = [
33
+ :fdescribe, :fcontext,
34
+ :focus, :fexample, :fit, :fspecify,
35
+ :ffeature, :fscenario
36
+ ].freeze
37
+
38
+ FOCUS_KEY = s(:sym, :focus)
39
+
40
+ FOCUS_TRUE_PAIR = s(:pair, FOCUS_KEY, s(:true))
41
+
42
+ def on_send(node)
43
+ _receiver, method_name, *_args = *node
44
+ @focusable_block = FOCUSABLE_BLOCKS.include?(method_name)
45
+ if FOCUSED_BLOCKS.include?(method_name)
46
+ add_offense(node, :expression, MESSAGE)
47
+ end
48
+
49
+ # check for :focus
50
+ return unless @focusable_block
51
+ node.children.any? do |n|
52
+ add_offense(n, :expression, MESSAGE) if n == FOCUS_KEY
53
+ end
54
+ end
55
+
56
+ def on_hash(node)
57
+ return unless @focusable_block
58
+ return if node.children.any? do |n|
59
+ if [FOCUS_TRUE_PAIR].include?(n)
60
+ add_offense(n, :expression, MESSAGE)
61
+ end
62
+ end
63
+ end
64
+ end
65
+ end
66
+ end
67
+ end
@@ -17,36 +17,37 @@ module RuboCop
17
17
  # expect(false).not_to be_true
18
18
  # end
19
19
  class NotToNot < Cop
20
- ACCEPTED_METHODS = [:not_to, :to_not].freeze
20
+ include RuboCop::Cop::ConfigurableEnforcedStyle
21
+
22
+ MSG = 'Prefer `%s` over `%s`'.freeze
23
+
24
+ METHOD_NAMES = [:not_to, :to_not].freeze
21
25
 
22
26
  def on_send(node)
23
27
  _receiver, method_name, *_args = *node
24
28
 
25
- if method_name == rejected_method
26
- add_offense(node, :expression, offense_message)
27
- end
28
- end
29
-
30
- private
29
+ return unless METHOD_NAMES.include?(method_name)
31
30
 
32
- def accepted_method
33
- @accepted_method ||= begin
34
- method = cop_config['AcceptedMethod'].to_sym
31
+ return if style == method_name
32
+ add_offense(node, :expression)
33
+ end
35
34
 
36
- unless ACCEPTED_METHODS.include?(method)
37
- raise "Invalid AcceptedMethod value: #{method}"
38
- end
35
+ def message(node)
36
+ _receiver, method_name, *_args = *node
39
37
 
40
- method
38
+ if method_name == :not_to
39
+ format(MSG, 'to_not', 'not_to')
40
+ else
41
+ format(MSG, 'not_to', 'to_not')
41
42
  end
42
43
  end
43
44
 
44
- def rejected_method
45
- @rejected_method ||= (ACCEPTED_METHODS - [accepted_method]).first
46
- end
47
-
48
- def offense_message
49
- "Use `#{accepted_method}` instead of `#{rejected_method}`"
45
+ def autocorrect(node)
46
+ _receiver, method_name, *_args = *node
47
+ lambda do |corrector|
48
+ corrector.replace(node.loc.selector,
49
+ method_name == :not_to ? 'to_not' : 'not_to')
50
+ end
50
51
  end
51
52
  end
52
53
  end
@@ -19,14 +19,24 @@ module RuboCop
19
19
  # end
20
20
  class VerifiedDoubles < Cop
21
21
  MSG = 'Prefer using verifying doubles over normal doubles.'.freeze
22
+ DOUBLE_TYPES = [:double, :spy].freeze
22
23
 
23
24
  def on_send(node)
24
- _receiver, method_name, *_args = *node
25
- return unless method_name == :double
25
+ _receiver, method_name, *args = *node
26
+ name, *_stubs = *args
27
+ return unless DOUBLE_TYPES.include?(method_name)
28
+ return if name.nil?
29
+ return if name_is_symbol?(name) && cop_config['IgnoreSymbolicNames']
26
30
  add_offense(node,
27
31
  :expression,
28
32
  format(MSG, node.loc.expression.source))
29
33
  end
34
+
35
+ private
36
+
37
+ def name_is_symbol?(name)
38
+ name.children.first.is_a? Symbol
39
+ end
30
40
  end
31
41
  end
32
42
  end
@@ -5,7 +5,7 @@ module RuboCop
5
5
  module RSpec
6
6
  # Version information for the RSpec RuboCop plugin.
7
7
  module Version
8
- STRING = '1.4.1'.freeze
8
+ STRING = '1.5.0'.freeze
9
9
  end
10
10
  end
11
11
  end
@@ -30,7 +30,7 @@ Gem::Specification.new do |spec|
30
30
  spec.test_files = spec.files.grep(%r{^spec/})
31
31
  spec.extra_rdoc_files = ['MIT-LICENSE.md', 'README.md']
32
32
 
33
- spec.add_runtime_dependency 'rubocop', '0.39.0'
33
+ spec.add_runtime_dependency 'rubocop', '>= 0.40.0'
34
34
 
35
35
  spec.add_development_dependency 'rake'
36
36
  spec.add_development_dependency 'rspec', '>= 3.4'
@@ -4,9 +4,14 @@ describe RuboCop::Cop::RSpec::AnyInstance do
4
4
  subject(:cop) { described_class.new }
5
5
 
6
6
  it 'finds `allow_any_instance_of` instead of an instance double' do
7
- inspect_source(cop, ['before do',
8
- ' allow_any_instance_of(Object).to receive(:foo)',
9
- 'end'])
7
+ inspect_source(
8
+ cop,
9
+ [
10
+ 'before do',
11
+ ' allow_any_instance_of(Object).to receive(:foo)',
12
+ 'end'
13
+ ]
14
+ )
10
15
  expect(cop.messages)
11
16
  .to eq(['Avoid stubbing using `allow_any_instance_of`'])
12
17
  expect(cop.highlights).to eq(['allow_any_instance_of(Object)'])
@@ -14,9 +19,14 @@ describe RuboCop::Cop::RSpec::AnyInstance do
14
19
  end
15
20
 
16
21
  it 'finds `expect_any_instance_of` instead of an instance double' do
17
- inspect_source(cop, ['before do',
18
- ' expect_any_instance_of(Object).to receive(:foo)',
19
- 'end'])
22
+ inspect_source(
23
+ cop,
24
+ [
25
+ 'before do',
26
+ ' expect_any_instance_of(Object).to receive(:foo)',
27
+ 'end'
28
+ ]
29
+ )
20
30
  expect(cop.messages)
21
31
  .to eq(['Avoid stubbing using `expect_any_instance_of`'])
22
32
  expect(cop.highlights).to eq(['expect_any_instance_of(Object)'])
@@ -24,9 +34,14 @@ describe RuboCop::Cop::RSpec::AnyInstance do
24
34
  end
25
35
 
26
36
  it 'finds old `any_instance` syntax instead of an instance double' do
27
- inspect_source(cop, ['before do',
28
- ' Object.any_instance.should_receive(:foo)',
29
- 'end'])
37
+ inspect_source(
38
+ cop,
39
+ [
40
+ 'before do',
41
+ ' Object.any_instance.should_receive(:foo)',
42
+ 'end'
43
+ ]
44
+ )
30
45
  expect(cop.messages)
31
46
  .to eq(['Avoid stubbing using `any_instance`'])
32
47
  expect(cop.highlights).to eq(['Object.any_instance'])