rubocop-rspec 0.18.1 → 1.0.rc1

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,32 @@
1
+ # encoding: utf-8
2
+
3
+ require 'spec_helper'
4
+
5
+ describe Rubocop::Cop::RSpecMultipleDescribes do
6
+ subject(:cop) { described_class.new }
7
+
8
+ it 'finds multiple top level describes with class and method' do
9
+ inspect_source(cop, ["describe MyClass, '.do_something' do; end",
10
+ "describe MyClass, '.do_something_else' do; end"])
11
+ expect(cop.offenses.size).to eq(1)
12
+ expect(cop.offenses.map(&:line).sort).to eq([1])
13
+ expect(cop.messages).to eq(['Do not use multiple top level describes - ' \
14
+ 'try to nest them.'])
15
+ end
16
+
17
+ it 'finds multiple top level describes only with class' do
18
+ inspect_source(cop, ['describe MyClass do; end',
19
+ 'describe MyOtherClass do; end'])
20
+ expect(cop.offenses.size).to eq(1)
21
+ expect(cop.offenses.map(&:line).sort).to eq([1])
22
+ expect(cop.messages).to eq(['Do not use multiple top level describes - ' \
23
+ 'try to nest them.'])
24
+ end
25
+
26
+ it 'skips single top level describe' do
27
+ inspect_source(cop, ["require 'spec_helper'",
28
+ '',
29
+ 'describe MyClass do; end'])
30
+ expect(cop.offenses).to be_empty
31
+ end
32
+ end
metadata CHANGED
@@ -1,14 +1,15 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rubocop-rspec
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.18.1
4
+ version: 1.0.rc1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Ian MacLeod
8
+ - Nils Gemeinhardt
8
9
  autorequire:
9
10
  bindir: bin
10
11
  cert_chain: []
11
- date: 2014-02-05 00:00:00.000000000 Z
12
+ date: 2014-05-18 00:00:00.000000000 Z
12
13
  dependencies:
13
14
  - !ruby/object:Gem::Dependency
14
15
  name: rubocop
@@ -16,25 +17,33 @@ dependencies:
16
17
  requirements:
17
18
  - - ~>
18
19
  - !ruby/object:Gem::Version
19
- version: '0.18'
20
+ version: '0.19'
21
+ - - '>='
22
+ - !ruby/object:Gem::Version
23
+ version: '0.19'
20
24
  type: :runtime
21
25
  prerelease: false
22
26
  version_requirements: !ruby/object:Gem::Requirement
23
27
  requirements:
24
28
  - - ~>
25
29
  - !ruby/object:Gem::Version
26
- version: '0.18'
30
+ version: '0.19'
31
+ - - '>='
32
+ - !ruby/object:Gem::Version
33
+ version: '0.19'
27
34
  description: |2
28
35
  Code style checking for RSpec files.
29
36
  A plugin for the RuboCop code style enforcing & linting tool.
30
37
  email:
31
38
  - ian@nevir.net
39
+ - git@nilsgemeinhardt.de
32
40
  executables: []
33
41
  extensions: []
34
42
  extra_rdoc_files:
35
43
  - MIT-LICENSE.md
36
44
  - README.md
37
45
  files:
46
+ - CHANGELOG.md
38
47
  - config/default.yml
39
48
  - coverage/assets/0.8.0/application.css
40
49
  - coverage/assets/0.8.0/application.js
@@ -63,8 +72,15 @@ files:
63
72
  - coverage/index.html
64
73
  - Gemfile
65
74
  - Gemfile.lock
66
- - lib/rubocop/cop/rspec/unit_spec_naming.rb
75
+ - lib/rubocop/cop/rspec_describe_class.rb
76
+ - lib/rubocop/cop/rspec_describe_method.rb
77
+ - lib/rubocop/cop/rspec_described_class.rb
78
+ - lib/rubocop/cop/rspec_example_wording.rb
79
+ - lib/rubocop/cop/rspec_file_name.rb
80
+ - lib/rubocop/cop/rspec_instance_variable.rb
81
+ - lib/rubocop/cop/rspec_multiple_describes.rb
67
82
  - lib/rubocop/rspec/inject.rb
83
+ - lib/rubocop/rspec/top_level_describe.rb
68
84
  - lib/rubocop/rspec/version.rb
