rubocop-rspec 1.15.0 → 1.15.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (32) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +7 -1
  3. data/Rakefile +1 -1
  4. data/config/default.yml +2 -1
  5. data/lib/rubocop/cop/rspec/cop.rb +3 -2
  6. data/lib/rubocop/cop/rspec/describe_method.rb +2 -2
  7. data/lib/rubocop/cop/rspec/example_wording.rb +7 -11
  8. data/lib/rubocop/cop/rspec/expect_actual.rb +4 -4
  9. data/lib/rubocop/cop/rspec/iterated_expectation.rb +1 -1
  10. data/lib/rubocop/cop/rspec/leading_subject.rb +1 -1
  11. data/lib/rubocop/cop/rspec/message_expectation.rb +1 -1
  12. data/lib/rubocop/cop/rspec/message_spies.rb +1 -1
  13. data/lib/rubocop/cop/rspec/single_argument_message_chain.rb +23 -3
  14. data/lib/rubocop/rspec/concept.rb +3 -2
  15. data/lib/rubocop/rspec/hook.rb +1 -1
  16. data/lib/rubocop/rspec/language.rb +17 -17
  17. data/lib/rubocop/rspec/version.rb +1 -1
  18. data/lib/rubocop/rspec/wording.rb +53 -19
  19. data/spec/expect_violation/expectation_spec.rb +1 -1
  20. data/spec/project/default_config_spec.rb +2 -2
  21. data/spec/rubocop/cop/rspec/cop_spec.rb +1 -1
  22. data/spec/rubocop/cop/rspec/described_class_spec.rb +1 -1
  23. data/spec/rubocop/cop/rspec/empty_example_group_spec.rb +1 -1
  24. data/spec/rubocop/cop/rspec/example_wording_spec.rb +41 -2
  25. data/spec/rubocop/cop/rspec/iterated_expectation_spec.rb +8 -0
  26. data/spec/rubocop/cop/rspec/multiple_expectations_spec.rb +1 -1
  27. data/spec/rubocop/cop/rspec/single_argument_message_chain_spec.rb +39 -0
  28. data/spec/rubocop/rspec/example_spec.rb +1 -1
  29. data/spec/rubocop/rspec/language/selector_set_spec.rb +4 -4
  30. data/spec/rubocop/rspec/wording_spec.rb +14 -8
  31. data/spec/support/expect_violation.rb +10 -8
  32. metadata +3 -3
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 05c5a02b8f251474055785a8e599fa2bbd66a5da
4
- data.tar.gz: 4d34abb87f561cbe99dcd4df35d4d2e4b8eb1499
3
+ metadata.gz: 6a604474acdd504b70582e29579a8ec65a6bbbfa
4
+ data.tar.gz: f8fa3ac1215089b95341115ca35edb73ddb148c3
5
5
  SHA512:
6
- metadata.gz: 55de6981f33d7f310a4290a1fc4578bb6d0ba905a2ce4ea86f966d025165cfd6d08d05f5198b56dcd207178724f574e6e046cb4af01be02a7e36662cfe792647
7
- data.tar.gz: 73f5cdbc39ed5bc4aaa0d2fa8aa0769855b09f2d960ccf5078638582be79556109a491819a4253414a567a50baef1e66b6b737203998a57fad0cf2997c4446ca
6
+ metadata.gz: a0d4f97983ce7f1147d32b8948d22d5c7b30490a946e5500e2aa78f60daad47f9e68eac81e6da2825e83f8248a8a8ed4dfd538a30e4b7dcc9af462fee16bda2c
7
+ data.tar.gz: dd3bc63ff868cef005a10da71f873dc804d333fd8950de8636d980064341b386a74e281ba698d051859c7c4ddceb7ee257d527ac68c7129fd660f7321014b9ac
@@ -2,7 +2,13 @@
2
2
 
3
3
  ## Master (Unreleased)
4
4
 
5
- ## 1.15.0 (2017-05-24)
5
+ ## 1.15.1 (2017-04-30)
6
+
7
+ * Fix the handling of various edge cases in the `RSpec/ExampleWording` cop, including one that would cause autocorrect to crash. ([@dgollahon][])
8
+ * Fix `RSpec/IteratedExpectation` crashing when there is an assignment in the iteration. ([@Darhazer][])
9
+ * Fix false positive in `RSpec/SingleArgumentMessageChain` cop when the single argument is a hash. ([@Darhazer][])
10
+
11
+ ## 1.15.0 (2017-03-26)
6
12
 
