rubocop-rspec 1.5.1 → 1.5.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.
- 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
|