rubocop-rspec 1.5.1 → 1.5.2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +7 -0
- data/Gemfile +0 -2
- data/README.md +0 -8
- data/Rakefile +1 -3
- data/lib/rubocop-rspec.rb +2 -2
- data/lib/rubocop/cop/rspec/any_instance.rb +1 -10
- data/lib/rubocop/cop/rspec/describe_class.rb +23 -15
- data/lib/rubocop/cop/rspec/describe_method.rb +4 -6
- data/lib/rubocop/cop/rspec/described_class.rb +5 -8
- data/lib/rubocop/cop/rspec/example_length.rb +4 -9
- data/lib/rubocop/cop/rspec/example_wording.rb +13 -37
- data/lib/rubocop/cop/rspec/file_path.rb +10 -13
- data/lib/rubocop/cop/rspec/focus.rb +48 -30
- data/lib/rubocop/cop/rspec/instance_variable.rb +0 -1
- data/lib/rubocop/cop/rspec/multiple_describes.rb +2 -3
- data/lib/rubocop/cop/rspec/not_to_not.rb +3 -5
- data/lib/rubocop/cop/rspec/verified_doubles.rb +7 -15
- data/lib/rubocop/rspec/inject.rb +0 -1
- data/lib/rubocop/rspec/top_level_describe.rb +0 -2
- data/lib/rubocop/rspec/util.rb +19 -0
- data/lib/rubocop/rspec/version.rb +1 -2
- data/lib/rubocop/rspec/wording.rb +47 -0
- data/rubocop-rspec.gemspec +2 -2
- data/spec/project_spec.rb +0 -2
- data/spec/rubocop/cop/rspec/any_instance_spec.rb +0 -2
- data/spec/rubocop/cop/rspec/describe_class_spec.rb +36 -2
- data/spec/rubocop/cop/rspec/describe_method_spec.rb +10 -3
- data/spec/rubocop/cop/rspec/described_class_spec.rb +32 -2
- data/spec/rubocop/cop/rspec/example_length_spec.rb +17 -3
- data/spec/rubocop/cop/rspec/example_wording_spec.rb +61 -62
- data/spec/rubocop/cop/rspec/file_path_spec.rb +61 -21
- data/spec/rubocop/cop/rspec/focus_spec.rb +11 -3
- data/spec/rubocop/cop/rspec/instance_variable_spec.rb +13 -2
- data/spec/rubocop/cop/rspec/multiple_describes_spec.rb +0 -2
- data/spec/rubocop/cop/rspec/not_to_not_spec.rb +0 -2
- data/spec/rubocop/cop/rspec/verified_doubles_spec.rb +41 -19
- data/spec/rubocop/rspec/util/one_spec.rb +21 -0
- data/spec/rubocop/rspec/wording_spec.rb +44 -0
- data/spec/spec_helper.rb +1 -9
- metadata +11 -5
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 41d29a68e96541d0d09976b9cdc582f4c468a447
|
4
|
+
data.tar.gz: d38ae28874032c3035a8fd78e6865dfece308fe6
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 109b7e39672639b8aeb325439b0501dcec5d9e96eecde7b014cbe5647403bc5d8715a6499bfe9a5ea86bd8ec05f94f17cd75a0c59d9f1882031b3463961fe92b
|
7
|
+
data.tar.gz: 3bb0205007875394a79cc08782dd82ce7186238e155ec18b7078a59aef9572ff8804cc252027f6c2977415fe200605f0741688011a6845ec0eb276e163a3e37d
|
data/CHANGELOG.md
CHANGED
@@ -1,5 +1,12 @@
|
|
1
1
|
# Change log
|
2
2
|
|
3
|
+
## Master (unreleased)
|
4
|
+
|
5
|
+
## 1.5.2 (2016-08-01)
|
6
|
+
|
7
|
+
* Drop support for ruby `2.0.0` and `2.1.0`. ([@backus][])
|
8
|
+
* Internal refactorings and improved test coverage. ([@backus][])
|
9
|
+
|
3
10
|
## 1.5.1 (2016-07-20)
|
4
11
|
|
5
12
|
* Fix `unrecognized parameter RSpec/VerifiedDoubles:IgnoreSymbolicNames` warning. ([@jeffreyc][])
|
data/Gemfile
CHANGED
data/README.md
CHANGED
@@ -80,14 +80,6 @@ RSpec/FilePath:
|
|
80
80
|
4. Push to the branch (`git push origin my-new-feature`)
|
81
81
|
5. Create new Pull Request
|
82
82
|
|
83
|
-
For running the spec files, this project depends on RuboCop's spec helpers.
|
84
|
-
This means that in order to run the specs locally, you need a (shallow) clone
|
85
|
-
of the RuboCop repository:
|
86
|
-
|
87
|
-
```bash
|
88
|
-
git submodule update --init vendor/rubocop
|
89
|
-
```
|
90
|
-
|
91
83
|
## License
|
92
84
|
|
93
85
|
`rubocop-rspec` is MIT licensed. [See the accompanying file](MIT-LICENSE.md) for
|
data/Rakefile
CHANGED
@@ -1,5 +1,3 @@
|
|
1
|
-
# encoding: utf-8
|
2
|
-
|
3
1
|
require 'bundler'
|
4
2
|
require 'bundler/gem_tasks'
|
5
3
|
begin
|
@@ -26,7 +24,7 @@ task :internal_investigation do
|
|
26
24
|
require 'rubocop-rspec'
|
27
25
|
|
28
26
|
result = RuboCop::CLI.new.run
|
29
|
-
abort('RuboCop failed!') unless result
|
27
|
+
abort('RuboCop failed!') unless result.zero?
|
30
28
|
end
|
31
29
|
|
32
30
|
task default: [:spec, :internal_investigation]
|
data/lib/rubocop-rspec.rb
CHANGED
@@ -1,10 +1,10 @@
|
|
1
|
-
# encoding: utf-8
|
2
|
-
|
3
1
|
require 'rubocop'
|
4
2
|
|
5
3
|
require 'rubocop/rspec/version'
|
6
4
|
require 'rubocop/rspec/inject'
|
7
5
|
require 'rubocop/rspec/top_level_describe'
|
6
|
+
require 'rubocop/rspec/wording'
|
7
|
+
require 'rubocop/rspec/util'
|
8
8
|
|
9
9
|
RuboCop::RSpec::Inject.defaults!
|
10
10
|
|
@@ -1,5 +1,3 @@
|
|
1
|
-
# encoding: utf-8
|
2
|
-
|
3
1
|
module RuboCop
|
4
2
|
module Cop
|
5
3
|
module RSpec
|
@@ -33,14 +31,7 @@ module RuboCop
|
|
33
31
|
_receiver, method_name, *_args = *node
|
34
32
|
return unless ANY_INSTANCE_METHODS.include?(method_name)
|
35
33
|
|
36
|
-
add_offense(
|
37
|
-
node,
|
38
|
-
:expression,
|
39
|
-
format(
|
40
|
-
MESSAGE % { method: method_name },
|
41
|
-
node.loc.expression.source
|
42
|
-
)
|
43
|
-
)
|
34
|
+
add_offense(node, :expression, MESSAGE % { method: method_name })
|
44
35
|
end
|
45
36
|
end
|
46
37
|
end
|
@@ -1,4 +1,3 @@
|
|
1
|
-
# encoding: utf-8
|
2
1
|
# frozen_string_literal: true
|
3
2
|
|
4
3
|
module RuboCop
|
@@ -21,25 +20,34 @@ module RuboCop
|
|
21
20
|
class DescribeClass < Cop
|
22
21
|
include RuboCop::RSpec::TopLevelDescribe
|
23
22
|
|
24
|
-
|
25
|
-
|
26
|
-
ROUTING_PAIR = s(:pair, s(:sym, :type), s(:sym, :routing))
|
27
|
-
VIEW_PAIR = s(:pair, s(:sym, :type), s(:sym, :view))
|
23
|
+
MSG = 'The first argument to describe should be '\
|
24
|
+
'the class or module being tested.'.freeze
|
28
25
|
|
29
|
-
|
30
|
-
|
26
|
+
def_node_matcher :valid_describe?, <<-PATTERN
|
27
|
+
{(send {(const nil :RSpec) nil} :describe const ...) (send nil :describe)}
|
28
|
+
PATTERN
|
31
29
|
|
32
|
-
|
33
|
-
|
30
|
+
def_node_matcher :describe_with_metadata, <<-PATTERN
|
31
|
+
(send {(const nil :RSpec) nil} :describe
|
32
|
+
!const
|
33
|
+
...
|
34
|
+
(hash $...))
|
35
|
+
PATTERN
|
34
36
|
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
37
|
+
def_node_matcher :rails_metadata?, <<-PATTERN
|
38
|
+
(pair
|
39
|
+
(sym :type)
|
40
|
+
(sym {:request :feature :routing :view}))
|
41
|
+
PATTERN
|
42
|
+
|
43
|
+
def on_top_level_describe(node, args)
|
44
|
+
return if valid_describe?(node)
|
45
|
+
|
46
|
+
describe_with_metadata(node) do |pairs|
|
47
|
+
return if pairs.any?(&method(:rails_metadata?))
|
40
48
|
end
|
41
49
|
|
42
|
-
add_offense(args
|
50
|
+
add_offense(args.first, :expression)
|
43
51
|
end
|
44
52
|
end
|
45
53
|
end
|
@@ -1,4 +1,3 @@
|
|
1
|
-
# encoding: utf-8
|
2
1
|
# frozen_string_literal: true
|
3
2
|
|
4
3
|
module RuboCop
|
@@ -19,16 +18,15 @@ module RuboCop
|
|
19
18
|
# describe MyClass, '.my_class_method' do
|
20
19
|
# end
|
21
20
|
class DescribeMethod < Cop
|
22
|
-
include RuboCop::RSpec::TopLevelDescribe
|
21
|
+
include RuboCop::RSpec::TopLevelDescribe, RuboCop::RSpec::Util
|
23
22
|
|
24
23
|
MESSAGE = 'The second argument to describe should be the method ' \
|
25
24
|
"being tested. '#instance' or '.class'".freeze
|
26
25
|
METHOD_STRING_MATCHER = /^[\#\.].+/
|
27
26
|
|
28
|
-
def on_top_level_describe(_node,
|
29
|
-
second_arg
|
30
|
-
return
|
31
|
-
return if METHOD_STRING_MATCHER =~ second_arg.children.first
|
27
|
+
def on_top_level_describe(_node, (_, second_arg))
|
28
|
+
return unless second_arg && second_arg.type.equal?(:str)
|
29
|
+
return if METHOD_STRING_MATCHER =~ one(second_arg.children)
|
32
30
|
|
33
31
|
add_offense(second_arg, :expression, MESSAGE)
|
34
32
|
end
|
@@ -1,4 +1,3 @@
|
|
1
|
-
# encoding: utf-8
|
2
1
|
# frozen_string_literal: true
|
3
2
|
|
4
3
|
module RuboCop
|
@@ -27,9 +26,8 @@ module RuboCop
|
|
27
26
|
method, _args, body = *node
|
28
27
|
return unless top_level_describe?(method)
|
29
28
|
|
30
|
-
_receiver,
|
31
|
-
return unless
|
32
|
-
return unless object && object.type == :const
|
29
|
+
_receiver, _method_name, object = *method
|
30
|
+
return unless object && object.type.equal?(:const)
|
33
31
|
|
34
32
|
inspect_children(body, object)
|
35
33
|
end
|
@@ -43,14 +41,13 @@ module RuboCop
|
|
43
41
|
private
|
44
42
|
|
45
43
|
def inspect_children(node, object)
|
46
|
-
return unless node.
|
47
|
-
return if scope_change?(node) || node.type
|
44
|
+
return unless node.instance_of?(Node)
|
45
|
+
return if scope_change?(node) || node.type.equal?(:const)
|
48
46
|
|
49
47
|
node.children.each do |child|
|
50
|
-
if child
|
48
|
+
if child.eql?(object)
|
51
49
|
name = object.loc.expression.source
|
52
50
|
add_offense(child, :expression, format(MESSAGE, name))
|
53
|
-
break
|
54
51
|
end
|
55
52
|
inspect_children(child, object)
|
56
53
|
end
|
@@ -1,4 +1,3 @@
|
|
1
|
-
# encoding: utf-8
|
2
1
|
# frozen_string_literal: true
|
3
2
|
|
4
3
|
module RuboCop
|
@@ -35,23 +34,19 @@ module RuboCop
|
|
35
34
|
|
36
35
|
length = code_length(node)
|
37
36
|
|
38
|
-
return unless length >
|
39
|
-
add_offense(node, :expression, message(length
|
37
|
+
return unless length > max_length
|
38
|
+
add_offense(node, :expression, message(length))
|
40
39
|
end
|
41
40
|
|
42
41
|
private
|
43
42
|
|
44
|
-
def max
|
45
|
-
cop_config['Max']
|
46
|
-
end
|
47
|
-
|
48
43
|
def code_length(node)
|
49
|
-
lines = node.source.lines
|
44
|
+
lines = node.source.lines[1..-2]
|
50
45
|
|
51
46
|
lines.count { |line| !irrelevant_line(line) }
|
52
47
|
end
|
53
48
|
|
54
|
-
def message(length
|
49
|
+
def message(length)
|
55
50
|
format('Example has too many lines. [%d/%d]', length, max_length)
|
56
51
|
end
|
57
52
|
end
|
@@ -1,4 +1,3 @@
|
|
1
|
-
# encoding: utf-8
|
2
1
|
# frozen_string_literal: true
|
3
2
|
|
4
3
|
module RuboCop
|
@@ -25,9 +24,9 @@ module RuboCop
|
|
25
24
|
method, = *node
|
26
25
|
_, method_name, *args = *method
|
27
26
|
|
28
|
-
return unless method_name
|
27
|
+
return unless method_name.equal?(:it)
|
29
28
|
|
30
|
-
arguments =
|
29
|
+
arguments = args.first.to_a
|
31
30
|
message = arguments.first.to_s
|
32
31
|
return unless message.downcase.start_with?('should')
|
33
32
|
|
@@ -36,53 +35,30 @@ module RuboCop
|
|
36
35
|
arg1.begin_pos + 1,
|
37
36
|
arg1.end_pos - 1)
|
38
37
|
|
39
|
-
add_offense(message, message
|
38
|
+
add_offense(message, message)
|
40
39
|
end
|
41
40
|
|
42
41
|
def autocorrect(range)
|
43
42
|
lambda do |corrector|
|
44
|
-
corrector.replace(
|
43
|
+
corrector.replace(
|
44
|
+
range,
|
45
|
+
RuboCop::RSpec::Wording.new(
|
46
|
+
range.source,
|
47
|
+
ignore: ignored_words,
|
48
|
+
replace: custom_transform
|
49
|
+
).rewrite
|
50
|
+
)
|
45
51
|
end
|
46
52
|
end
|
47
53
|
|
48
54
|
private
|
49
55
|
|
50
|
-
def corrected_message(range)
|
51
|
-
range.source.split(' ').tap do |words|
|
52
|
-
first_word = words.shift
|
53
|
-
words.unshift('not') if first_word == "shouldn't"
|
54
|
-
|
55
|
-
words.each_with_index do |value, key|
|
56
|
-
next if ignored_words.include?(value)
|
57
|
-
words[key] = simple_present(words[key])
|
58
|
-
break
|
59
|
-
end
|
60
|
-
end.join(' ')
|
61
|
-
end
|
62
|
-
|
63
|
-
def simple_present(word)
|
64
|
-
return custom_transform[word] if custom_transform[word]
|
65
|
-
|
66
|
-
# ends with o s x ch sh or ss
|
67
|
-
if %w(o s x]).include?(word[-1]) ||
|
68
|
-
%w(ch sh ss]).include?(word[-2..-1])
|
69
|
-
return "#{word}es"
|
70
|
-
end
|
71
|
-
|
72
|
-
# ends with y
|
73
|
-
if word[-1] == 'y' && !%w(a u i o e).include?(word[-2])
|
74
|
-
return "#{word[0..-2]}ies"
|
75
|
-
end
|
76
|
-
|
77
|
-
"#{word}s"
|
78
|
-
end
|
79
|
-
|
80
56
|
def custom_transform
|
81
|
-
cop_config
|
57
|
+
cop_config.fetch('CustomTransform', {})
|
82
58
|
end
|
83
59
|
|
84
60
|
def ignored_words
|
85
|
-
cop_config
|
61
|
+
cop_config.fetch('IgnoredWords', [])
|
86
62
|
end
|
87
63
|
end
|
88
64
|
end
|
@@ -1,4 +1,3 @@
|
|
1
|
-
# encoding: utf-8
|
2
1
|
# frozen_string_literal: true
|
3
2
|
|
4
3
|
module RuboCop
|
@@ -29,7 +28,7 @@ module RuboCop
|
|
29
28
|
object = args.first.const_name
|
30
29
|
return unless object
|
31
30
|
|
32
|
-
path_matcher = matcher(object, args
|
31
|
+
path_matcher = matcher(object, args.at(1))
|
33
32
|
return if source_filename =~ regexp_from_glob(path_matcher)
|
34
33
|
|
35
34
|
add_offense(node, :expression, format(MESSAGE, path_matcher))
|
@@ -38,16 +37,15 @@ module RuboCop
|
|
38
37
|
private
|
39
38
|
|
40
39
|
def routing_spec?(args)
|
41
|
-
args
|
42
|
-
next unless arg.hash_type?
|
40
|
+
args.any? do |arg|
|
43
41
|
arg.children.include?(ROUTING_PAIR)
|
44
42
|
end
|
45
43
|
end
|
46
44
|
|
47
45
|
def matcher(object, method)
|
48
46
|
path = File.join(parts(object))
|
49
|
-
if method && method.type
|
50
|
-
path += '*' + method.
|
47
|
+
if method && method.type.equal?(:str)
|
48
|
+
path += '*' + method.str_content.gsub(/\W+/, '')
|
51
49
|
end
|
52
50
|
|
53
51
|
"#{path}*_spec.rb"
|
@@ -64,19 +62,18 @@ module RuboCop
|
|
64
62
|
end
|
65
63
|
|
66
64
|
def camel_to_underscore(string)
|
67
|
-
string
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
end
|
65
|
+
string
|
66
|
+
.gsub(/([^A-Z])([A-Z]+)/, '\\1_\\2')
|
67
|
+
.gsub(/([A-Z])([A-Z\d][^A-Z\d]+)/, '\\1_\\2')
|
68
|
+
.downcase
|
72
69
|
end
|
73
70
|
|
74
71
|
def regexp_from_glob(glob)
|
75
|
-
Regexp.new(glob.
|
72
|
+
Regexp.new(glob.sub('.', '\\.').gsub('*', '.*') + '$')
|
76
73
|
end
|
77
74
|
|
78
75
|
def custom_transform
|
79
|
-
cop_config['CustomTransform'] ||
|
76
|
+
cop_config['CustomTransform'] || {}
|
80
77
|
end
|
81
78
|
end
|
82
79
|
end
|
@@ -1,4 +1,3 @@
|
|
1
|
-
# encoding: utf-8
|
2
1
|
# frozen_string_literal: true
|
3
2
|
|
4
3
|
module RuboCop
|
@@ -21,44 +20,63 @@ module RuboCop
|
|
21
20
|
# describe MyClass do
|
22
21
|
# end
|
23
22
|
class Focus < Cop
|
24
|
-
|
23
|
+
MSG = 'Focused spec found.'.freeze
|
25
24
|
|
26
|
-
|
27
|
-
:
|
28
|
-
:
|
29
|
-
:
|
30
|
-
|
25
|
+
FOCUSABLE_SELECTORS = '
|
26
|
+
:context
|
27
|
+
:describe
|
28
|
+
:example
|
29
|
+
:example_group
|
30
|
+
:feature
|
31
|
+
:it
|
32
|
+
:scenario
|
33
|
+
:specify
|
34
|
+
:xcontext
|
35
|
+
:xdescribe
|
36
|
+
:xexample
|
37
|
+
:xfeature
|
38
|
+
:xit
|
39
|
+
:xscenario
|
40
|
+
:xspecify
|
41
|
+
'.freeze
|
31
42
|
|
32
|
-
|
33
|
-
:
|
34
|
-
:
|
35
|
-
:
|
36
|
-
|
43
|
+
FOCUSING_SELECTORS = '
|
44
|
+
:fcontext
|
45
|
+
:fdescribe
|
46
|
+
:fexample
|
47
|
+
:ffeature
|
48
|
+
:fit
|
49
|
+
:focus
|
50
|
+
:fscenario
|
51
|
+
:fspecify
|
52
|
+
'.freeze
|
37
53
|
|
38
|
-
|
54
|
+
FOCUS_SYMBOL = s(:sym, :focus)
|
55
|
+
FOCUS_TRUE = s(:pair, FOCUS_SYMBOL, s(:true))
|
39
56
|
|
40
|
-
|
57
|
+
def_node_matcher :metadata, <<-PATTERN
|
58
|
+
{(send nil {#{FOCUSABLE_SELECTORS}} ... (hash $...))
|
59
|
+
(send nil {#{FOCUSABLE_SELECTORS}} $...)}
|
60
|
+
PATTERN
|
41
61
|
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
if FOCUSED_BLOCKS.include?(method_name)
|
46
|
-
add_offense(node, :expression, MESSAGE)
|
47
|
-
end
|
62
|
+
def_node_matcher :focused_block?, <<-PATTERN
|
63
|
+
(send nil {#{FOCUSING_SELECTORS}} ...)
|
64
|
+
PATTERN
|
48
65
|
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
add_offense(n, :expression, MESSAGE) if n == FOCUS_KEY
|
66
|
+
def on_send(node)
|
67
|
+
focus_metadata(node) do |focus|
|
68
|
+
add_offense(focus, :expression)
|
53
69
|
end
|
54
70
|
end
|
55
71
|
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
72
|
+
private
|
73
|
+
|
74
|
+
def focus_metadata(node, &block)
|
75
|
+
yield(node) if focused_block?(node)
|
76
|
+
|
77
|
+
metadata(node) do |matches|
|
78
|
+
matches.grep(FOCUS_SYMBOL, &block)
|
79
|
+
matches.grep(FOCUS_TRUE, &block)
|
62
80
|
end
|
63
81
|
end
|
64
82
|
end
|