7
13
  * Add `RSpec/DescribeSymbol` cop. ([@tsigo][])
8
14
  * Fix error when `RSpec/OverwritingSetup` and `RSpec/ScatteredLet` analyzed empty example groups. ([@backus][])
data/Rakefile CHANGED
@@ -44,4 +44,4 @@ task confirm_config: :build_config do
44
44
  end
45
45
  end
46
46
 
47
- task default: %i(build_config coverage internal_investigation confirm_config)
47
+ task default: %i[build_config coverage internal_investigation confirm_config]
@@ -73,8 +73,9 @@ RSpec/ExampleWording:
73
73
  Enabled: true
74
74
  CustomTransform:
75
75
  be: is
76
+ BE: IS
76
77
  have: has
77
- not: does not
78
+ HAVE: HAS
78
79
  IgnoredWords: []
79
80
 
80
81
  RSpec/ExpectActual:
@@ -33,11 +33,12 @@ module RuboCop
33
33
  # - '_test.rb$'
34
34
  # - '(?:^|/)test/'
35
35
  class Cop < WorkaroundCop
36
+ include RuboCop::RSpec::Language
37
+ include RuboCop::RSpec::Language::NodePattern
38
+
36
39
  DEFAULT_CONFIGURATION =
37
40
  RuboCop::RSpec::CONFIG.fetch('AllCops').fetch('RSpec')
38
41
 
39
- include RuboCop::RSpec::Language, RuboCop::RSpec::Language::NodePattern
40
-
41
42
  # Invoke the original inherited hook so our cops are recognized
42
43
  def self.inherited(subclass)
43
44
  RuboCop::Cop::Cop.inherited(subclass)
@@ -17,8 +17,8 @@ module RuboCop
17
17
  # describe MyClass, '.my_class_method' do
18
18
  # end
19
19
  class DescribeMethod < Cop
20
- include RuboCop::RSpec::TopLevelDescribe,
21
- RuboCop::RSpec::Util
20
+ include RuboCop::RSpec::TopLevelDescribe
21
+ include RuboCop::RSpec::Util
22
22
 
23
23
  MSG = 'The second argument to describe should be the method '\
24
24
  "being tested. '#instance' or '.class'.".freeze
@@ -33,8 +33,8 @@ module RuboCop
33
33
  MSG_SHOULD = 'Do not use should when describing your tests.'.freeze
34
34
  MSG_IT = "Do not repeat 'it' when describing your tests.".freeze
35
35
 
