rubocop-rspec 1.12.0 → 1.13.0
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 +11 -0
- data/config/default.yml +15 -1
- data/lib/rubocop-rspec.rb +2 -0
- data/lib/rubocop/cop/rspec/any_instance.rb +7 -10
- data/lib/rubocop/cop/rspec/around_block.rb +19 -30
- data/lib/rubocop/cop/rspec/be_eql.rb +3 -7
- data/lib/rubocop/cop/rspec/before_after_all.rb +10 -16
- data/lib/rubocop/cop/rspec/cop.rb +5 -1
- data/lib/rubocop/cop/rspec/describe_class.rb +8 -8
- data/lib/rubocop/cop/rspec/describe_method.rb +6 -5
- data/lib/rubocop/cop/rspec/described_class.rb +2 -2
- data/lib/rubocop/cop/rspec/example_length.rb +5 -8
- data/lib/rubocop/cop/rspec/example_wording.rb +57 -23
- data/lib/rubocop/cop/rspec/expect_actual.rb +3 -9
- data/lib/rubocop/cop/rspec/expect_output.rb +2 -2
- data/lib/rubocop/cop/rspec/file_path.rb +30 -29
- data/lib/rubocop/cop/rspec/hook_argument.rb +1 -1
- data/lib/rubocop/cop/rspec/instance_spy.rb +12 -12
- data/lib/rubocop/cop/rspec/instance_variable.rb +2 -2
- data/lib/rubocop/cop/rspec/it_behaves_like.rb +47 -0
- data/lib/rubocop/cop/rspec/leading_subject.rb +1 -1
- data/lib/rubocop/cop/rspec/message_chain.rb +7 -4
- data/lib/rubocop/cop/rspec/message_spies.rb +6 -5
- data/lib/rubocop/cop/rspec/multiple_describes.rb +1 -1
- data/lib/rubocop/cop/rspec/multiple_expectations.rb +38 -6
- data/lib/rubocop/cop/rspec/named_subject.rb +2 -2
- data/lib/rubocop/cop/rspec/nested_groups.rb +10 -6
- data/lib/rubocop/cop/rspec/not_to_not.rb +12 -23
- data/lib/rubocop/cop/rspec/shared_context.rb +107 -0
- data/lib/rubocop/cop/rspec/single_argument_message_chain.rb +16 -23
- data/lib/rubocop/cop/rspec/subject_stub.rb +4 -4
- data/lib/rubocop/cop/rspec/verified_doubles.rb +4 -3
- data/lib/rubocop/rspec/example_group.rb +1 -1
- data/lib/rubocop/rspec/language.rb +25 -7
- data/lib/rubocop/rspec/version.rb +1 -1
- data/spec/expect_violation/expectation_spec.rb +16 -16
- data/spec/project/changelog_spec.rb +1 -1
- data/spec/project/default_config_spec.rb +1 -1
- data/spec/project/project_requires_spec.rb +1 -1
- data/spec/rubocop/cop/rspec/any_instance_spec.rb +4 -4
- data/spec/rubocop/cop/rspec/around_block_spec.rb +115 -26
- data/spec/rubocop/cop/rspec/be_eql_spec.rb +9 -9
- data/spec/rubocop/cop/rspec/before_after_all_spec.rb +38 -80
- data/spec/rubocop/cop/rspec/describe_class_spec.rb +1 -1
- data/spec/rubocop/cop/rspec/describe_method_spec.rb +2 -2
- data/spec/rubocop/cop/rspec/described_class_spec.rb +13 -13
- data/spec/rubocop/cop/rspec/empty_example_group_spec.rb +1 -1
- data/spec/rubocop/cop/rspec/example_length_spec.rb +3 -32
- data/spec/rubocop/cop/rspec/example_wording_spec.rb +21 -2
- data/spec/rubocop/cop/rspec/expect_actual_spec.rb +33 -18
- data/spec/rubocop/cop/rspec/expect_output_spec.rb +3 -3
- data/spec/rubocop/cop/rspec/file_path_spec.rb +119 -170
- data/spec/rubocop/cop/rspec/focus_spec.rb +1 -1
- data/spec/rubocop/cop/rspec/hook_argument_spec.rb +1 -3
- data/spec/rubocop/cop/rspec/implicit_expect_spec.rb +1 -1
- data/spec/rubocop/cop/rspec/instance_spy_spec.rb +11 -11
- data/spec/rubocop/cop/rspec/instance_variable_spec.rb +4 -4
- data/spec/rubocop/cop/rspec/it_behaves_like_spec.rb +51 -0
- data/spec/rubocop/cop/rspec/leading_subject_spec.rb +1 -1
- data/spec/rubocop/cop/rspec/let_setup_spec.rb +1 -1
- data/spec/rubocop/cop/rspec/message_chain_spec.rb +3 -3
- data/spec/rubocop/cop/rspec/message_expectation_spec.rb +5 -23
- data/spec/rubocop/cop/rspec/message_spies_spec.rb +9 -23
- data/spec/rubocop/cop/rspec/multiple_describes_spec.rb +1 -1
- data/spec/rubocop/cop/rspec/multiple_expectations_spec.rb +66 -3
- data/spec/rubocop/cop/rspec/nested_groups_spec.rb +4 -4
- data/spec/rubocop/cop/rspec/not_to_not_spec.rb +3 -3
- data/spec/rubocop/cop/rspec/repeated_description_spec.rb +1 -1
- data/spec/rubocop/cop/rspec/repeated_example_spec.rb +1 -1
- data/spec/rubocop/cop/rspec/scattered_setup_spec.rb +1 -1
- data/spec/rubocop/cop/rspec/shared_context_spec.rb +142 -0
- data/spec/rubocop/cop/rspec/single_argument_message_chain_spec.rb +5 -5
- data/spec/rubocop/cop/rspec/subject_stub_spec.rb +1 -1
- data/spec/rubocop/cop/rspec/verified_doubles_spec.rb +2 -2
- data/spec/rubocop/rspec/config_formatter_spec.rb +12 -12
- data/spec/rubocop/rspec/description_extractor_spec.rb +23 -23
- data/spec/rubocop/rspec/example_group_spec.rb +11 -11
- data/spec/rubocop/rspec/example_spec.rb +1 -1
- data/spec/rubocop/rspec/language/selector_set_spec.rb +1 -1
- data/spec/rubocop/rspec/util/one_spec.rb +1 -1
- data/spec/rubocop/rspec/wording_spec.rb +1 -1
- data/spec/shared/detects_style_behavior.rb +3 -4
- data/spec/spec_helper.rb +10 -0
- metadata +8 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 94ad662f54f32cf6cbde51f8c2fdd788fa44e989
|
4
|
+
data.tar.gz: d0c3723b84a23c6589aa10d9f379b7d56b332bcc
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: fbc83814064a1e25163689e9da12bcfcac4c8f0849c62fe34adb13b6fa7a569f8a37a627bd04fe067f28bec140c4d8f89c9b2bed537b21eaafdeac9ad32c8663
|
7
|
+
data.tar.gz: cf26853505de97b2ba385add43eb5cbf71cac5395c9f773208f93d4bd02b9650e023ee9a27b4c0f23e0ee7909370d8c8060fa05fa2299aa639ba3837054cdfb1
|
data/CHANGELOG.md
CHANGED
@@ -2,6 +2,16 @@
|
|
2
2
|
|
3
3
|
## Master (Unreleased)
|
4
4
|
|
5
|
+
## 1.13.0 (2017-03-07)
|
6
|
+
|
7
|
+
* Add repeated 'it' detection to `RSpec/ExampleWording` cop. ([@dgollahon][])
|
8
|
+
* Add [observed_nesting/max_nesting] info to `RSpec/NestedGroups` messages. ([@dgollahon][])
|
9
|
+
* Add `RSpec/ItBehavesLike` cop. ([@dgollahon][])
|
10
|
+
* Add `RSpec/SharedContext` cop. ([@Darhazer][])
|
11
|
+
* `Rspec/MultipleExpectations`: Count aggregate_failures block as single expectation. ([@Darhazer][])
|
12
|
+
* Fix `ExpectActual` cop flagging `rspec-rails` routing specs. ([@backus][])
|
13
|
+
* Fix `FilePath` cop not registering offenses for files like `spec/blog/user.rb` when it should be `spec/blog/user_spec.rb`. ([@backus][])
|
14
|
+
|
5
15
|
## 1.12.0 (2017-02-21)
|
6
16
|
|
7
17
|
* Add `RSpec/InstanceSpy` cop. ([@Darhazer][])
|
@@ -186,3 +196,4 @@
|
|
186
196
|
[@Darhazer]: https://github.com/Darhazer
|
187
197
|
[@redross]: https://github.com/redross
|
188
198
|
[@cfabianski]: https://github.com/cfabianski
|
199
|
+
[@dgollahon]: https://github.com/dgollahon
|
data/config/default.yml
CHANGED
@@ -53,7 +53,7 @@ RSpec/ExampleLength:
|
|
53
53
|
Max: 5
|
54
54
|
|
55
55
|
RSpec/ExampleWording:
|
56
|
-
Description: Checks
|
56
|
+
Description: Checks for common mistakes in example descriptions.
|
57
57
|
Enabled: true
|
58
58
|
CustomTransform:
|
59
59
|
be: is
|
@@ -64,6 +64,8 @@ RSpec/ExampleWording:
|
|
64
64
|
RSpec/ExpectActual:
|
65
65
|
Description: Checks for `expect(...)` calls containing literal values.
|
66
66
|
Enabled: true
|
67
|
+
Exclude:
|
68
|
+
- spec/routing/**/*
|
67
69
|
|
68
70
|
RSpec/ExpectOutput:
|
69
71
|
Description: Checks for opportunities to use `expect { ... }.to output`.
|
@@ -107,6 +109,14 @@ RSpec/InstanceVariable:
|
|
107
109
|
AssignmentOnly: false
|
108
110
|
Enabled: true
|
109
111
|
|
112
|
+
RSpec/ItBehavesLike:
|
113
|
+
Description: Checks that only one `it_behaves_like` style is used.
|
114
|
+
Enabled: true
|
115
|
+
EnforcedStyle: it_behaves_like
|
116
|
+
SupportedStyles:
|
117
|
+
- it_behaves_like
|
118
|
+
- it_should_behave_like
|
119
|
+
|
110
120
|
RSpec/LeadingSubject:
|
111
121
|
Description: Checks for `subject` definitions that come after `let` definitions.
|
112
122
|
Enabled: true
|
@@ -169,6 +179,10 @@ RSpec/RepeatedExample:
|
|
169
179
|
Enabled: true
|
170
180
|
Description: Check for repeated examples within example groups.
|
171
181
|
|
182
|
+
RSpec/SharedContext:
|
183
|
+
Description: Checks for proper shared_context and shared_examples usage.
|
184
|
+
Enabled: true
|
185
|
+
|
172
186
|
RSpec/SingleArgumentMessageChain:
|
173
187
|
Description: Checks that chains of messages contain more than one element.
|
174
188
|
Enabled: true
|
data/lib/rubocop-rspec.rb
CHANGED
@@ -38,6 +38,7 @@ require 'rubocop/cop/rspec/hook_argument'
|
|
38
38
|
require 'rubocop/cop/rspec/implicit_expect'
|
39
39
|
require 'rubocop/cop/rspec/instance_spy'
|
40
40
|
require 'rubocop/cop/rspec/instance_variable'
|
41
|
+
require 'rubocop/cop/rspec/it_behaves_like'
|
41
42
|
require 'rubocop/cop/rspec/leading_subject'
|
42
43
|
require 'rubocop/cop/rspec/let_setup'
|
43
44
|
require 'rubocop/cop/rspec/message_chain'
|
@@ -51,6 +52,7 @@ require 'rubocop/cop/rspec/not_to_not'
|
|
51
52
|
require 'rubocop/cop/rspec/repeated_description'
|
52
53
|
require 'rubocop/cop/rspec/repeated_example'
|
53
54
|
require 'rubocop/cop/rspec/scattered_setup'
|
55
|
+
require 'rubocop/cop/rspec/shared_context'
|
54
56
|
require 'rubocop/cop/rspec/single_argument_message_chain'
|
55
57
|
require 'rubocop/cop/rspec/subject_stub'
|
56
58
|
require 'rubocop/cop/rspec/verified_doubles'
|
@@ -21,19 +21,16 @@ module RuboCop
|
|
21
21
|
# end
|
22
22
|
# end
|
23
23
|
class AnyInstance < Cop
|
24
|
-
|
24
|
+
MSG = 'Avoid stubbing using `%{method}`.'.freeze
|
25
25
|
|
26
|
-
|
27
|
-
:any_instance
|
28
|
-
|
29
|
-
:expect_any_instance_of
|
30
|
-
].freeze
|
26
|
+
def_node_matcher :disallowed_stub, <<-PATTERN
|
27
|
+
(send _ ${:any_instance :allow_any_instance_of :expect_any_instance_of} ...)
|
28
|
+
PATTERN
|
31
29
|
|
32
30
|
def on_send(node)
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
add_offense(node, :expression, format(MESSAGE, method: method_name))
|
31
|
+
disallowed_stub(node) do |method|
|
32
|
+
add_offense(node, :expression, format(MSG, method: method))
|
33
|
+
end
|
37
34
|
end
|
38
35
|
end
|
39
36
|
end
|
@@ -24,53 +24,42 @@ module RuboCop
|
|
24
24
|
# test.run
|
25
25
|
# end
|
26
26
|
class AroundBlock < Cop
|
27
|
-
MSG_NO_ARG
|
28
|
-
MSG_UNUSED_ARG = 'You should call `%<arg>s.call` '
|
29
|
-
|
27
|
+
MSG_NO_ARG = 'Test object should be passed to around block.'.freeze
|
28
|
+
MSG_UNUSED_ARG = 'You should call `%<arg>s.call` '\
|
29
|
+
'or `%<arg>s.run`.'.freeze
|
30
30
|
|
31
|
-
def_node_matcher :
|
32
|
-
|
31
|
+
def_node_matcher :hook, <<-PATTERN
|
32
|
+
(block {(send nil :around) (send nil :around sym)} (args $...) ...)
|
33
33
|
PATTERN
|
34
34
|
|
35
|
-
|
36
|
-
|
35
|
+
def_node_search :find_arg_usage, <<-PATTERN
|
36
|
+
{(send $... {:call :run}) (send _ _ $...) (yield $...) (block-pass $...)}
|
37
37
|
PATTERN
|
38
38
|
|
39
|
-
def_node_search :find_arg_usage, '(lvar $_)'
|
40
|
-
|
41
39
|
def on_block(node)
|
42
|
-
hook(node) do |
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
unused_parameters(parameters) do |param, name|
|
49
|
-
add_offense(param, :expression, format(MSG_UNUSED_ARG, arg: name))
|
40
|
+
hook(node) do |(example_proxy)|
|
41
|
+
if example_proxy.nil?
|
42
|
+
add_no_arg_offense(node)
|
43
|
+
else
|
44
|
+
check_for_unused_proxy(node, example_proxy)
|
50
45
|
end
|
51
46
|
end
|
52
47
|
end
|
53
48
|
|
54
49
|
private
|
55
50
|
|
56
|
-
def
|
57
|
-
|
51
|
+
def add_no_arg_offense(node)
|
52
|
+
add_offense(node, :expression, MSG_NO_ARG)
|
58
53
|
end
|
59
54
|
|
60
|
-
def
|
61
|
-
|
62
|
-
param, _methods, _args = *first_arg
|
63
|
-
start = node.parent
|
55
|
+
def check_for_unused_proxy(block, proxy)
|
56
|
+
name, = *proxy
|
64
57
|
|
65
|
-
find_arg_usage(
|
66
|
-
return if
|
58
|
+
find_arg_usage(block) do |usage|
|
59
|
+
return if usage.include?(s(:lvar, name))
|
67
60
|
end
|
68
61
|
|
69
|
-
|
70
|
-
end
|
71
|
-
|
72
|
-
def hook(node, &block)
|
73
|
-
scoped_hook(node, &block) || unscoped_hook(node, &block)
|
62
|
+
add_offense(proxy, :expression, format(MSG_UNUSED_ARG, arg: name))
|
74
63
|
end
|
75
64
|
end
|
76
65
|
end
|
@@ -34,22 +34,18 @@ module RuboCop
|
|
34
34
|
# coerce objects for comparison.
|
35
35
|
#
|
36
36
|
class BeEql < Cop
|
37
|
-
MSG = 'Prefer `be` over `eql
|
37
|
+
MSG = 'Prefer `be` over `eql`.'.freeze
|
38
38
|
|
39
39
|
def_node_matcher :eql_type_with_identity, <<-PATTERN
|
40
40
|
(send _ :to $(send nil :eql {true false int float sym nil_type?}))
|
41
41
|
PATTERN
|
42
42
|
|
43
43
|
def on_send(node)
|
44
|
-
eql_type_with_identity(node)
|
45
|
-
add_offense(eql, :selector, MSG)
|
46
|
-
end
|
44
|
+
eql_type_with_identity(node) { |eql| add_offense(eql, :selector) }
|
47
45
|
end
|
48
46
|
|
49
47
|
def autocorrect(node)
|
50
|
-
|
51
|
-
corrector.replace(node.loc.selector, 'be')
|
52
|
-
end
|
48
|
+
->(corrector) { corrector.replace(node.loc.selector, 'be') }
|
53
49
|
end
|
54
50
|
end
|
55
51
|
end
|
@@ -24,25 +24,19 @@ module RuboCop
|
|
24
24
|
# after(:each) { Widget.delete_all }
|
25
25
|
# end
|
26
26
|
class BeforeAfterAll < Cop
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
27
|
+
MSG = 'Beware of using `%<hook>s` as it may cause state to leak '\
|
28
|
+
'between tests. If you are using `rspec-rails`, and '\
|
29
|
+
'`use_transactional_fixtures` is enabled, then records created '\
|
30
|
+
'in `%<hook>s` are not automatically rolled back.'.freeze
|
31
31
|
|
32
|
-
|
33
|
-
:before
|
34
|
-
|
35
|
-
].freeze
|
36
|
-
|
37
|
-
ALL_PAIR = s(:sym, :all)
|
38
|
-
CONTEXT_PAIR = s(:sym, :context)
|
32
|
+
def_node_matcher :before_or_after_all, <<-PATTERN
|
33
|
+
$(send _ {:before :after} (sym {:all :context}))
|
34
|
+
PATTERN
|
39
35
|
|
40
36
|
def on_send(node)
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
add_offense(node, :expression, MESSAGE)
|
37
|
+
before_or_after_all(node) do |hook|
|
38
|
+
add_offense(node, :expression, format(MSG, hook: hook.source))
|
39
|
+
end
|
46
40
|
end
|
47
41
|
end
|
48
42
|
end
|
@@ -44,11 +44,15 @@ module RuboCop
|
|
44
44
|
end
|
45
45
|
|
46
46
|
def relevant_file?(file)
|
47
|
-
|
47
|
+
relevant_rubocop_rspec_file?(file) && super
|
48
48
|
end
|
49
49
|
|
50
50
|
private
|
51
51
|
|
52
|
+
def relevant_rubocop_rspec_file?(file)
|
53
|
+
rspec_pattern =~ file
|
54
|
+
end
|
55
|
+
|
52
56
|
def rspec_pattern
|
53
57
|
Regexp.union(rspec_pattern_config.map(&Regexp.public_method(:new)))
|
54
58
|
end
|
@@ -23,20 +23,20 @@ module RuboCop
|
|
23
23
|
'the class or module being tested.'.freeze
|
24
24
|
|
25
25
|
def_node_matcher :valid_describe?, <<-PATTERN
|
26
|
-
|
26
|
+
{(send {(const nil :RSpec) nil} :describe const ...) (send nil :describe)}
|
27
27
|
PATTERN
|
28
28
|
|
29
29
|
def_node_matcher :describe_with_metadata, <<-PATTERN
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
30
|
+
(send {(const nil :RSpec) nil} :describe
|
31
|
+
!const
|
32
|
+
...
|
33
|
+
(hash $...))
|
34
34
|
PATTERN
|
35
35
|
|
36
36
|
def_node_matcher :rails_metadata?, <<-PATTERN
|
37
|
-
|
38
|
-
|
39
|
-
|
37
|
+
(pair
|
38
|
+
(sym :type)
|
39
|
+
(sym {:request :feature :routing :view}))
|
40
40
|
PATTERN
|
41
41
|
|
42
42
|
def_node_matcher :shared_group?, <<-PATTERN
|
@@ -20,15 +20,16 @@ module RuboCop
|
|
20
20
|
include RuboCop::RSpec::TopLevelDescribe,
|
21
21
|
RuboCop::RSpec::Util
|
22
22
|
|
23
|
-
|
24
|
-
|
25
|
-
|
23
|
+
MSG = 'The second argument to describe should be the method '\
|
24
|
+
"being tested. '#instance' or '.class'.".freeze
|
25
|
+
|
26
|
+
METHOD_STRING_MATCHER = /\A[\#\.].+/
|
26
27
|
|
27
28
|
def on_top_level_describe(_node, (_, second_arg))
|
28
|
-
return unless second_arg && second_arg.
|
29
|
+
return unless second_arg && second_arg.str_type?
|
29
30
|
return if METHOD_STRING_MATCHER =~ one(second_arg.children)
|
30
31
|
|
31
|
-
add_offense(second_arg, :expression
|
32
|
+
add_offense(second_arg, :expression)
|
32
33
|
end
|
33
34
|
end
|
34
35
|
end
|
@@ -34,10 +34,10 @@ module RuboCop
|
|
34
34
|
#
|
35
35
|
class DescribedClass < Cop
|
36
36
|
include RuboCop::RSpec::TopLevelDescribe
|
37
|
-
include
|
37
|
+
include ConfigurableEnforcedStyle
|
38
38
|
|
39
39
|
DESCRIBED_CLASS = 'described_class'.freeze
|
40
|
-
MSG = 'Use `%s` instead of `%s
|
40
|
+
MSG = 'Use `%s` instead of `%s`.'.freeze
|
41
41
|
|
42
42
|
def_node_matcher :common_instance_exec_closure?, <<-PATTERN
|
43
43
|
(block (send (const nil {:Class :Module}) :new ...) ...)
|
@@ -28,29 +28,26 @@ module RuboCop
|
|
28
28
|
class ExampleLength < Cop
|
29
29
|
include CodeLength
|
30
30
|
|
31
|
-
|
31
|
+
MSG = 'Example has too many lines [%d/%d].'.freeze
|
32
32
|
|
33
33
|
def on_block(node)
|
34
|
-
|
35
|
-
_receiver, method_name, _object = *method
|
36
|
-
return unless EXAMPLE_BLOCKS.include?(method_name)
|
34
|
+
return unless example?(node)
|
37
35
|
|
38
36
|
length = code_length(node)
|
39
37
|
|
40
38
|
return unless length > max_length
|
39
|
+
|
41
40
|
add_offense(node, :expression, message(length))
|
42
41
|
end
|
43
42
|
|
44
43
|
private
|
45
44
|
|
46
45
|
def code_length(node)
|
47
|
-
|
48
|
-
|
49
|
-
lines.count { |line| !irrelevant_line(line) }
|
46
|
+
node.source.lines[1..-2].count { |line| !irrelevant_line(line) }
|
50
47
|
end
|
51
48
|
|
52
49
|
def message(length)
|
53
|
-
format(
|
50
|
+
format(MSG, length, max_length)
|
54
51
|
end
|
55
52
|
end
|
56
53
|
end
|
@@ -3,7 +3,9 @@
|
|
3
3
|
module RuboCop
|
4
4
|
module Cop
|
5
5
|
module RSpec
|
6
|
-
# Checks
|
6
|
+
# Checks for common mistakes in example descriptions.
|
7
|
+
#
|
8
|
+
# This cop will correct docstrings that begin with 'should' and 'it'.
|
7
9
|
#
|
8
10
|
# @see http://betterspecs.org/#should
|
9
11
|
#
|
@@ -18,42 +20,74 @@ module RuboCop
|
|
18
20
|
# # good
|
19
21
|
# it 'finds nothing' do
|
20
22
|
# end
|
23
|
+
#
|
24
|
+
# @example
|
25
|
+
# # bad
|
26
|
+
# it 'it does things' do
|
27
|
+
# end
|
28
|
+
#
|
29
|
+
# # good
|
30
|
+
# it 'does things' do
|
31
|
+
# end
|
21
32
|
class ExampleWording < Cop
|
22
|
-
|
33
|
+
MSG_SHOULD = 'Do not use should when describing your tests.'.freeze
|
34
|
+
MSG_IT = "Do not repeat 'it' when describing your tests.".freeze
|
23
35
|
|
24
|
-
|
25
|
-
|
26
|
-
_, method_name, *args = *method
|
36
|
+
SHOULD_PREFIX = 'should'.freeze
|
37
|
+
IT_PREFIX = 'it '.freeze
|
27
38
|
|
28
|
-
|
39
|
+
def_node_matcher(
|
40
|
+
:it_description,
|
41
|
+
'(block (send _ :it $(str $_) ...) ...)'
|
42
|
+
)
|
29
43
|
|
30
|
-
|
31
|
-
|
32
|
-
|
44
|
+
def on_block(node)
|
45
|
+
it_description(node) do |description_node, message|
|
46
|
+
text = message.downcase
|
33
47
|
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
48
|
+
if text.start_with?(SHOULD_PREFIX)
|
49
|
+
add_wording_offense(description_node, MSG_SHOULD)
|
50
|
+
elsif text.start_with?(IT_PREFIX)
|
51
|
+
add_wording_offense(description_node, MSG_IT)
|
52
|
+
end
|
53
|
+
end
|
40
54
|
end
|
41
55
|
|
42
56
|
def autocorrect(range)
|
43
57
|
lambda do |corrector|
|
44
|
-
corrector.replace(
|
45
|
-
range,
|
46
|
-
RuboCop::RSpec::Wording.new(
|
47
|
-
range.source,
|
48
|
-
ignore: ignored_words,
|
49
|
-
replace: custom_transform
|
50
|
-
).rewrite
|
51
|
-
)
|
58
|
+
corrector.replace(range, replacement_text(range))
|
52
59
|
end
|
53
60
|
end
|
54
61
|
|
55
62
|
private
|
56
63
|
|
64
|
+
def add_wording_offense(node, message)
|
65
|
+
expr = node.loc.expression
|
66
|
+
|
67
|
+
docstring =
|
68
|
+
Parser::Source::Range.new(
|
69
|
+
expr.source_buffer,
|
70
|
+
expr.begin_pos + 1,
|
71
|
+
expr.end_pos - 1
|
72
|
+
)
|
73
|
+
|
74
|
+
add_offense(docstring, docstring, message)
|
75
|
+
end
|
76
|
+
|
77
|
+
def replacement_text(range)
|
78
|
+
text = range.source
|
79
|
+
|
80
|
+
if text.start_with?('should')
|
81
|
+
RuboCop::RSpec::Wording.new(
|
82
|
+
text,
|
83
|
+
ignore: ignored_words,
|
84
|
+
replace: custom_transform
|
85
|
+
).rewrite
|
86
|
+
elsif text.start_with?(IT_PREFIX)
|
87
|
+
text.sub(IT_PREFIX, '')
|
88
|
+
end
|
89
|
+
end
|
90
|
+
|
57
91
|
def custom_transform
|
58
92
|
cop_config.fetch('CustomTransform', {})
|
59
93
|
end
|