rubocop-rspec 1.35.0 → 1.36.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (116) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +12 -0
  3. data/config/default.yml +11 -0
  4. data/lib/rubocop/cop/rspec/capybara/current_path_expectation.rb +16 -0
  5. data/lib/rubocop/cop/rspec/context_method.rb +53 -0
  6. data/lib/rubocop/cop/rspec/describe_class.rb +7 -10
  7. data/lib/rubocop/cop/rspec/described_class.rb +29 -1
  8. data/lib/rubocop/cop/rspec/empty_line_after_example.rb +87 -0
  9. data/lib/rubocop/cop/rspec/example_wording.rb +28 -12
  10. data/lib/rubocop/cop/rspec/expect_change.rb +8 -8
  11. data/lib/rubocop/cop/rspec/factory_bot/attribute_defined_statically.rb +2 -9
  12. data/lib/rubocop/cop/rspec/focus.rb +5 -10
  13. data/lib/rubocop/cop/rspec/instance_variable.rb +2 -1
  14. data/lib/rubocop/cop/rspec/multiple_expectations.rb +13 -21
  15. data/lib/rubocop/cop/rspec/pending.rb +19 -25
  16. data/lib/rubocop/cop/rspec_cops.rb +2 -0
  17. data/lib/rubocop/rspec/version.rb +1 -1
  18. metadata +7 -198
  19. data/Gemfile +0 -11
  20. data/Rakefile +0 -87
  21. data/rubocop-rspec.gemspec +0 -49
  22. data/spec/project/changelog_spec.rb +0 -76
  23. data/spec/project/default_config_spec.rb +0 -76
  24. data/spec/project/project_requires_spec.rb +0 -20
  25. data/spec/rubocop/cop/rspec/align_left_let_brace_spec.rb +0 -51
  26. data/spec/rubocop/cop/rspec/align_right_let_brace_spec.rb +0 -51
  27. data/spec/rubocop/cop/rspec/any_instance_spec.rb +0 -32
  28. data/spec/rubocop/cop/rspec/around_block_spec.rb +0 -121
  29. data/spec/rubocop/cop/rspec/be_eql_spec.rb +0 -81
  30. data/spec/rubocop/cop/rspec/be_spec.rb +0 -35
  31. data/spec/rubocop/cop/rspec/before_after_all_spec.rb +0 -52
  32. data/spec/rubocop/cop/rspec/capybara/current_path_expectation_spec.rb +0 -65
  33. data/spec/rubocop/cop/rspec/capybara/feature_methods_spec.rb +0 -130
  34. data/spec/rubocop/cop/rspec/context_wording_spec.rb +0 -94
  35. data/spec/rubocop/cop/rspec/cop_spec.rb +0 -95
  36. data/spec/rubocop/cop/rspec/describe_class_spec.rb +0 -168
  37. data/spec/rubocop/cop/rspec/describe_method_spec.rb +0 -34
  38. data/spec/rubocop/cop/rspec/describe_symbol_spec.rb +0 -44
  39. data/spec/rubocop/cop/rspec/described_class_spec.rb +0 -352
  40. data/spec/rubocop/cop/rspec/dialect_spec.rb +0 -78
  41. data/spec/rubocop/cop/rspec/empty_example_group_spec.rb +0 -93
  42. data/spec/rubocop/cop/rspec/empty_line_after_example_group_spec.rb +0 -121
  43. data/spec/rubocop/cop/rspec/empty_line_after_final_let_spec.rb +0 -239
  44. data/spec/rubocop/cop/rspec/empty_line_after_hook_spec.rb +0 -133
  45. data/spec/rubocop/cop/rspec/empty_line_after_subject_spec.rb +0 -94
  46. data/spec/rubocop/cop/rspec/example_length_spec.rb +0 -78
  47. data/spec/rubocop/cop/rspec/example_without_description_spec.rb +0 -92
  48. data/spec/rubocop/cop/rspec/example_wording_spec.rb +0 -173
  49. data/spec/rubocop/cop/rspec/expect_actual_spec.rb +0 -150
  50. data/spec/rubocop/cop/rspec/expect_change_spec.rb +0 -86
  51. data/spec/rubocop/cop/rspec/expect_in_hook_spec.rb +0 -79
  52. data/spec/rubocop/cop/rspec/expect_output_spec.rb +0 -62
  53. data/spec/rubocop/cop/rspec/factory_bot/attribute_defined_statically_spec.rb +0 -208
  54. data/spec/rubocop/cop/rspec/factory_bot/create_list_spec.rb +0 -171
  55. data/spec/rubocop/cop/rspec/file_path_spec.rb +0 -200
  56. data/spec/rubocop/cop/rspec/focus_spec.rb +0 -139
  57. data/spec/rubocop/cop/rspec/hook_argument_spec.rb +0 -173
  58. data/spec/rubocop/cop/rspec/hooks_before_examples_spec.rb +0 -150
  59. data/spec/rubocop/cop/rspec/implicit_block_expectation_spec.rb +0 -135
  60. data/spec/rubocop/cop/rspec/implicit_expect_spec.rb +0 -102
  61. data/spec/rubocop/cop/rspec/implicit_subject_spec.rb +0 -188
  62. data/spec/rubocop/cop/rspec/instance_spy_spec.rb +0 -61
  63. data/spec/rubocop/cop/rspec/instance_variable_spec.rb +0 -95
  64. data/spec/rubocop/cop/rspec/invalid_predicate_matcher_spec.rb +0 -39
  65. data/spec/rubocop/cop/rspec/it_behaves_like_spec.rb +0 -47
  66. data/spec/rubocop/cop/rspec/iterated_expectation_spec.rb +0 -82
  67. data/spec/rubocop/cop/rspec/leading_subject_spec.rb +0 -119
  68. data/spec/rubocop/cop/rspec/leaky_constant_declaration_spec.rb +0 -91
  69. data/spec/rubocop/cop/rspec/let_before_examples_spec.rb +0 -137
  70. data/spec/rubocop/cop/rspec/let_setup_spec.rb +0 -66
  71. data/spec/rubocop/cop/rspec/message_chain_spec.rb +0 -23
  72. data/spec/rubocop/cop/rspec/message_expectation_spec.rb +0 -45
  73. data/spec/rubocop/cop/rspec/message_spies_spec.rb +0 -151
  74. data/spec/rubocop/cop/rspec/missing_example_group_argument_spec.rb +0 -57
  75. data/spec/rubocop/cop/rspec/multiple_describes_spec.rb +0 -30
  76. data/spec/rubocop/cop/rspec/multiple_expectations_spec.rb +0 -261
  77. data/spec/rubocop/cop/rspec/multiple_subjects_spec.rb +0 -83
  78. data/spec/rubocop/cop/rspec/named_subject_spec.rb +0 -123
  79. data/spec/rubocop/cop/rspec/nested_groups_spec.rb +0 -81
  80. data/spec/rubocop/cop/rspec/not_to_not_spec.rb +0 -77
  81. data/spec/rubocop/cop/rspec/overwriting_setup_spec.rb +0 -91
  82. data/spec/rubocop/cop/rspec/pending_spec.rb +0 -186
  83. data/spec/rubocop/cop/rspec/predicate_matcher_spec.rb +0 -354
  84. data/spec/rubocop/cop/rspec/rails/http_status_spec.rb +0 -90
  85. data/spec/rubocop/cop/rspec/receive_counts_spec.rb +0 -138
  86. data/spec/rubocop/cop/rspec/receive_never_spec.rb +0 -57
  87. data/spec/rubocop/cop/rspec/repeated_description_spec.rb +0 -76
  88. data/spec/rubocop/cop/rspec/repeated_example_spec.rb +0 -74
  89. data/spec/rubocop/cop/rspec/return_from_stub_spec.rb +0 -289
  90. data/spec/rubocop/cop/rspec/scattered_let_spec.rb +0 -28
  91. data/spec/rubocop/cop/rspec/scattered_setup_spec.rb +0 -98
  92. data/spec/rubocop/cop/rspec/shared_context_spec.rb +0 -137
  93. data/spec/rubocop/cop/rspec/shared_examples_spec.rb +0 -75
  94. data/spec/rubocop/cop/rspec/single_argument_message_chain_spec.rb +0 -178
  95. data/spec/rubocop/cop/rspec/subject_stub_spec.rb +0 -293
  96. data/spec/rubocop/cop/rspec/unspecified_exception_spec.rb +0 -177
  97. data/spec/rubocop/cop/rspec/verified_doubles_spec.rb +0 -86
  98. data/spec/rubocop/cop/rspec/void_expect_spec.rb +0 -49
  99. data/spec/rubocop/cop/rspec/yield_spec.rb +0 -81
  100. data/spec/rubocop/rspec/config_formatter_spec.rb +0 -52
  101. data/spec/rubocop/rspec/description_extractor_spec.rb +0 -63
  102. data/spec/rubocop/rspec/example_group_spec.rb +0 -44
  103. data/spec/rubocop/rspec/example_spec.rb +0 -62
  104. data/spec/rubocop/rspec/hook_spec.rb +0 -53
  105. data/spec/rubocop/rspec/language/selector_set_spec.rb +0 -53
  106. data/spec/rubocop/rspec/util/one_spec.rb +0 -23
  107. data/spec/rubocop/rspec/wording_spec.rb +0 -52
  108. data/spec/shared/autocorrect_behavior.rb +0 -9
  109. data/spec/shared/detects_style_behavior.rb +0 -9
  110. data/spec/shared/smoke_test_examples.rb +0 -27
  111. data/spec/smoke_tests/empty_spec.rb +0 -0
  112. data/spec/smoke_tests/factory_bot_spec.rb +0 -11
  113. data/spec/smoke_tests/no_tests_spec.rb +0 -4
  114. data/spec/smoke_tests/weird_rspec_spec.rb +0 -233
  115. data/spec/spec_helper.rb +0 -42
  116. data/spec/support/expect_offense.rb +0 -19
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 47216a8696392108804dfd285875acfdec9857df832fb6270120b29161bcd5d6
4
- data.tar.gz: 742b3c4e6836a6e7c8aa4d2ca02abd73f09870165f2e10a4eb41ea9d1ef6c859
3
+ metadata.gz: 5941ed5c040054adc2993a3da2b76e591a9096767e486727191702956bc04430
4
+ data.tar.gz: 34d3b8460cd36dcf5af8f1cdf918bbd43e43bf5e4c7a5a0fba829eb9c1980cbf
5
5
  SHA512:
6
- metadata.gz: 488afcabe181b6658b73014730194c4a1bab399e096d2fdb230f2d16bee41afa3d71d285fd764a7a6b766117bd68d6702c54cab33503a18ed3f6501428569ff0
7
- data.tar.gz: a8030e59e2f88880b09621a868f18e8af0b44bca6927822f7e07cfcae9668a3e11d91aab7e4450dffa05d7409043a4e2db9b87373ea9b1316d00e924e52668d1
6
+ metadata.gz: d868ef13a01bdf13ba05eb54a0b39354017184001d44975ef3e1bbcb0d429f2ccac6675429308886cd3246e3ff83bf8f7e5e34b1b8613b9fdbfc879493f459a9
7
+ data.tar.gz: 05fae5ae2505feabbfdfa8203c57a0bbd6f9b398c33d80d9c848e2ed6fd9fdb78019c699b9f428b26533d3799c78051a5a5ddd5176d07224938f29217ca77e61
@@ -2,6 +2,17 @@
2
2
 
3
3
  ## Master (Unreleased)
4
4
 
5
+ ## 1.36.0 (2019-09-27)
6
+
7
+ * Fix `RSpec/DescribedClass`'s error when `described_class` is used as part of a constant. ([@pirj][])
8
+ * Fix `RSpec/ExampleWording` autocorrect of multi-line docstrings. ([@pirj][])
9
+ * Add `RSpec/ContextMethod` cop, to detect method names in `context`. ([@geniou][])
10
+ * Update RuboCop dependency to 0.68.1 with support for children matching node pattern syntax. ([@pirj][])
11
+ * Add `RSpec/EmptyLineAfterExample` cop to check that there is an empty line after example blocks. ([@pirj][])
12
+ * Fix `Capybara/CurrentPathExpectation` auto-corrector, to include option `ignore_query: true`. ([@onumis][])
13
+ * Fix `RSpec/Focus` detecting mixed array/hash metadata. ([@dgollahon][])
14
+ * Fix `RSpec/Focus` to also detect `pending` examples. ([@dgollahon][])
15
+
5
16
  ## 1.35.0 (2019-08-02)