36
- SHOULD_PREFIX = 'should'.freeze
37
- IT_PREFIX = 'it '.freeze
36
+ SHOULD_PREFIX = /\Ashould(?:n't)?\b/i
37
+ IT_PREFIX = /\Ait /i
38
38
 
39
39
  def_node_matcher(
40
40
  :it_description,
@@ -43,20 +43,16 @@ module RuboCop
43
43
 
44
44
  def on_block(node)
45
45
  it_description(node) do |description_node, message|
46
- text = message.downcase
47
-
48
- if text.start_with?(SHOULD_PREFIX)
46
+ if message =~ SHOULD_PREFIX
49
47
  add_wording_offense(description_node, MSG_SHOULD)
50
- elsif text.start_with?(IT_PREFIX)
48
+ elsif message =~ IT_PREFIX
51
49
  add_wording_offense(description_node, MSG_IT)
52
50
  end
53
51
  end
54
52
  end
55
53
 
56
54
  def autocorrect(range)
57
- lambda do |corrector|
58
- corrector.replace(range, replacement_text(range))
59
- end
55
+ ->(corrector) { corrector.replace(range, replacement_text(range)) }
60
56
  end
61
57
 
62
58
  private
@@ -77,13 +73,13 @@ module RuboCop
77
73
  def replacement_text(range)
78
74
  text = range.source
79
75
 
80
- if text.start_with?('should')
76
+ if text =~ SHOULD_PREFIX
81
77
  RuboCop::RSpec::Wording.new(
82
78
  text,
83
79
  ignore: ignored_words,
84
80
  replace: custom_transform
85
81
  ).rewrite
86
- elsif text.start_with?(IT_PREFIX)
82
+ else
87
83
  text.sub(IT_PREFIX, '')
88
84
  end
89
85
  end
@@ -19,7 +19,7 @@ module RuboCop
19
19
  class ExpectActual < Cop
20
20
  MSG = 'Provide the actual you are testing to `expect(...)`.'.freeze
21
21
 
22
- SIMPLE_LITERALS = %i(
22
+ SIMPLE_LITERALS = %i[
23
23
  true
24
24
  false
25
25
  nil
@@ -30,16 +30,16 @@ module RuboCop
30
30
  complex
31
31
  rational
32
32
  regopt
33
- ).freeze
33
+ ].freeze
34
34
 
35
- COMPLEX_LITERALS = %i(
35
+ COMPLEX_LITERALS = %i[
36
36
  array
37
37
  hash
38
38
  pair
39
39
  irange
40
40
  erange
41
41
  regexp
42
- ).freeze
42
+ ].freeze
43
43
 
44
44
  def_node_matcher :expect_literal, '(send _ :expect $#literal?)'
45
45
 
@@ -44,7 +44,7 @@ module RuboCop
44
44
  end
45
45
 
46
46
  def only_expectations?(body, arg)
47
- body.children.all? { |child| expectation?(child, arg) }
47
+ body.each_child_node.all? { |child| expectation?(child, arg) }
48
48
  end
49
49
  end
50
50
  end
@@ -54,7 +54,7 @@ module RuboCop
54
54
  private
55
55
 
56
56
  def let?(node)
57
- [:let, :let!].include?(node.method_name)
57
+ %i[let let!].include?(node.method_name)
58
58
  end
59
59
 
60
60
  def find_first_let(node)
@@ -29,7 +29,7 @@ module RuboCop
29
29
 
30
30
  MSG = 'Prefer `%s` for setting message expectations.'.freeze
31
31
 
32
- SUPPORTED_STYLES = %w(allow expect).freeze
32
+ SUPPORTED_STYLES = %w[allow expect].freeze
33
33
 
34
34
  def_node_matcher :message_expectation, <<-PATTERN
35
35
  (send $(send nil {:expect :allow} ...) :to #receive_message?)
@@ -34,7 +34,7 @@ module RuboCop
34
34
  'expectations. Setup `%s` as a spy using `allow`'\
35
35
  ' or `instance_spy`.'.freeze
36
36
 
37
- SUPPORTED_STYLES = %w(have_received receive).freeze
37
+ SUPPORTED_STYLES = %w[have_received receive].freeze
38
38
 
39
39
  def_node_matcher :message_expectation, %(
40
40
  (send (send nil :expect $_) {:to :to_not :not_to} ...)
@@ -19,12 +19,16 @@ module RuboCop
19
19
  '`%<called>s` with a single argument.'.freeze
20
20
 
21
21
  def_node_matcher :message_chain, <<-PATTERN
22
- (send _ #{Matchers::MESSAGE_CHAIN.node_pattern_union} $...)
22
+ (send _ #{Matchers::MESSAGE_CHAIN.node_pattern_union} $_)
23
23
  PATTERN
24
24
 
25
+ def_node_matcher :single_key_hash?, '(hash pair)'
26
+
25
27
  def on_send(node)
26
- message_chain(node) do |(first, *remaining)|
27
- return if first.to_s.include?('.') || remaining.any?
28
+ message_chain(node) do |arg|
29
+ return if arg.to_s.include?('.')
30
+
31
+ return if arg.hash_type? && !single_key_hash?(arg)
28
32
 
29
33
  add_offense(node, :selector)
30
34
  end
@@ -33,11 +37,27 @@ module RuboCop
33
37
  def autocorrect(node)
34
38
  lambda do |corrector|
35
39
  corrector.replace(node.loc.selector, replacement(node.method_name))
40
+ message_chain(node) do |arg|
41
+ autocorrect_hash_arg(corrector, arg) if single_key_hash?(arg)
42
+ end
36
43
  end
37
44
  end
38
45
 
39
46
  private
40
47
 
48
+ def autocorrect_hash_arg(corrector, arg)
49
+ key, value = *arg.children.first
50
+
51
+ corrector.replace(arg.loc.expression, key_to_arg(key))
52
+ corrector.insert_after(arg.parent.loc.end,
53
+ ".and_return(#{value.source})")
54
+ end
55
+
56
+ def key_to_arg(node)
57
+ key, = *node
58
+ node.sym_type? ? ":#{key}" : node.source
59
+ end
60
+
41
61
  def replacement(method)
42
62
  method.equal?(:receive_message_chain) ? 'receive' : 'stub'
43
63
  end
@@ -4,7 +4,8 @@ module RuboCop
4
4
  module RSpec
5
5
  # Wrapper for RSpec DSL methods
6
6
  class Concept
7
- include Language, Language::NodePattern
7
+ include Language
8
+ include Language::NodePattern
8
9
  extend NodePattern::Macros
9
10
 
10
11
  def initialize(node)
@@ -12,7 +13,7 @@ module RuboCop
12
13
  end
13
14
 
14
15
  def eql?(other)
15
- node.eql?(other.node)
16
+ node == other.node
16
17
  end
17
18
 
18
19
  alias == eql?
@@ -4,7 +4,7 @@ module RuboCop
4
4
  module RSpec
5
5
  # Wrapper for RSpec hook
6
6
  class Hook < Concept
7
- STANDARDIZED_SCOPES = %i(each context suite).freeze
7
+ STANDARDIZED_SCOPES = %i[each context suite].freeze
8
8
  private_constant(:STANDARDIZED_SCOPES)
9
9
 
10
10
  def name
@@ -44,49 +44,49 @@ module RuboCop
44
44
  end
45
45
 
46
46
  module Matchers
47
- MESSAGE_CHAIN = SelectorSet.new(%i(receive_message_chain stub_chain))
47
+ MESSAGE_CHAIN = SelectorSet.new(%i[receive_message_chain stub_chain])
48
48
  end
49
49
 
50
50
  module ExampleGroups
51
- GROUPS = SelectorSet.new(%i(describe context feature example_group))
52
- SKIPPED = SelectorSet.new(%i(xdescribe xcontext xfeature))
53
- FOCUSED = SelectorSet.new(%i(fdescribe fcontext ffeature))
51
+ GROUPS = SelectorSet.new(%i[describe context feature example_group])
52
+ SKIPPED = SelectorSet.new(%i[xdescribe xcontext xfeature])
53
+ FOCUSED = SelectorSet.new(%i[fdescribe fcontext ffeature])
54
54
 
55
55
  ALL = GROUPS + SKIPPED + FOCUSED
56
56
  end
57
57
 
58
58
  module SharedGroups
59
- EXAMPLES = SelectorSet.new(%i(shared_examples shared_examples_for))
60
- CONTEXT = SelectorSet.new(%i(shared_context))
59
+ EXAMPLES = SelectorSet.new(%i[shared_examples shared_examples_for])
60
+ CONTEXT = SelectorSet.new(%i[shared_context])
61
61
 
62
62
  ALL = EXAMPLES + CONTEXT
63
63
  end
64
64
 
65
65
  module Includes
66
66
  EXAMPLES = SelectorSet.new(
67
- %i(
67
+ %i[
68
68
  it_behaves_like
69
69
  it_should_behave_like
70
70
  include_examples
71
- )
71
+ ]
72
72
  )
73
- CONTEXT = SelectorSet.new(%i(include_context))
73
+ CONTEXT = SelectorSet.new(%i[include_context])
74
74
 
75
75
  ALL = EXAMPLES + CONTEXT
76
76
  end
77
77
 
78
78
  module Examples
79
- EXAMPLES = SelectorSet.new(%i(it specify example scenario its))
80
- FOCUSED = SelectorSet.new(%i(fit fspecify fexample fscenario focus))
81
- SKIPPED = SelectorSet.new(%i(xit xspecify xexample xscenario skip))
82
- PENDING = SelectorSet.new(%i(pending))
79
+ EXAMPLES = SelectorSet.new(%i[it specify example scenario its])
80
+ FOCUSED = SelectorSet.new(%i[fit fspecify fexample fscenario focus])
81
+ SKIPPED = SelectorSet.new(%i[xit xspecify xexample xscenario skip])
82
+ PENDING = SelectorSet.new(%i[pending])
83
83
 
84
84
  ALL = EXAMPLES + FOCUSED + SKIPPED + PENDING
85
85
  end
86
86
 
87
87
  module Hooks
88
88
  ALL = SelectorSet.new(
89
- %i(
89
+ %i[
90
90
  prepend_before
91
91
  before
92
92
  append_before
@@ -94,16 +94,16 @@ module RuboCop
94
94
  prepend_after
95
95
  after
96
96
  append_after
97
- )
97
+ ]
98
98
  )
99
99
  end
100
100
 
101
101
  module Helpers
102
- ALL = SelectorSet.new(%i(let let!))
102
+ ALL = SelectorSet.new(%i[let let!])
103
103
  end
104
104
 
105
105
  module Subject
106
- ALL = SelectorSet.new(%i(subject))
106
+ ALL = SelectorSet.new(%i[subject subject!])
107
107
  end
108
108
 
109
109
  ALL =
@@ -4,7 +4,7 @@ module RuboCop
4
4
  module RSpec
5
5
  # Version information for the RSpec RuboCop plugin.
6
6
  module Version
7
- STRING = '1.15.0'.freeze
7
+ STRING = '1.15.1'.freeze
8
8
  end
9
9
  end
10
10
  end
@@ -4,6 +4,11 @@ module RuboCop
4
4
  module RSpec
5
5
  # RSpec example wording rewriter
6
6
  class Wording
7
+ SHOULDNT_PREFIX = /\Ashould(?:n't| not)\b/i
8
+ SHOULDNT_BE_PREFIX = /#{SHOULDNT_PREFIX} be\b/i
9
+ ES_SUFFIX_PATTERN = /(?:o|s|x|ch|sh|z)\z/i
10
+ IES_SUFFIX_PATTERN = /[^aeou]y\z/i
11
+
7
12
  def initialize(text, ignore:, replace:)
8
13
  @text = text
9
14
  @ignores = ignore
@@ -11,37 +16,66 @@ module RuboCop
11
16
  end
12
17
 
13
18
  def rewrite
14
- text.split.tap do |words|
15
- first_word = words.shift
16
- words.unshift('not') if first_word.eql?("shouldn't")
17
-
18
- words.each_with_index do |value, key|
19
- next if ignores.include?(value)
20
- words[key] = simple_present(words.fetch(key))
21
- break
22
- end
23
- end.join(' ')
19
+ case text
20
+ when SHOULDNT_BE_PREFIX
21
+ replace_prefix(SHOULDNT_BE_PREFIX, 'is not')
22
+ when SHOULDNT_PREFIX
23
+ replace_prefix(SHOULDNT_PREFIX, 'does not')
24
+ else
25
+ remove_should_and_pluralize
26
+ end
24
27
  end
25
28
 
26
29
  private
27
30
 
28
31
  attr_reader :text, :ignores, :replacements
29
32
 
30
- def simple_present(word)
31
- return replacements.fetch(word) if replacements.key?(word)
33
+ def replace_prefix(pattern, replacement)
34
+ text.sub(pattern) do |shouldnt|
35
+ uppercase?(shouldnt) ? replacement.upcase : replacement
36
+ end
37
+ end
38
+
39
+ def uppercase?(word)
40
+ word.upcase.eql?(word)
41
+ end
42
+
43
+ def remove_should_and_pluralize
44
+ _should, *words = text.split
45
+
46
+ words.each_with_index do |word, index|
47
+ next if ignored_word?(word)
32
48
 
33
- # ends with o s x ch sh or ss
34
- if %w(o s x ch sh).any?(&word.public_method(:end_with?))
35
- return "#{word}es"
49
+ words[index] = substitute(word)
50
+
51
+ break
36
52
  end
37
53
 
38
- # ends with y
39
- if word.end_with?('y') && !%w(a u o e).include?(word[-2])
40
- return "#{word[0..-2]}ies"
54
+ words.join(' ')
55
+ end
56
+
57
+ def ignored_word?(word)
58
+ ignores.any? { |ignore| ignore.casecmp(word).zero? }
59
+ end
60
+
61
+ def substitute(word)
62
+ # NOTE: Custom replacements are case sensitive.
63
+ return replacements.fetch(word) if replacements.key?(word)
64
+
65
+ case word
66
+ when ES_SUFFIX_PATTERN then append_suffix(word, 'es')
67
+ when IES_SUFFIX_PATTERN then append_suffix(word[0..-2], 'ies')
68
+ else append_suffix(word, 's')
41
69
  end
70
+ end
42
71
 
43
- "#{word}s"
72
+ def append_suffix(word, suffix)
73
+ suffix = suffix.upcase if uppercase?(word)
74
+
75
+ "#{word}#{suffix}"
44
76
  end
77
+
78
+ private_constant(*constants(false))
45
79
  end
46
80
  end
47
81
  end
@@ -71,7 +71,7 @@ RSpec.describe ExpectViolation::Expectation do
71
71
 
72
72
  it 'has an assertion with correct violation message' do
73
73
  expect(assertions.map(&:message)).to eql(
74
- %w(Charlie Charlie Alpha Bronco Delta)
74
+ %w[Charlie Charlie Alpha Bronco Delta]
75
75
  )
76
76
  end
77
77
 
@@ -14,11 +14,11 @@ RSpec.describe 'config/default.yml' do
14
14
  "RSpec/#{cop_name}"
15
15
  end
16
16
 
17
- cop_names - %w(RSpec/Cop)
17
+ cop_names - %w[RSpec/Cop]
18
18
  end
19
19
 
20
20
  let(:config_keys) do
21
- cop_names + %w(AllCops)
21
+ cop_names + %w[AllCops]
22
22
  end
23
23
 
24
24
  def cop_configuration(config_key)
@@ -12,7 +12,7 @@ RSpec.describe RuboCop::Cop::RSpec::Cop do
12
12
  }
13
13
  },
14
14
  'RSpec/FakeCop' => {
15
- 'Exclude' => %w(bar_spec.rb)
15
+ 'Exclude' => %w[bar_spec.rb]
16
16
  }
17
17
  }
18
18
 
@@ -62,7 +62,7 @@ RSpec.describe RuboCop::Cop::RSpec::DescribedClass, :config do
62
62
  end
63
63
 
64
64
  context 'when SkipBlocks is not set' do
65
- let(:cop_config) { Hash.new }
65
+ let(:cop_config) { {} }
66
66
 
67
67
  include_examples 'SkipBlocks disabled'
68
68
  end
@@ -63,7 +63,7 @@ RSpec.describe RuboCop::Cop::RSpec::EmptyExampleGroup, :config do
63
63
 
64
64
  context 'when a custom include method is specified' do
65
65
  let(:cop_config) do
66
- { 'CustomIncludeMethods' => %w(it_has_special_behavior) }
66
+ { 'CustomIncludeMethods' => %w[it_has_special_behavior] }
67
67
  end
68
68
 
69
69
  it 'does not flag an otherwise empty example group' do
@@ -4,8 +4,8 @@ RSpec.describe RuboCop::Cop::RSpec::ExampleWording, :config do
4
4
  context 'with configuration' do
5
5
  let(:cop_config) do
6
6
  {
7
- 'CustomTransform' => { 'have' => 'has', 'not' => 'does not' },
8
- 'IgnoredWords' => %w(only really)
7
+ 'CustomTransform' => { 'have' => 'has' },
8
+ 'IgnoredWords' => %w[only really]
9
9
  }
10
10
  end
11
11
 
@@ -37,6 +37,22 @@ RSpec.describe RuboCop::Cop::RSpec::ExampleWording, :config do
37
37
  RUBY
38
38
  end
39
39
 
40
+ it 'flags a lone should' do
41
+ expect_violation(<<-RUBY)
42
+ it 'should' do
43
+ ^^^^^^ Do not use should when describing your tests.
44
+ end
45
+ RUBY
46
+ end
47
+
48
+ it 'flags a lone should not' do
49
+ expect_violation(<<-RUBY)
50
+ it 'should not' do
51
+ ^^^^^^^^^^ Do not use should when describing your tests.
52
+ end
53
+ RUBY
54
+ end
55
+
40
56
  it 'finds leading its' do
41
57
  expect_violation(<<-RUBY)
42
58
  it "it does something" do
@@ -59,13 +75,36 @@ RSpec.describe RuboCop::Cop::RSpec::ExampleWording, :config do
59
75
  RUBY
60
76
  end
61
77
 
78
+ it 'skips descriptions starting with words that begin with `should`' do
79
+ expect_no_violations(<<-RUBY)
80
+ it 'shoulders the burden' do
81
+ end
82
+ RUBY
83
+ end
84
+
62
85
  include_examples 'autocorrect',
63
86
  'it "should only have trait" do end',
64
87
  'it "only has trait" do end'
65
88
 
89
+ include_examples 'autocorrect',
90
+ 'it "SHOULDN\'T only have trait" do end',
91
+ 'it "DOES NOT only have trait" do end'
92
+
66
93
  include_examples 'autocorrect',
67
94
  'it "it does something" do end',
68
95
  'it "does something" do end'
96
+
97
+ include_examples 'autocorrect',
98
+ 'it "It does something" do end',
99
+ 'it "does something" do end'
100
+
101
+ include_examples 'autocorrect',
102
+ 'it "should" do end',
103
+ 'it "" do end'
104
+
105
+ include_examples 'autocorrect',
106
+ 'it "should not" do end',
107
+ 'it "does not" do end'
69
108
  end
70
109
 
71
110
  context 'when configuration is empty' do
@@ -59,6 +59,14 @@ RSpec.describe RuboCop::Cop::RSpec::IteratedExpectation do
59
59
  RUBY
60
60
  end
61
61
 
62
+ it 'ignores assignments in the iteration' do
63
+ expect_no_violations(<<-RUBY)
64
+ it 'validates users' do
65
+ [user1, user2, user3].each { |user| array = array.concat(user) }
66
+ end
67
+ RUBY
68
+ end
69
+
62
70
  it 'ignores `each` when there is a negative expectation' do
63
71
  expect_no_violations(<<-RUBY)
64
72
  it 'validates users' do
@@ -4,7 +4,7 @@ RSpec.describe RuboCop::Cop::RSpec::MultipleExpectations, :config do
4
4
  subject(:cop) { described_class.new(config) }
5
5
 
6
6
  context 'without configuration' do
7
- let(:cop_config) { Hash.new }
7
+ let(:cop_config) { {} }
8
8
 
9
9
  it 'flags multiple expectations' do
10
10
  expect_violation(<<-RUBY)
@@ -47,6 +47,45 @@ RSpec.describe RuboCop::Cop::RSpec::SingleArgumentMessageChain do
47
47
  end
48
48
  RUBY
49
49
  end
50
+
51
+ context 'with single-key hash argument' do
52
+ it 'reports an offence' do
53
+ expect_violation(<<-RUBY)
54
+ before do
55
+ allow(foo).to receive_message_chain(bar: 42)
56
+ ^^^^^^^^^^^^^^^^^^^^^ Use `receive` instead of calling `receive_message_chain` with a single argument.
57
+ end
58
+ RUBY
59
+ end
60
+
61
+ include_examples(
62
+ 'autocorrect',
63
+ 'before { allow(foo).to receive_message_chain(bar: 42) }',
64
+ 'before { allow(foo).to receive(:bar).and_return(42) }'
65
+ )
66
+
67
+ include_examples(
68
+ 'autocorrect',
69
+ 'before { allow(foo).to receive_message_chain("bar" => 42) }',
70
+ 'before { allow(foo).to receive("bar").and_return(42) }'
71
+ )
72
+
73
+ include_examples(
74
+ 'autocorrect',
75
+ 'before { allow(foo).to receive_message_chain(:"#{foo}" => 42) }',
76
+ 'before { allow(foo).to receive(:"#{foo}").and_return(42) }'
77
+ )
78
+ end
79
+
80
+ context 'with multiple keys hash argument' do
81
+ it "doesn't report an offence" do
82
+ expect_no_violations(<<-RUBY)
83
+ before do
84
+ allow(foo).to receive_message_chain(bar: 42, baz: 42)
85
+ end
86
+ RUBY
87
+ end
88
+ end
50
89
  end
51
90
 
52
91
  describe 'stub_chain' do
@@ -28,7 +28,7 @@ RSpec.describe RuboCop::RSpec::Example do
28
28
 
29
29
  it 'extracts implementation' do
30
30
  expect(example('it("foo") { bar; baz }').implementation)
31
- .to eql(s(:begin, s(:send, nil, :bar), s(:send, nil, :baz)))
31
+ .to eq(s(:begin, s(:send, nil, :bar), s(:send, nil, :baz)))
32
32
  end
33
33
 
34
34
  it 'returns node' do
@@ -1,14 +1,14 @@
1
1
  RSpec.describe RuboCop::RSpec::Language::SelectorSet do
2
- subject(:selector_set) { described_class.new(%i(foo bar)) }
2
+ subject(:selector_set) { described_class.new(%i[foo bar]) }
3
3
 
4
4
  it 'composes sets' do
5
- combined = selector_set + described_class.new(%i(baz))
5
+ combined = selector_set + described_class.new(%i[baz])
6
6
 
7
- expect(combined).to eq(described_class.new(%i(foo bar baz)))
7
+ expect(combined).to eq(described_class.new(%i[foo bar baz]))
8
8
  end
9
9
 
10
10
  it 'compares by value' do
11
- expect(selector_set).not_to eq(described_class.new(%i(foo bar baz)))
11
+ expect(selector_set).not_to eq(described_class.new(%i[foo bar baz]))
12
12
  end
13
13
 
14
14
  context '#include?' do
@@ -1,11 +1,6 @@
1
1
  RSpec.describe RuboCop::RSpec::Wording do
2
- let(:replacements) do
3
- { 'have' => 'has', 'not' => 'does not' }
4
- end
5
-
6
- let(:ignores) do
7
- %w(only really)
8
- end
2
+ let(:replacements) { { 'have' => 'has' } }
3
+ let(:ignores) { %w[only really] }
9
4
 
10
5
  expected_rewrites =
11
6
  {
@@ -26,7 +21,18 @@ RSpec.describe RuboCop::RSpec::Wording do
26
21
  'should search the internet' => 'searches the internet',
27
22
  'should wish me luck' => 'wishes me luck',
28
23
  'should really only return one item' => 'really only returns one item',
29
- "shouldn't return something" => 'does not return something'
24
+ "shouldn't return something" => 'does not return something',
25
+ 'SHOULD RETAIN UPPERCASE' => 'RETAINS UPPERCASE',
26
+ "shouldn't be true" => 'is not true',
27
+ "SHOULDN'T BE true" => 'IS NOT true',
28
+ "SHOULDN'T NOT RETAIN UPPERCASE" => 'DOES NOT NOT RETAIN UPPERCASE',
29
+ 'should WORRY' => 'WORRIES',
30
+ 'should WISH me luck' => 'WISHES me luck',
31
+ '' => '',
32
+ 'should' => '',
33
+ "shouldn't" => 'does not',
34
+ 'should not' => 'does not',
35
+ 'should fizz' => 'fizzes'
30
36
  }
31
37
 
32
38
  expected_rewrites.each do |old, new|
@@ -39,13 +39,14 @@ module ExpectViolation
39
39
  end
40
40
 
41
41
  class Expectation
42
+ include Adamantium
43
+ include Concord.new(:string)
44
+
42
45
  VIOLATION_LINE_PATTERN = /\A *\^/
43
46
 
44
47
  VIOLATION = :violation
45
48
  SOURCE = :line
46
49
 
47
- include Adamantium, Concord.new(:string)
48
-
49
50
  def source
50
51
  source_map.to_s
51
52
  end
@@ -117,6 +118,10 @@ module ExpectViolation
117
118
  end
118
119
 
119
120
  class Assertion
121
+ include Adamantium
122
+ include Anima.new(:message, :column_range, :line_number)
123
+ include Comparable
124
+
120
125
  def self.parse(text:, line_number:)
121
126
  parser = Parser.new(text)
122
127
 
@@ -127,10 +132,6 @@ module ExpectViolation
127
132
  )
128
133
  end
129
134
 
130
- include Anima.new(:message, :column_range, :line_number),
131
- Adamantium,
132
- Comparable
133
-
134
135
  def <=>(other)
135
136
  to_a <=> other.to_a
136
137
  end
@@ -142,9 +143,10 @@ module ExpectViolation
142
143
  end
143
144
 
144
145
  class Parser
145
- COLUMN_PATTERN = /^ *(?<carets>\^\^*) (?<message>.+)$/
146
+ include Adamantium
147
+ include Concord.new(:text)
146
148
 
147
- include Concord.new(:text), Adamantium
149
+ COLUMN_PATTERN = /^ *(?<carets>\^\^*) (?<message>.+)$/
148
150
 
149
151
  def column_range
150
152
  Range.new(*match.offset(:carets), true)
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rubocop-rspec
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.15.0
4
+ version: 1.15.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - John Backus
@@ -10,7 +10,7 @@ authors:
10
10
  autorequire:
11
11
  bindir: bin
12
12
  cert_chain: []
13
- date: 2017-03-25 00:00:00.000000000 Z
13
+ date: 2017-05-01 00:00:00.000000000 Z
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
16
16
  name: rubocop
@@ -281,7 +281,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
281
281
  version: '0'
282
282
  requirements: []
283
283
  rubyforge_project:
284
- rubygems_version: 2.6.8
284
+ rubygems_version: 2.6.11
285
285
  signing_key:
286
286
  specification_version: 4
287
287
  summary: Code style checking for RSpec files