69
85
  - lib/rubocop-rspec.rb
70
86
  - MIT-LICENSE.md
@@ -72,10 +88,17 @@ files:
72
88
  - pkg/rubocop-rspec-0.17.0.gem
73
89
  - pkg/rubocop-rspec-0.18.0.gem
74
90
  - pkg/rubocop-rspec-0.18.1.gem
91
+ - pkg/rubocop-rspec-1.0.rc1.gem
75
92
  - Rakefile
76
93
  - README.md
77
94
  - rubocop-rspec.gemspec
78
- - spec/rubocop/cop/rspec/unit_spec_naming_spec.rb
95
+ - spec/rubocop/cop/rspec_describe_class_spec.rb
96
+ - spec/rubocop/cop/rspec_describe_method_spec.rb
97
+ - spec/rubocop/cop/rspec_described_class_spec.rb
98
+ - spec/rubocop/cop/rspec_example_wording_spec.rb
99
+ - spec/rubocop/cop/rspec_file_name_spec.rb
100
+ - spec/rubocop/cop/rspec_instance_variable_spec.rb
101
+ - spec/rubocop/cop/rspec_multiple_describes_spec.rb
79
102
  - spec/spec_helper.rb
80
103
  homepage: http://github.com/nevir/rubocop-rspec
81
104
  licenses:
@@ -92,9 +115,9 @@ required_ruby_version: !ruby/object:Gem::Requirement
92
115
  version: 1.9.2
93
116
  required_rubygems_version: !ruby/object:Gem::Requirement
94
117
  requirements:
95
- - - '>='
118
+ - - '>'
96
119
  - !ruby/object:Gem::Version
97
- version: '0'
120
+ version: 1.3.1
98
121
  requirements: []
99
122
  rubyforge_project:
100
123
  rubygems_version: 2.0.3
@@ -102,5 +125,11 @@ signing_key:
102
125
  specification_version: 4
103
126
  summary: Code style checking for RSpec files
104
127
  test_files:
105
- - spec/rubocop/cop/rspec/unit_spec_naming_spec.rb
128
+ - spec/rubocop/cop/rspec_describe_class_spec.rb
129
+ - spec/rubocop/cop/rspec_describe_method_spec.rb
130
+ - spec/rubocop/cop/rspec_described_class_spec.rb
131
+ - spec/rubocop/cop/rspec_example_wording_spec.rb
132
+ - spec/rubocop/cop/rspec_file_name_spec.rb
133
+ - spec/rubocop/cop/rspec_instance_variable_spec.rb
134
+ - spec/rubocop/cop/rspec_multiple_describes_spec.rb
106
135
  - spec/spec_helper.rb