6
17
 
7
18
  * Add `RSpec/ImplicitBlockExpectation` cop. ([@pirj][])
@@ -440,3 +451,4 @@ Compatibility release so users can upgrade RuboCop to 0.51.0. No new features.
440
451
  [@schmijos]: https://github.com/schmijos
441
452
  [@foton]: https://github.com/foton
442
453
  [@nc-holodakg]: https://github.com/nc-holodakg
454
+ [@onumis]: https://github.com/onumis
@@ -49,6 +49,11 @@ RSpec/BeforeAfterAll:
49
49
  - spec/support/**/*.rb
50
50
  StyleGuide: http://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/BeforeAfterAll
51
51
 
52
+ RSpec/ContextMethod:
53
+ Description: "`context` should not be used for specifying methods."
54
+ Enabled: true
55
+ StyleGuide: http://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/ContextMethod
56
+
52
57
  RSpec/ContextWording:
53
58
  Description: Checks that `context` docstring starts with an allowed prefix.
54
59
  Enabled: true
@@ -95,6 +100,12 @@ RSpec/EmptyExampleGroup:
95
100
  CustomIncludeMethods: []
96
101
  StyleGuide: http://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/EmptyExampleGroup
97
102
 
103
+ RSpec/EmptyLineAfterExample:
104
+ Description: Checks if there is an empty line after example blocks.
105
+ Enabled: true
106
+ AllowConsecutiveOneLiners: true
107
+ StyleGuide: http://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/EmptyLineAfterExample
108
+
98
109
  RSpec/EmptyLineAfterExampleGroup:
99
110
  Description: Checks if there is an empty line after example group blocks.
100
111
  Enabled: true
@@ -78,6 +78,7 @@ module RuboCop
78
78
  'have_no_current_path'
79
79
  end
80
80
  corrector.replace(matcher_node.loc.selector, matcher_method)
81
+ add_ignore_query_options(corrector, node)
81
82
  end
82
83
 
83
84
  def convert_regexp_str_to_literal(corrector, matcher_node, regexp_str)
@@ -85,6 +86,21 @@ module RuboCop
85
86
  regexp_expr = Regexp.new(regexp_str).inspect
86
87
  corrector.replace(str_node.loc.expression, regexp_expr)
87
88
  end
89
+
90
+ # `have_current_path` with no options will include the querystring
91
+ # while `page.current_path` does not.
92
+ # This ensures the option `ignore_query: true` is added
93
+ # except when the expectation is a regexp or string
94
+ def add_ignore_query_options(corrector, node)
95
+ expectation_node = node.parent.last_argument
96
+ expectation_last_child = expectation_node.children.last
97
+ return if %i[regexp str].include?(expectation_last_child.type)
98
+
99
+ corrector.insert_after(
100
+ expectation_last_child.loc.expression,
101
+ ', ignore_query: true'
102
+ )
103
+ end
88
104
  end
89
105
  end
90
106
  end
