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.
Files changed (41) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +7 -0
  3. data/Gemfile +0 -2
  4. data/README.md +0 -8
  5. data/Rakefile +1 -3
  6. data/lib/rubocop-rspec.rb +2 -2
  7. data/lib/rubocop/cop/rspec/any_instance.rb +1 -10
  8. data/lib/rubocop/cop/rspec/describe_class.rb +23 -15
  9. data/lib/rubocop/cop/rspec/describe_method.rb +4 -6
  10. data/lib/rubocop/cop/rspec/described_class.rb +5 -8
  11. data/lib/rubocop/cop/rspec/example_length.rb +4 -9
  12. data/lib/rubocop/cop/rspec/example_wording.rb +13 -37
  13. data/lib/rubocop/cop/rspec/file_path.rb +10 -13
  14. data/lib/rubocop/cop/rspec/focus.rb +48 -30
  15. data/lib/rubocop/cop/rspec/instance_variable.rb +0 -1
  16. data/lib/rubocop/cop/rspec/multiple_describes.rb +2 -3
  17. data/lib/rubocop/cop/rspec/not_to_not.rb +3 -5
  18. data/lib/rubocop/cop/rspec/verified_doubles.rb +7 -15
  19. data/lib/rubocop/rspec/inject.rb +0 -1
  20. data/lib/rubocop/rspec/top_level_describe.rb +0 -2
  21. data/lib/rubocop/rspec/util.rb +19 -0
  22. data/lib/rubocop/rspec/version.rb +1 -2
  23. data/lib/rubocop/rspec/wording.rb +47 -0
  24. data/rubocop-rspec.gemspec +2 -2
  25. data/spec/project_spec.rb +0 -2
  26. data/spec/rubocop/cop/rspec/any_instance_spec.rb +0 -2
  27. data/spec/rubocop/cop/rspec/describe_class_spec.rb +36 -2
  28. data/spec/rubocop/cop/rspec/describe_method_spec.rb +10 -3
  29. data/spec/rubocop/cop/rspec/described_class_spec.rb +32 -2
  30. data/spec/rubocop/cop/rspec/example_length_spec.rb +17 -3
  31. data/spec/rubocop/cop/rspec/example_wording_spec.rb +61 -62
  32. data/spec/rubocop/cop/rspec/file_path_spec.rb +61 -21
  33. data/spec/rubocop/cop/rspec/focus_spec.rb +11 -3
  34. data/spec/rubocop/cop/rspec/instance_variable_spec.rb +13 -2
  35. data/spec/rubocop/cop/rspec/multiple_describes_spec.rb +0 -2
  36. data/spec/rubocop/cop/rspec/not_to_not_spec.rb +0 -2
  37. data/spec/rubocop/cop/rspec/verified_doubles_spec.rb +41 -19
  38. data/spec/rubocop/rspec/util/one_spec.rb +21 -0
  39. data/spec/rubocop/rspec/wording_spec.rb +44 -0
  40. data/spec/spec_helper.rb +1 -9
  41. metadata +11 -5
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 6e7b5f7025e117a87e31f15d9e2a8f052e590270
4
- data.tar.gz: 89bfe35b6ba5d2af8eb751403e87d765a73931ce
3
+ metadata.gz: 41d29a68e96541d0d09976b9cdc582f4c468a447
4
+ data.tar.gz: d38ae28874032c3035a8fd78e6865dfece308fe6
5
5
  SHA512:
6
- metadata.gz: 83f01b1e8b7a94599499b286ba65034c791b5939bfbfb84400db6950ed6c4092c27e0b1ac4544c6d21bcf068724495ea73408812cdf7216ef6199cf510c51cac
7
- data.tar.gz: da36f3a208108b5342d3718fc64a6a35dfcaf2fd9a0b18039f244f6a0ea1ad97e0b2a39ce4d78f8cff69fb2d189fbd5dce8403559c92157d4d8d10e6e436e488
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
@@ -1,5 +1,3 @@
1
- # encoding: utf-8
2
-
3
1
  source 'https://rubygems.org'
4
2
 
