rubocop-rspec 1.15.0 → 1.15.1

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.
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