@@ -0,0 +1,53 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RuboCop
4
+ module Cop
5
+ module RSpec
6
+ # `context` should not be used for specifying methods.
7
+ #
8
+ # @example
9
+ # # bad
10
+ # context '#foo_bar' do
11
+ # # ...
12
+ # end
13
+ #
14
+ # context '.foo_bar' do
15
+ # # ...
16
+ # end
17
+ #
18
+ # # good
19
+ # describe '#foo_bar' do
20
+ # # ...
21
+ # end
22
+ #
23
+ # describe '.foo_bar' do
24
+ # # ...
25
+ # end
26
+ class ContextMethod < Cop
27
+ MSG = 'Use `describe` for testing methods.'
28
+
29
+ def_node_matcher :context_method, <<-PATTERN
30
+ (block (send #{RSPEC} :context $(str #method_name?) ...) ...)
31
+ PATTERN
32
+
33
+ def on_block(node)
34
+ context_method(node) do |context|
35
+ add_offense(context)
36
+ end
37
+ end
38
+
39
+ def autocorrect(node)
40
+ lambda do |corrector|
41
+ corrector.replace(node.parent.loc.selector, 'describe')
42
+ end
43
+ end
44
+
45
+ private
46
+
47
+ def method_name?(description)
48
+ description.start_with?('.', '#')
49
+ end
50
+ end
51
+ end
52
+ end
53
+ end
@@ -29,17 +29,17 @@ module RuboCop
29
29
  }
30
30
  PATTERN
31
31
 
32
- def_node_matcher :describe_with_metadata, <<-PATTERN
33
- (send #{RSPEC} :describe
34
- !const
35
- ...
36
- (hash $...))
32
+ def_node_matcher :describe_with_rails_metadata?, <<-PATTERN
33
+ (send #{RSPEC} :describe !const ...
34
+ (hash <#rails_metadata? ...>)
35
+ )
37
36
  PATTERN
38
37
 
39
38
  def_node_matcher :rails_metadata?, <<-PATTERN
40
39
  (pair
41
40
  (sym :type)
42
- (sym {:request :feature :system :routing :view}))
41
+ (sym {:request :feature :system :routing :view})
42
+ )
43
43
  PATTERN
44
44
 
45
45
  def_node_matcher :shared_group?, SharedGroups::ALL.block_pattern
@@ -47,10 +47,7 @@ module RuboCop
47
47
  def on_top_level_describe(node, args)
48
48
  return if shared_group?(root_node)
49
49
  return if valid_describe?(node)
50
-
51
- describe_with_metadata(node) do |pairs|
52
- return if pairs.any?(&method(:rails_metadata?))
53
- end
50
+ return if describe_with_rails_metadata?(node)
54
51
 
55
52
  add_offense(args.first)
56
53
  end
@@ -8,7 +8,8 @@ module RuboCop
8
8
  # If the first argument of describe is a class, the class is exposed to
9
9
  # each example via described_class.
10
10
  #
11
- # This cop can be configured using the `EnforcedStyle` option
11
+ # This cop can be configured using the `EnforcedStyle` and `SkipBlocks`
12
+ # options.
12
13
  #
13
14
  # @example `EnforcedStyle: described_class`
14
15
  # # bad
@@ -32,6 +33,27 @@ module RuboCop
32
33
  # subject { MyClass.do_something }
33
34
  # end
34
35
  #
36
+ # There's a known caveat with rspec-rails's `controller` helper that
37
+ # runs its block in a different context, and `described_class` is not
38
+ # available to it. `SkipBlocks` option excludes detection in all
39
+ # non-RSpec related blocks.
40
+ #
41
+ # To narrow down this setting to only a specific directory, it is
42
+ # possible to use an overriding configuration file local to that
43
+ # directory.
44
+ #
45
+ # @example `SkipBlocks: true`
46
+ # # spec/controllers/.rubocop.yml
47
+ # # RSpec/DescribedClass:
48
+ # # SkipBlocks: true
49
+ #
50
+ # # acceptable
51
+ # describe MyConcern do
52
+ # controller(ApplicationController) do
53
+ # include MyConcern
54
+ # end
55
+ # end
56
+ #
35
57
  class DescribedClass < Cop
36
58
  include ConfigurableEnforcedStyle
37
59
 
@@ -51,6 +73,10 @@ module RuboCop
51
73
  (block (send _ :describe $(const ...) ...) (args) $_)
52
74
  PATTERN
53
75
 
76
+ def_node_search :contains_described_class?, <<-PATTERN
77
+ (send nil? :described_class)
78
+ PATTERN
79
+
54
80
  def on_block(node)
55
81
  # In case the explicit style is used, we need to remember what's
56
82
  # being described.
@@ -119,6 +145,8 @@ module RuboCop
119
145
 
120
146
  def offensive_described_class?(node)
121
147
  return unless node.const_type?
148
+ # E.g. `described_class::CONSTANT`
149
+ return if contains_described_class?(node)
122
150
 
123
151
  nearest_described_class, = node.each_ancestor(:block)
124
152
  .map { |ancestor| described_constant(ancestor) }.find(&:itself)
@@ -0,0 +1,87 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RuboCop
4
+ module Cop
5
+ module RSpec
6
+ # Checks if there is an empty line after example blocks.
7
+ #
8
+ # @example
9
+ # # bad
10
+ # RSpec.describe Foo do
11
+ # it 'does this' do
12
+ # end
13
+ # it 'does that' do
14
+ # end
15
+ # end
16
+ #
17
+ # # good
18
+ # RSpec.describe Foo do
19
+ # it 'does this' do
20
+ # end
21
+ #
22
+ # it 'does that' do
23
+ # end
24
+ # end
25
+ #
26
+ # # fair - it's ok to have non-separated one-liners
27
+ # RSpec.describe Foo do
28
+ # it { one }
29
+ # it { two }
30
+ # end
31
+ #
32
+ # @example with AllowConsecutiveOneLiners configuration
33
+ #
34
+ # # rubocop.yml
35
+ # # RSpec/EmptyLineAfterExample:
36
+ # # AllowConsecutiveOneLiners: false
37
+ #
38
+ # # bad
39
+ # RSpec.describe Foo do
40
+ # it { one }
41
+ # it { two }
42
+ # end
43
+ #
44
+ class EmptyLineAfterExample < Cop
45
+ include RuboCop::RSpec::BlankLineSeparation
46
+
47
+ MSG = 'Add an empty line after `%<example>s`.'
48
+
49
+ def on_block(node)
50
+ return unless example?(node)
51
+ return if last_child?(node)
52
+ return if allowed_one_liner?(node)
53
+
54
+ missing_separating_line(node) do |location|
55
+ add_offense(node,
56
+ location: location,
57
+ message: format(MSG, example: node.method_name))
58
+ end
59
+ end
60
+
61
+ def allowed_one_liner?(node)
62
+ consecutive_one_liner?(node) && allow_consecutive_one_liners?
63
+ end
64
+
65
+ def allow_consecutive_one_liners?
66
+ cop_config['AllowConsecutiveOneLiners']
67
+ end
68
+
69
+ def consecutive_one_liner?(node)
70
+ node.line_count == 1 && next_one_line_example?(node)
71
+ end
72
+
73
+ def next_one_line_example?(node)
74
+ next_sibling = next_sibling(node)
75
+ return unless next_sibling
76
+ return unless example?(next_sibling)
77
+
78
+ next_sibling.line_count == 1
79
+ end
80
+
81
+ def next_sibling(node)
82
+ node.parent.children[node.sibling_index + 1]
83
+ end
84
+ end
85
+ end
86
+ end
87
+ end
@@ -53,27 +53,30 @@ module RuboCop
53
53
  end
54
54
  end
55
55
 
56
- def autocorrect(range)
57
- ->(corrector) { corrector.replace(range, replacement_text(range)) }
56
+ def autocorrect(node)
57
+ lambda do |corrector|
58
+ corrector.replace(docstring(node), replacement_text(node))
59
+ end
58
60
  end
59
61
 
60
62
  private
61
63
 
62
64
  def add_wording_offense(node, message)
63
- expr = node.loc.expression
65
+ add_offense(node, location: docstring(node), message: message)
66
+ end
64
67
 
65
- docstring =
66
- Parser::Source::Range.new(
67
- expr.source_buffer,
68
- expr.begin_pos + 1,
69
- expr.end_pos - 1
70
- )
68
+ def docstring(node)
69
+ expr = node.loc.expression
71
70
 
72
- add_offense(docstring, location: docstring, message: message)
71
+ Parser::Source::Range.new(
72
+ expr.source_buffer,
73
+ expr.begin_pos + 1,
74
+ expr.end_pos - 1
75
+ )
73
76
  end
74
77
 
75
- def replacement_text(range)
76
- text = range.source
78
+ def replacement_text(node)
79
+ text = text(node)
77
80
 
78
81
  if text =~ SHOULD_PREFIX
79
82
  RuboCop::RSpec::Wording.new(
@@ -86,6 +89,19 @@ module RuboCop
86
89
  end
87
90
  end
88
91
 
92
+ # Recursive processing is required to process nested dstr nodes
93
+ # that is the case for \-separated multiline strings with interpolation.
94
+ def text(node)
95
+ case node.type
96
+ when :dstr
97
+ node.node_parts.map { |child_node| text(child_node) }.join
98
+ when :str
99
+ node.value
100
+ when :begin
101
+ node.source
102
+ end
103
+ end
104
+
89
105
  def custom_transform
90
106
  cop_config.fetch('CustomTransform', {})
91
107
  end
@@ -12,22 +12,22 @@ module RuboCop
12
12
  #
13
13
  # @example `EnforcedStyle: block`
14
14
  # # bad
15
- # expect(run).to change(Foo, :bar)
15
+ # expect { run }.to change(Foo, :bar)
16
16
  #
17
17
  # # good
18
- # expect(run).to change { Foo.bar }
18
+ # expect { run }.to change { Foo.bar }
19
19
  #
20
20
  # @example `EnforcedStyle: method_call`
21
21
  # # bad
22
- # expect(run).to change { Foo.bar }
23
- # expect(run).to change { foo.baz }
22
+ # expect { run }.to change { Foo.bar }
23
+ # expect { run }.to change { foo.baz }
24
24
  #
25
25
  # # good
26
- # expect(run).to change(Foo, :bar)
27
- # expect(run).to change(foo, :baz)
26
+ # expect { run }.to change(Foo, :bar)
27
+ # expect { run }.to change(foo, :baz)
28
28
  # # also good when there are arguments or chained method calls
29
- # expect(run).to change { Foo.bar(:count) }
30
- # expect(run).to change { user.reload.name }
29
+ # expect { run }.to change { Foo.bar(:count) }
30
+ # expect { run }.to change { user.reload.name }
31
31
  #
32
32
  class ExpectChange < Cop
33
33
  include ConfigurableEnforcedStyle
@@ -38,7 +38,7 @@ module RuboCop
38
38
  def on_block(node)
39
39
  factory_attributes(node).to_a.flatten.each do |attribute|
40
40
  next unless offensive_receiver?(attribute.receiver, node)
41
- next if proc?(attribute) || association?(attribute)
41
+ next if proc?(attribute) || association?(attribute.first_argument)
42
42
 
43
43
  add_offense(attribute)
44
44
  end
@@ -72,14 +72,7 @@ module RuboCop
72
72
  value_matcher(attribute).to_a.all?(&:block_pass_type?)
73
73
  end
74
74
 
75
- def association?(attribute)
76
- argument = attribute.first_argument
77
- argument.hash_type? && factory_key?(argument)
78
- end
79
-
80
- def factory_key?(hash_node)
81
- hash_node.keys.any? { |key| key.sym_type? && key.value == :factory }
82
- end
75
+ def_node_matcher :association?, '(hash <(pair (sym :factory) _) ...>)'
83
76
 
84
77
  def autocorrect_replacing_parens(node)
85
78
  left_braces, right_braces = braces(node)
@@ -26,18 +26,16 @@ module RuboCop
26
26
  ExampleGroups::GROUPS +
27
27
  ExampleGroups::SKIPPED +
28
28
  Examples::EXAMPLES +
29
- Examples::SKIPPED
29
+ Examples::SKIPPED +
30
+ Examples::PENDING
30
31
 
31
32
  focused = ExampleGroups::FOCUSED + Examples::FOCUSED
32
33
 
33
34
  FOCUSABLE_SELECTORS = focusable.node_pattern_union
34
35
 
35
- FOCUS_SYMBOL = s(:sym, :focus)
36
- FOCUS_TRUE = s(:pair, FOCUS_SYMBOL, s(:true))
37
-
38
36
  def_node_matcher :metadata, <<-PATTERN
39
- {(send #{RSPEC} #{FOCUSABLE_SELECTORS} ... (hash $...))
40
- (send #{RSPEC} #{FOCUSABLE_SELECTORS} $...)}
37
+ {(send #{RSPEC} #{FOCUSABLE_SELECTORS} <$(sym :focus) ...>)
38
+ (send #{RSPEC} #{FOCUSABLE_SELECTORS} ... (hash <$(pair (sym :focus) true) ...>))}
41
39
  PATTERN
42
40
 
43
41
  def_node_matcher :focused_block?, focused.send_pattern
@@ -53,10 +51,7 @@ module RuboCop
53
51
  def focus_metadata(node, &block)
54
52
  yield(node) if focused_block?(node)
55
53
 
56
- metadata(node) do |matches|
57
- matches.grep(FOCUS_SYMBOL, &block)
58
- matches.grep(FOCUS_TRUE, &block)
59
- end
54
+ metadata(node, &block)
60
55
  end
61
56
  end
62
57
  end