5
3
  gemspec
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 == 0
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
- REQUEST_PAIR = s(:pair, s(:sym, :type), s(:sym, :request))
25
- FEATURE_PAIR = s(:pair, s(:sym, :type), s(:sym, :feature))
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
- MESSAGE = 'The first argument to describe should be the class or ' \
30
- 'module being tested.'.freeze
26
+ def_node_matcher :valid_describe?, <<-PATTERN
27
+ {(send {(const nil :RSpec) nil} :describe const ...) (send nil :describe)}
28
+ PATTERN
31
29
 
32
- def on_top_level_describe(_node, args)
33
- return if args[0] && args[0].type == :const
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
- return if args[1..-1].any? do |arg|
36
- next unless arg.hash_type?
37
- arg.children.any? do |n|
38
- [REQUEST_PAIR, FEATURE_PAIR, ROUTING_PAIR, VIEW_PAIR].include?(n)
39
- end
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[0], :expression, MESSAGE)
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, args)
29
- second_arg = args[1]
30
- return unless second_arg && second_arg.type == :str
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, method_name, object = *method
31
- return unless method_name == :describe
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.is_a? Parser::AST::Node
47
- return if scope_change?(node) || node.type == :const
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 == object
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 > max
39
- add_offense(node, :expression, message(length, max))
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.to_a[1..-2] || []
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, max_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 == :it
27
+ return unless method_name.equal?(:it)
29
28
 
30
- arguments = *args.first
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, MSG)
38
+ add_offense(message, message)
40
39
  end
41
40
 
42
41
  def autocorrect(range)
43
42
  lambda do |corrector|
44
- corrector.replace(range, corrected_message(range))
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['CustomTransform'] || []
57
+ cop_config.fetch('CustomTransform', {})
82
58
  end
83
59
 
84
60
  def ignored_words
85
- cop_config['IgnoredWords'] || []
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[1])
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[1..-1].any? do |arg|
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 == :str
50
- path += '*' + method.children.first.gsub(/\W+/, '')
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.dup.tap do |result|
68
- result.gsub!(/([^A-Z])([A-Z]+)/, '\\1_\\2')
69
- result.gsub!(/([A-Z])([A-Z\d][^A-Z\d]+)/, '\\1_\\2')
70
- result.downcase!
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.gsub('.', '\\.').gsub('*', '.*') + '$')
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
- MESSAGE = 'Focused spec found.'.freeze
23
+ MSG = 'Focused spec found.'.freeze
25
24
 
26
- FOCUSABLE_BLOCKS = [
27
- :example_group, :describe, :context, :xdescribe, :xcontext,
28
- :it, :example, :specify, :xit, :xexample, :xspecify,
29
- :feature, :scenario, :xfeature, :xscenario
30
- ].freeze
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
- FOCUSED_BLOCKS = [
33
- :fdescribe, :fcontext,
34
- :focus, :fexample, :fit, :fspecify,
35
- :ffeature, :fscenario
36
- ].freeze
43
+ FOCUSING_SELECTORS = '
44
+ :fcontext
45
+ :fdescribe
46
+ :fexample
47
+ :ffeature
48
+ :fit
49
+ :focus
50
+ :fscenario
51
+ :fspecify
52
+ '.freeze
37
53
 
38
- FOCUS_KEY = s(:sym, :focus)
54
+ FOCUS_SYMBOL = s(:sym, :focus)
55
+ FOCUS_TRUE = s(:pair, FOCUS_SYMBOL, s(:true))
39
56
 
40
- FOCUS_TRUE_PAIR = s(:pair, FOCUS_KEY, s(:true))
57
+ def_node_matcher :metadata, <<-PATTERN
58
+ {(send nil {#{FOCUSABLE_SELECTORS}} ... (hash $...))
59
+ (send nil {#{FOCUSABLE_SELECTORS}} $...)}
60
+ PATTERN
41
61
 
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
62
+ def_node_matcher :focused_block?, <<-PATTERN
63
+ (send nil {#{FOCUSING_SELECTORS}} ...)
64
+ PATTERN
48
65
 
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
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
- 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
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