@@ -1,144 +0,0 @@
1
- # encoding: utf-8
2
-
3
- module Rubocop
4
- module Cop
5
- module RSpec
6
- # This cop checks that RSpec unit tests conform to a consistent naming
7
- # scheme - both for the describe call, and the file path.
8
- #
9
- # Disabled by default. Generally, you want to scope it to your project's
10
- # unit spec paths:
11
- #
12
- # UnitSpecNaming:
13
- # Enabled: true
14
- # Include:
15
- # - 'spec/rubocop/*'
16
- #
17
- class UnitSpecNaming < Cop
18
- DESCRIBE_CLASS_MSG = 'The first argument to describe should be the ' \
19
- 'class or module being tested.'
20
-
21
- METHOD_STRING_MSG = 'The second argument to describe should be the ' \
22
- "method being tested. '#instance' or '.class'"
23
-
24
- CLASS_SPEC_MSG = 'Class unit spec should have a path ending with %s'
25
-
26
- METHOD_SPEC_MSG = 'Unit spec should have a path matching %s'
27
-
28
- METHOD_STRING_MATCHER = /^[\#\.].+/
29
-
30
- def on_send(node)
31
- return unless top_level_describe? node
32
- _receiver, _method_name, *args = *node
33
- # Ignore non-string args (RSpec metadata)
34
- args = [args.first] + args[1..-1].select { |a| a.type == :str }
35
-
36
- if cop_config['EnforceDescribeStatement']
37
- enforce_describe_statement(node, args)
38
- end
39
-
40
- if offences.size == 0 && cop_config['EnforceFilenames']
41
- enforce_filename(node, args)
42
- end
43
- end
44
-
45
- private
46
-
47
- def enforce_describe_statement(node, args)
48
- check_described_class(node, args.first)
49
- check_described_method(node, args[1])
50
- end
51
-
52
- def enforce_filename(node, args)
53
- path_parts = const_name(args.first).split('::').map do |part|
54
- camel_to_underscore(part)
55
- end
56
-
57
- if !args[1]
58
- check_class_spec(node, path_parts)
59
- else
60
- method_str = args[1].children.first if args[1]
61
- path_parts << 'class_methods' if method_str.start_with? '.'
62
- check_method_spec(node, path_parts, method_str)
63
- end
64
- end
65
-
66
- def check_described_class(node, first_arg)
67
- if !first_arg || first_arg.type != :const
68
- add_offence(first_arg || node, :expression, DESCRIBE_CLASS_MSG)
69
- end
70
- end
71
-
72
- def check_described_method(node, second_arg)
73
- return unless second_arg
74
-
75
- unless METHOD_STRING_MATCHER =~ second_arg.children.first
76
- add_offence(second_arg, :expression, METHOD_STRING_MSG)
77
- end
78
- end
79
-
80
- def check_class_spec(node, path_parts)
81
- spec_path = File.join(path_parts) + '_spec.rb'
82
- unless source_filename.end_with? spec_path
83
- add_offence(node, :expression, format(CLASS_SPEC_MSG, spec_path))
84
- end
85
- end
86
-
87
- def check_method_spec(node, path_parts, method_str)
88
- matcher_parts = path_parts.dup
89
- # Strip out symbols; it's not worth enforcing a vocabulary for them.
90
- matcher_parts << method_str[1..-1].gsub(/\W+/, '*') + '_spec.rb'
91
-
92
- glob_matcher = File.join(matcher_parts)
93
- unless source_filename =~ regexp_from_glob(glob_matcher)
94
- message = format(METHOD_SPEC_MSG, glob_matcher)
95
- add_offence(node, :expression, message)
96
- end
97
- end
98
-
99
- def top_level_describe?(node)
100
- _receiver, method_name, *_args = *node
101
- return false unless method_name == :describe
102
-
103
- root_node = processed_source.ast
104
- top_level_nodes = describe_statement_children(root_node)
105
- # If we have no top level describe statements, we need to check any
106
- # blocks on the top level (e.g. after a require).
107
- if top_level_nodes.size == 0
108
- top_level_nodes = node_children(root_node).map do |child|
109
- describe_statement_children(child) if child.type == :block
110
- end.flatten.compact
111
- end
112
-
113
- top_level_nodes.include? node
114
- end
115
-
116
- def describe_statement_children(node)
117
- node_children(node).select do |element|
118
- element.type == :send && element.children[1] == :describe
119
- end
120
- end
121
-
122
- def source_filename
123
- processed_source.buffer.name
124
- end
125
-
126
- def camel_to_underscore(string)
127
- string.dup.tap do |result|
128
- result.gsub!(/([^A-Z])([A-Z]+)/, '\\1_\\2')
129
- result.gsub!(/([A-Z]{2,})([A-Z][^A-Z]+)/, '\\1_\\2')
130
- result.downcase!
131
- end
132
- end
133
-
134
- def regexp_from_glob(glob)
135
- Regexp.new(glob.gsub('.', '\\.').gsub('*', '.*') + '$')
136
- end
137
-
138
- def node_children(node)
139
- node.children.select { |e| e.is_a? Parser::AST::Node }
140
- end
141
- end
142
- end
143
- end
144
- end
@@ -1,137 +0,0 @@
1
- # encoding: utf-8
2
-
3
- require 'spec_helper'
4
-
5
- describe Rubocop::Cop::RSpec::UnitSpecNaming, :config do
6
- subject(:cop) { described_class.new(config) }
7
-
8
- context 'describe statement enforcement' do
9
- let(:cop_config) { { 'EnforceFilenames' => false } }
10
-
11
- it 'checks first-line describe statements' do
12
- inspect_source(cop,
13
- ['describe "bad describe" do; end'])
14
- expect(cop.offences.size).to eq(1)
15
- end
16
-
17
- it 'checks describe statements after a require' do
18
- inspect_source(cop,
19
- ["require 'spec_helper'",
20
- 'describe "bad describe" do; end'])
21
- expect(cop.offences.size).to eq(1)
22
- end
23
-
24
- it 'ignores nested describe statements' do
25
- inspect_source(cop,
26
- ['describe Some::Class do',
27
- ' describe "bad describe" do; end',
28
- 'end'])
29
- expect(cop.offences).to eq([])
30
- end
31
-
32
- it "doesn't blow up on single-line describes" do
33
- inspect_source(cop,
34
- ['describe Some::Class'])
35
- expect(cop.offences).to eq([])
36
- end
37
-
38
- it 'checks class method naming' do
39
- inspect_source(cop,
40
- ["describe Some::Class, '.asdf' do; end"])
41
- expect(cop.offences).to eq([])
42
- end
43
-
44
- it 'checks instance method naming' do
45
- inspect_source(cop,
46
- ["describe Some::Class, '#fdsa' do; end"])
47
- expect(cop.offences).to eq([])
48
- end
49
-
50
- it 'enforces non-method names' do
51
- inspect_source(cop,
52
- ["describe Some::Class, 'nope' do; end"])
53
- expect(cop.offences.size).to eq(1)
54
- end
55
- end
56
-
57
- context 'filename enforcement' do
58
- let(:cop_config) { { 'EnforceDescribeStatement' => false } }
59
-
60
- it 'checks class specs' do
61
- inspect_source(cop,
62
- ['describe Some::Class do; end'],
63
- 'some/class_spec.rb')
64
- expect(cop.offences).to eq([])
65
- end
66
-
67
- it 'handles CamelCaps class names' do
68
- inspect_source(cop,
69
- ['describe MyClass do; end'],
70
- 'my_class_spec.rb')
71
- expect(cop.offences).to eq([])
72
- end
73
-
74
- it 'handles ACRONYMClassNames' do
75
- inspect_source(cop,
76
- ['describe ABCOne::Two do; end'],
77
- 'abc_one/two_spec.rb')
78
- expect(cop.offences).to eq([])
79
- end
80
-
81
- it 'handles ALLCAPS class names' do
82
- inspect_source(cop,
83
- ['describe ALLCAPS do; end'],
84
- 'allcaps_spec.rb')
85
- expect(cop.offences).to eq([])
86
- end
87
-
88
- it 'checks instance methods' do
89
- inspect_source(cop,
90
- ["describe Some::Class, '#inst' do; end"],
91
- 'some/class/inst_spec.rb')
92
- expect(cop.offences).to eq([])
93
- end
94
-
95
- it 'checks class methods' do
96
- inspect_source(cop,
97
- ["describe Some::Class, '.inst' do; end"],
98
- 'some/class/class_methods/inst_spec.rb')
99
- expect(cop.offences).to eq([])
100
- end
101
-
102
- it 'ignores non-alphanumeric characters' do
103
- inspect_source(cop,
104
- ["describe Some::Class, '#pred?' do; end"],
105
- 'some/class/pred_spec.rb')
106
- expect(cop.offences).to eq([])
107
- end
108
-
109
- it 'allows flexibility with predicates' do
110
- inspect_source(cop,
111
- ["describe Some::Class, '#thing?' do; end"],
112
- 'some/class/thing_predicate_spec.rb')
113
- expect(cop.offences).to eq([])
114
- end
115
-
116
- it 'allows flexibility with operators' do
117
- inspect_source(cop,
118
- ["describe MyClass, '#<=>' do; end"],
119
- 'my_class/spaceship_operator_spec.rb')
120
- expect(cop.offences).to eq([])
121
- end
122
-
123
- it 'checks the path' do
124
- inspect_source(cop,
125
- ["describe MyClass, '#foo' do; end"],
126
- 'my_clas/foo_spec.rb')
127
- expect(cop.offences.size).to eq(1)
128
- end
129
-
130
- it 'checks class spec paths' do
131
- inspect_source(cop,
132
- ['describe MyClass do; end'],
133
- 'my_clas_spec.rb')
134
- expect(cop.offences.size).to eq(1)
135
- end
136
- end
137
- end