rubocop-rspec 2.16.0 → 2.18.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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +25 -0
- data/README.md +1 -1
- data/config/default.yml +12 -0
- data/config/obsoletion.yml +9 -0
- data/lib/rubocop/cop/rspec/capybara/current_path_expectation.rb +29 -115
- data/lib/rubocop/cop/rspec/capybara/match_style.rb +38 -0
- data/lib/rubocop/cop/rspec/capybara/negation_matcher.rb +23 -96
- data/lib/rubocop/cop/rspec/capybara/specific_actions.rb +19 -75
- data/lib/rubocop/cop/rspec/capybara/specific_finders.rb +14 -83
- data/lib/rubocop/cop/rspec/capybara/specific_matcher.rb +25 -69
- data/lib/rubocop/cop/rspec/capybara/visibility_matcher.rb +26 -63
- data/lib/rubocop/cop/rspec/context_method.rb +5 -1
- data/lib/rubocop/cop/rspec/context_wording.rb +0 -1
- data/lib/rubocop/cop/rspec/mixin/skip_or_pending.rb +1 -1
- data/lib/rubocop/cop/rspec/pending_without_reason.rb +10 -12
- data/lib/rubocop/cop/rspec/predicate_matcher.rb +37 -2
- data/lib/rubocop/cop/rspec/rails/minitest_assertions.rb +60 -0
- data/lib/rubocop/cop/rspec/stubbed_mock.rb +1 -1
- data/lib/rubocop/cop/rspec/subject_stub.rb +0 -1
- data/lib/rubocop/cop/rspec_cops.rb +2 -0
- data/lib/rubocop/rspec/config_formatter.rb +10 -0
- data/lib/rubocop/rspec/version.rb +1 -1
- data/lib/rubocop-rspec.rb +1 -2
- metadata +19 -5
- data/lib/rubocop/cop/rspec/mixin/capybara_help.rb +0 -80
- data/lib/rubocop/cop/rspec/mixin/css_selector.rb +0 -146
@@ -4,75 +4,31 @@ module RuboCop
|
|
4
4
|
module Cop
|
5
5
|
module RSpec
|
6
6
|
module Capybara
|
7
|
-
#
|
8
|
-
#
|
9
|
-
#
|
10
|
-
#
|
11
|
-
# #
|
12
|
-
#
|
13
|
-
# expect(page).to
|
14
|
-
# expect(page).to
|
15
|
-
# expect(page).to
|
16
|
-
# expect(page).to
|
17
|
-
# expect(page).to have_css('
|
18
|
-
# expect(page).to have_css('
|
19
|
-
#
|
20
|
-
# #
|
21
|
-
#
|
22
|
-
# expect(page).to
|
23
|
-
# expect(page).to
|
24
|
-
# expect(page).to
|
25
|
-
# expect(page).to
|
26
|
-
# expect(page).to
|
27
|
-
# expect(page).to
|
28
|
-
#
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
have_no_css].freeze
|
33
|
-
SPECIFIC_MATCHER = {
|
34
|
-
'button' => 'button',
|
35
|
-
'a' => 'link',
|
36
|
-
'table' => 'table',
|
37
|
-
'select' => 'select',
|
38
|
-
'input' => 'field'
|
39
|
-
}.freeze
|
40
|
-
|
41
|
-
# @!method first_argument(node)
|
42
|
-
def_node_matcher :first_argument, <<-PATTERN
|
43
|
-
(send nil? _ (str $_) ... )
|
44
|
-
PATTERN
|
45
|
-
|
46
|
-
def on_send(node)
|
47
|
-
first_argument(node) do |arg|
|
48
|
-
next unless (matcher = specific_matcher(arg))
|
49
|
-
next if CssSelector.multiple_selectors?(arg)
|
50
|
-
next unless CapybaraHelp.specific_option?(node, arg, matcher)
|
51
|
-
next unless CapybaraHelp.specific_pseudo_classes?(arg)
|
52
|
-
|
53
|
-
add_offense(node, message: message(node, matcher))
|
54
|
-
end
|
55
|
-
end
|
56
|
-
|
57
|
-
private
|
58
|
-
|
59
|
-
def specific_matcher(arg)
|
60
|
-
splitted_arg = arg[/^\w+/, 0]
|
61
|
-
SPECIFIC_MATCHER[splitted_arg]
|
62
|
-
end
|
63
|
-
|
64
|
-
def message(node, matcher)
|
65
|
-
format(MSG,
|
66
|
-
good_matcher: good_matcher(node, matcher),
|
67
|
-
bad_matcher: node.method_name)
|
68
|
-
end
|
69
|
-
|
70
|
-
def good_matcher(node, matcher)
|
71
|
-
node.method_name
|
72
|
-
.to_s
|
73
|
-
.gsub(/selector|css/, matcher.to_s)
|
74
|
-
end
|
75
|
-
end
|
7
|
+
# @!parse
|
8
|
+
# # Checks for there is a more specific matcher offered by Capybara.
|
9
|
+
# #
|
10
|
+
# # @example
|
11
|
+
# #
|
12
|
+
# # # bad
|
13
|
+
# # expect(page).to have_selector('button')
|
14
|
+
# # expect(page).to have_no_selector('button.cls')
|
15
|
+
# # expect(page).to have_css('button')
|
16
|
+
# # expect(page).to have_no_css('a.cls', href: 'http://example.com')
|
17
|
+
# # expect(page).to have_css('table.cls')
|
18
|
+
# # expect(page).to have_css('select')
|
19
|
+
# # expect(page).to have_css('input', exact_text: 'foo')
|
20
|
+
# #
|
21
|
+
# # # good
|
22
|
+
# # expect(page).to have_button
|
23
|
+
# # expect(page).to have_no_button(class: 'cls')
|
24
|
+
# # expect(page).to have_button
|
25
|
+
# # expect(page).to have_no_link('foo', class: 'cls', href: 'http://example.com')
|
26
|
+
# # expect(page).to have_table(class: 'cls')
|
27
|
+
# # expect(page).to have_select
|
28
|
+
# # expect(page).to have_field('foo')
|
29
|
+
# #
|
30
|
+
# class SpecificMatcher < ::RuboCop::Cop::Base; end
|
31
|
+
SpecificMatcher = ::RuboCop::Cop::Capybara::SpecificMatcher
|
76
32
|
end
|
77
33
|
end
|
78
34
|
end
|
@@ -4,69 +4,32 @@ module RuboCop
|
|
4
4
|
module Cop
|
5
5
|
module RSpec
|
6
6
|
module Capybara
|
7
|
-
#
|
8
|
-
#
|
9
|
-
#
|
10
|
-
#
|
11
|
-
#
|
12
|
-
#
|
13
|
-
#
|
14
|
-
#
|
15
|
-
#
|
16
|
-
#
|
17
|
-
#
|
18
|
-
#
|
19
|
-
# #
|
20
|
-
#
|
21
|
-
#
|
22
|
-
# expect(page).to
|
23
|
-
#
|
24
|
-
# #
|
25
|
-
#
|
26
|
-
#
|
27
|
-
# expect(page).to
|
28
|
-
#
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
button
|
34
|
-
checked_field
|
35
|
-
css
|
36
|
-
field
|
37
|
-
link
|
38
|
-
select
|
39
|
-
selector
|
40
|
-
table
|
41
|
-
unchecked_field
|
42
|
-
xpath
|
43
|
-
].flat_map do |element|
|
44
|
-
["have_#{element}".to_sym, "have_no_#{element}".to_sym]
|
45
|
-
end
|
46
|
-
|
47
|
-
RESTRICT_ON_SEND = CAPYBARA_MATCHER_METHODS
|
48
|
-
|
49
|
-
# @!method visible_true?(node)
|
50
|
-
def_node_matcher :visible_true?, <<~PATTERN
|
51
|
-
(send nil? #capybara_matcher? ... (hash <$(pair (sym :visible) true) ...>))
|
52
|
-
PATTERN
|
53
|
-
|
54
|
-
# @!method visible_false?(node)
|
55
|
-
def_node_matcher :visible_false?, <<~PATTERN
|
56
|
-
(send nil? #capybara_matcher? ... (hash <$(pair (sym :visible) false) ...>))
|
57
|
-
PATTERN
|
58
|
-
|
59
|
-
def on_send(node)
|
60
|
-
visible_false?(node) { |arg| add_offense(arg, message: MSG_FALSE) }
|
61
|
-
visible_true?(node) { |arg| add_offense(arg, message: MSG_TRUE) }
|
62
|
-
end
|
63
|
-
|
64
|
-
private
|
65
|
-
|
66
|
-
def capybara_matcher?(method_name)
|
67
|
-
CAPYBARA_MATCHER_METHODS.include? method_name
|
68
|
-
end
|
69
|
-
end
|
7
|
+
# @!parse
|
8
|
+
# # Checks for boolean visibility in Capybara finders.
|
9
|
+
# #
|
10
|
+
# # Capybara lets you find elements that match a certain visibility
|
11
|
+
# # using the `:visible` option. `:visible` accepts both boolean and
|
12
|
+
# # symbols as values, however using booleans can have unwanted
|
13
|
+
# # effects. `visible: false` does not find just invisible elements,
|
14
|
+
# # but both visible and invisible elements. For expressiveness and
|
15
|
+
# # clarity, use one of the # symbol values, `:all`, `:hidden` or
|
16
|
+
# # `:visible`.
|
17
|
+
# # Read more in
|
18
|
+
# # https://www.rubydoc.info/gems/capybara/Capybara%2FNode%2FFinders:all[the documentation].
|
19
|
+
# #
|
20
|
+
# # @example
|
21
|
+
# # # bad
|
22
|
+
# # expect(page).to have_selector('.foo', visible: false)
|
23
|
+
# # expect(page).to have_css('.foo', visible: true)
|
24
|
+
# # expect(page).to have_link('my link', visible: false)
|
25
|
+
# #
|
26
|
+
# # # good
|
27
|
+
# # expect(page).to have_selector('.foo', visible: :visible)
|
28
|
+
# # expect(page).to have_css('.foo', visible: :all)
|
29
|
+
# # expect(page).to have_link('my link', visible: :hidden)
|
30
|
+
# #
|
31
|
+
# class VisibilityMatcher < ::RuboCop::Cop::Base; end
|
32
|
+
VisibilityMatcher = ::RuboCop::Cop::Capybara::VisibilityMatcher
|
70
33
|
end
|
71
34
|
end
|
72
35
|
end
|
@@ -31,7 +31,11 @@ module RuboCop
|
|
31
31
|
|
32
32
|
# @!method context_method(node)
|
33
33
|
def_node_matcher :context_method, <<-PATTERN
|
34
|
-
(block
|
34
|
+
(block
|
35
|
+
(send #rspec? :context
|
36
|
+
${(str #method_name?) (dstr (str #method_name?) ...)}
|
37
|
+
...)
|
38
|
+
...)
|
35
39
|
PATTERN
|
36
40
|
|
37
41
|
def on_block(node) # rubocop:disable InternalAffairs/NumblockHandler
|
@@ -10,7 +10,6 @@ module RuboCop
|
|
10
10
|
# include `if`, `unless`, `for`, `before`, `after`, or `during`.
|
11
11
|
# They may consist of multiple words if desired.
|
12
12
|
#
|
13
|
-
# @see https://rspec.rubystyle.guide/#context-descriptions
|
14
13
|
# @see http://www.betterspecs.org/#contexts
|
15
14
|
#
|
16
15
|
# @example `Prefixes` configuration
|
@@ -11,7 +11,7 @@ module RuboCop
|
|
11
11
|
def_node_matcher :skipped_in_metadata?, <<-PATTERN
|
12
12
|
{
|
13
13
|
(send _ _ <#skip_or_pending? ...>)
|
14
|
-
(send _ _ ... (hash <(pair #skip_or_pending? { true str }) ...>))
|
14
|
+
(send _ _ ... (hash <(pair #skip_or_pending? { true str dstr }) ...>))
|
15
15
|
}
|
16
16
|
PATTERN
|
17
17
|
|
@@ -87,35 +87,33 @@ module RuboCop
|
|
87
87
|
(send #rspec? {#ExampleGroups.all #Examples.all} ... {<(sym :skip) ...> (hash <(pair (sym :skip) true) ...>)})
|
88
88
|
PATTERN
|
89
89
|
|
90
|
+
# @!method without_reason?(node)
|
91
|
+
def_node_matcher :without_reason?, <<~PATTERN
|
92
|
+
(send nil? ${:pending :skip})
|
93
|
+
PATTERN
|
94
|
+
|
90
95
|
def on_send(node)
|
91
96
|
if pending_without_reason?(node)
|
92
97
|
add_offense(node, message: 'Give the reason for pending.')
|
93
98
|
elsif skipped_without_reason?(node)
|
94
99
|
add_offense(node, message: 'Give the reason for skip.')
|
100
|
+
elsif without_reason?(node) && example?(node.parent)
|
101
|
+
add_offense(node,
|
102
|
+
message: "Give the reason for #{node.method_name}.")
|
95
103
|
end
|
96
104
|
end
|
97
105
|
|
98
106
|
private
|
99
107
|
|
100
|
-
def pending_by_pending_step_without_reason?(node)
|
101
|
-
node.method?(:pending) && node.first_argument.nil?
|
102
|
-
end
|
103
|
-
|
104
108
|
def pending_without_reason?(node)
|
105
109
|
pending_by_example_method?(node.block_node) ||
|
106
|
-
pending_by_metadata_without_reason?(node)
|
107
|
-
pending_by_pending_step_without_reason?(node)
|
108
|
-
end
|
109
|
-
|
110
|
-
def skipped_by_skip_step_without_reason?(node)
|
111
|
-
node.method?(:skip) && node.first_argument.nil?
|
110
|
+
pending_by_metadata_without_reason?(node)
|
112
111
|
end
|
113
112
|
|
114
113
|
def skipped_without_reason?(node)
|
115
114
|
skipped_by_example_group_method?(node.block_node) ||
|
116
115
|
skipped_by_example_method?(node.block_node) ||
|
117
|
-
skipped_by_metadata_without_reason?(node)
|
118
|
-
skipped_by_skip_step_without_reason?(node)
|
116
|
+
skipped_by_metadata_without_reason?(node)
|
119
117
|
end
|
120
118
|
end
|
121
119
|
end
|
@@ -118,7 +118,7 @@ module RuboCop
|
|
118
118
|
end
|
119
119
|
|
120
120
|
# A helper for `explicit` style
|
121
|
-
module ExplicitHelper
|
121
|
+
module ExplicitHelper # rubocop:disable Metrics/ModuleLength
|
122
122
|
include RuboCop::RSpec::Language
|
123
123
|
extend NodePattern::Macros
|
124
124
|
|
@@ -149,12 +149,35 @@ module RuboCop
|
|
149
149
|
return if part_of_ignored_node?(node)
|
150
150
|
|
151
151
|
predicate_matcher?(node) do |actual, matcher|
|
152
|
+
next unless replaceable_matcher?(matcher)
|
153
|
+
|
152
154
|
add_offense(node, message: message_explicit(matcher)) do |corrector|
|
155
|
+
next if uncorrectable_matcher?(node, matcher)
|
156
|
+
|
153
157
|
corrector_explicit(corrector, node, actual, matcher, matcher)
|
154
158
|
end
|
155
159
|
end
|
156
160
|
end
|
157
161
|
|
162
|
+
def replaceable_matcher?(matcher)
|
163
|
+
case matcher.method_name.to_s
|
164
|
+
when 'include'
|
165
|
+
matcher.arguments.one?
|
166
|
+
else
|
167
|
+
true
|
168
|
+
end
|
169
|
+
end
|
170
|
+
|
171
|
+
def uncorrectable_matcher?(node, matcher)
|
172
|
+
heredoc_argument?(matcher) && !same_line?(node, matcher)
|
173
|
+
end
|
174
|
+
|
175
|
+
def heredoc_argument?(matcher)
|
176
|
+
matcher.arguments.select do |arg|
|
177
|
+
%i[str dstr xstr].include?(arg.type)
|
178
|
+
end.any?(&:heredoc?)
|
179
|
+
end
|
180
|
+
|
158
181
|
# @!method predicate_matcher?(node)
|
159
182
|
def_node_matcher :predicate_matcher?, <<-PATTERN
|
160
183
|
(send
|
@@ -179,7 +202,8 @@ module RuboCop
|
|
179
202
|
|
180
203
|
return false if allowed_explicit_matchers.include?(name)
|
181
204
|
|
182
|
-
name.start_with?('be_', 'have_') && !name.end_with?('?')
|
205
|
+
name.start_with?('be_', 'have_') && !name.end_with?('?') ||
|
206
|
+
%w[include respond_to].include?(name)
|
183
207
|
end
|
184
208
|
|
185
209
|
def message_explicit(matcher)
|
@@ -270,6 +294,17 @@ module RuboCop
|
|
270
294
|
# # good - the above code is rewritten to it by this cop
|
271
295
|
# expect(foo.something?).to be(true)
|
272
296
|
#
|
297
|
+
# # bad - no autocorrect
|
298
|
+
# expect(foo)
|
299
|
+
# .to be_something(<<~TEXT)
|
300
|
+
# bar
|
301
|
+
# TEXT
|
302
|
+
#
|
303
|
+
# # good
|
304
|
+
# expect(foo.something?(<<~TEXT)).to be(true)
|
305
|
+
# bar
|
306
|
+
# TEXT
|
307
|
+
#
|
273
308
|
# @example Strict: false, EnforcedStyle: explicit
|
274
309
|
# # bad
|
275
310
|
# expect(foo).to be_something
|
@@ -0,0 +1,60 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module RuboCop
|
4
|
+
module Cop
|
5
|
+
module RSpec
|
6
|
+
module Rails
|
7
|
+
# Check if using Minitest matchers.
|
8
|
+
#
|
9
|
+
# @example
|
10
|
+
# # bad
|
11
|
+
# assert_equal(a, b)
|
12
|
+
# assert_equal a, b, "must be equal"
|
13
|
+
# refute_equal(a, b)
|
14
|
+
#
|
15
|
+
# # good
|
16
|
+
# expect(a).to eq(b)
|
17
|
+
# expect(a).to(eq(b), "must be equal")
|
18
|
+
# expect(a).not_to eq(b)
|
19
|
+
#
|
20
|
+
class MinitestAssertions < Base
|
21
|
+
extend AutoCorrector
|
22
|
+
|
23
|
+
MSG = 'Use `%<prefer>s`.'
|
24
|
+
RESTRICT_ON_SEND = %i[assert_equal refute_equal].freeze
|
25
|
+
|
26
|
+
# @!method minitest_assertion(node)
|
27
|
+
def_node_matcher :minitest_assertion, <<-PATTERN
|
28
|
+
(send nil? {:assert_equal :refute_equal} $_ $_ $_?)
|
29
|
+
PATTERN
|
30
|
+
|
31
|
+
def on_send(node)
|
32
|
+
minitest_assertion(node) do |expected, actual, failure_message|
|
33
|
+
prefer = replacement(node, expected, actual,
|
34
|
+
failure_message.first)
|
35
|
+
add_offense(node, message: message(prefer)) do |corrector|
|
36
|
+
corrector.replace(node, prefer)
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
private
|
42
|
+
|
43
|
+
def replacement(node, expected, actual, failure_message)
|
44
|
+
runner = node.method?(:assert_equal) ? 'to' : 'not_to'
|
45
|
+
if failure_message.nil?
|
46
|
+
"expect(#{expected.source}).#{runner} eq(#{actual.source})"
|
47
|
+
else
|
48
|
+
"expect(#{expected.source}).#{runner}(eq(#{actual.source}), " \
|
49
|
+
"#{failure_message.source})"
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
def message(prefer)
|
54
|
+
format(MSG, prefer: prefer)
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
@@ -91,7 +91,7 @@ module RuboCop
|
|
91
91
|
# @param node [RuboCop::AST::Node]
|
92
92
|
# @yield [RuboCop::AST::Node] matcher
|
93
93
|
def_node_matcher :matcher_with_return_block, <<~PATTERN
|
94
|
-
(block #message_expectation? args _) # receive(:foo) { 'bar' }
|
94
|
+
(block #message_expectation? (args) _) # receive(:foo) { 'bar' }
|
95
95
|
PATTERN
|
96
96
|
|
97
97
|
# @!method matcher_with_hash(node)
|
@@ -12,7 +12,6 @@ module RuboCop
|
|
12
12
|
#
|
13
13
|
# @see https://robots.thoughtbot.com/don-t-stub-the-system-under-test
|
14
14
|
# @see https://penelope.zone/2015/12/27/introducing-rspec-smells-and-where-to-find-them.html#smell-1-stubjec
|
15
|
-
# @see https://github.com/rubocop-hq/rspec-style-guide#dont-stub-subject
|
16
15
|
#
|
17
16
|
# @example
|
18
17
|
# # bad
|
@@ -2,6 +2,7 @@
|
|
2
2
|
|
3
3
|
require_relative 'rspec/capybara/current_path_expectation'
|
4
4
|
require_relative 'rspec/capybara/feature_methods'
|
5
|
+
require_relative 'rspec/capybara/match_style'
|
5
6
|
require_relative 'rspec/capybara/negation_matcher'
|
6
7
|
require_relative 'rspec/capybara/specific_actions'
|
7
8
|
require_relative 'rspec/capybara/specific_finders'
|
@@ -23,6 +24,7 @@ rescue LoadError
|
|
23
24
|
# Rails/HttpStatus cannot be loaded if rack/utils is unavailable.
|
24
25
|
end
|
25
26
|
require_relative 'rspec/rails/inferred_spec_type'
|
27
|
+
require_relative 'rspec/rails/minitest_assertions'
|
26
28
|
|
27
29
|
require_relative 'rspec/align_left_let_brace'
|
28
30
|
require_relative 'rspec/align_right_let_brace'
|
@@ -8,6 +8,15 @@ module RuboCop
|
|
8
8
|
class ConfigFormatter
|
9
9
|
EXTENSION_ROOT_DEPARTMENT = %r{^(RSpec/)}.freeze
|
10
10
|
SUBDEPARTMENTS = %(RSpec/Capybara RSpec/FactoryBot RSpec/Rails)
|
11
|
+
EXTRACTED_COPS = %(
|
12
|
+
RSpec/Capybara/CurrentPathExpectation
|
13
|
+
RSpec/Capybara/MatchStyle
|
14
|
+
RSpec/Capybara/NegationMatcher
|
15
|
+
RSpec/Capybara/SpecificActions
|
16
|
+
RSpec/Capybara/SpecificFinders
|
17
|
+
RSpec/Capybara/SpecificMatcher
|
18
|
+
RSpec/Capybara/VisibilityMatcher
|
19
|
+
)
|
11
20
|
AMENDMENTS = %(Metrics/BlockLength)
|
12
21
|
COP_DOC_BASE_URL = 'https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/'
|
13
22
|
|
@@ -29,6 +38,7 @@ module RuboCop
|
|
29
38
|
def unified_config
|
30
39
|
cops.each_with_object(config.dup) do |cop, unified|
|
31
40
|
next if SUBDEPARTMENTS.include?(cop) || AMENDMENTS.include?(cop)
|
41
|
+
next if EXTRACTED_COPS.include?(cop)
|
32
42
|
|
33
43
|
replace_nil(unified[cop])
|
34
44
|
unified[cop].merge!(descriptions.fetch(cop))
|
data/lib/rubocop-rspec.rb
CHANGED
@@ -4,6 +4,7 @@ require 'pathname'
|
|
4
4
|
require 'yaml'
|
5
5
|
|
6
6
|
require 'rubocop'
|
7
|
+
require 'rubocop-capybara'
|
7
8
|
|
8
9
|
require_relative 'rubocop/rspec'
|
9
10
|
require_relative 'rubocop/rspec/inject'
|
@@ -17,8 +18,6 @@ require_relative 'rubocop/rspec/language'
|
|
17
18
|
|
18
19
|
require_relative 'rubocop/rspec/factory_bot/language'
|
19
20
|
|
20
|
-
require_relative 'rubocop/cop/rspec/mixin/capybara_help'
|
21
|
-
require_relative 'rubocop/cop/rspec/mixin/css_selector'
|
22
21
|
require_relative 'rubocop/cop/rspec/mixin/final_end_location'
|
23
22
|
require_relative 'rubocop/cop/rspec/mixin/inside_example_group'
|
24
23
|
require_relative 'rubocop/cop/rspec/mixin/metadata'
|
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: 2.
|
4
|
+
version: 2.18.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:
|
13
|
+
date: 2023-01-19 00:00:00.000000000 Z
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|
16
16
|
name: rubocop
|
@@ -26,6 +26,20 @@ dependencies:
|
|
26
26
|
- - "~>"
|
27
27
|
- !ruby/object:Gem::Version
|
28
28
|
version: '1.33'
|
29
|
+
- !ruby/object:Gem::Dependency
|
30
|
+
name: rubocop-capybara
|
31
|
+
requirement: !ruby/object:Gem::Requirement
|
32
|
+
requirements:
|
33
|
+
- - "~>"
|
34
|
+
- !ruby/object:Gem::Version
|
35
|
+
version: '2.17'
|
36
|
+
type: :runtime
|
37
|
+
prerelease: false
|
38
|
+
version_requirements: !ruby/object:Gem::Requirement
|
39
|
+
requirements:
|
40
|
+
- - "~>"
|
41
|
+
- !ruby/object:Gem::Version
|
42
|
+
version: '2.17'
|
29
43
|
description: |2
|
30
44
|
Code style checking for RSpec files.
|
31
45
|
A plugin for the RuboCop code style enforcing & linting tool.
|
@@ -58,6 +72,7 @@ files:
|
|
58
72
|
- lib/rubocop/cop/rspec/before_after_all.rb
|
59
73
|
- lib/rubocop/cop/rspec/capybara/current_path_expectation.rb
|
60
74
|
- lib/rubocop/cop/rspec/capybara/feature_methods.rb
|
75
|
+
- lib/rubocop/cop/rspec/capybara/match_style.rb
|
61
76
|
- lib/rubocop/cop/rspec/capybara/negation_matcher.rb
|
62
77
|
- lib/rubocop/cop/rspec/capybara/specific_actions.rb
|
63
78
|
- lib/rubocop/cop/rspec/capybara/specific_finders.rb
|
@@ -115,9 +130,7 @@ files:
|
|
115
130
|
- lib/rubocop/cop/rspec/message_expectation.rb
|
116
131
|
- lib/rubocop/cop/rspec/message_spies.rb
|
117
132
|
- lib/rubocop/cop/rspec/missing_example_group_argument.rb
|
118
|
-
- lib/rubocop/cop/rspec/mixin/capybara_help.rb
|
119
133
|
- lib/rubocop/cop/rspec/mixin/comments_help.rb
|
120
|
-
- lib/rubocop/cop/rspec/mixin/css_selector.rb
|
121
134
|
- lib/rubocop/cop/rspec/mixin/empty_line_separation.rb
|
122
135
|
- lib/rubocop/cop/rspec/mixin/final_end_location.rb
|
123
136
|
- lib/rubocop/cop/rspec/mixin/inside_example_group.rb
|
@@ -142,6 +155,7 @@ files:
|
|
142
155
|
- lib/rubocop/cop/rspec/rails/have_http_status.rb
|
143
156
|
- lib/rubocop/cop/rspec/rails/http_status.rb
|
144
157
|
- lib/rubocop/cop/rspec/rails/inferred_spec_type.rb
|
158
|
+
- lib/rubocop/cop/rspec/rails/minitest_assertions.rb
|
145
159
|
- lib/rubocop/cop/rspec/receive_counts.rb
|
146
160
|
- lib/rubocop/cop/rspec/receive_never.rb
|
147
161
|
- lib/rubocop/cop/rspec/repeated_description.rb
|
@@ -207,7 +221,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
207
221
|
- !ruby/object:Gem::Version
|
208
222
|
version: '0'
|
209
223
|
requirements: []
|
210
|
-
rubygems_version: 3.
|
224
|
+
rubygems_version: 3.3.7
|
211
225
|
signing_key:
|
212
226
|
specification_version: 4
|
213
227
|
summary: Code style checking for RSpec files
|
@@ -1,80 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
module RuboCop
|
4
|
-
module Cop
|
5
|
-
module RSpec
|
6
|
-
# Help methods for capybara.
|
7
|
-
module CapybaraHelp
|
8
|
-
module_function
|
9
|
-
|
10
|
-
# @param node [RuboCop::AST::SendNode]
|
11
|
-
# @param locator [String]
|
12
|
-
# @param element [String]
|
13
|
-
# @return [Boolean]
|
14
|
-
def specific_option?(node, locator, element)
|
15
|
-
attrs = CssSelector.attributes(locator).keys
|
16
|
-
return false unless replaceable_element?(node, element, attrs)
|
17
|
-
|
18
|
-
attrs.all? do |attr|
|
19
|
-
CssSelector.specific_options?(element, attr)
|
20
|
-
end
|
21
|
-
end
|
22
|
-
|
23
|
-
# @param locator [String]
|
24
|
-
# @return [Boolean]
|
25
|
-
def specific_pseudo_classes?(locator)
|
26
|
-
CssSelector.pseudo_classes(locator).all? do |pseudo_class|
|
27
|
-
replaceable_pseudo_class?(pseudo_class, locator)
|
28
|
-
end
|
29
|
-
end
|
30
|
-
|
31
|
-
# @param pseudo_class [String]
|
32
|
-
# @param locator [String]
|
33
|
-
# @return [Boolean]
|
34
|
-
def replaceable_pseudo_class?(pseudo_class, locator)
|
35
|
-
return false unless CssSelector.specific_pesudo_classes?(pseudo_class)
|
36
|
-
|
37
|
-
case pseudo_class
|
38
|
-
when 'not()' then replaceable_pseudo_class_not?(locator)
|
39
|
-
else true
|
40
|
-
end
|
41
|
-
end
|
42
|
-
|
43
|
-
# @param locator [String]
|
44
|
-
# @return [Boolean]
|
45
|
-
def replaceable_pseudo_class_not?(locator)
|
46
|
-
locator.scan(/not\(.*?\)/).all? do |negation|
|
47
|
-
CssSelector.attributes(negation).values.all? do |v|
|
48
|
-
v.is_a?(TrueClass) || v.is_a?(FalseClass)
|
49
|
-
end
|
50
|
-
end
|
51
|
-
end
|
52
|
-
|
53
|
-
# @param node [RuboCop::AST::SendNode]
|
54
|
-
# @param element [String]
|
55
|
-
# @param attrs [Array<String>]
|
56
|
-
# @return [Boolean]
|
57
|
-
def replaceable_element?(node, element, attrs)
|
58
|
-
case element
|
59
|
-
when 'link' then replaceable_to_link?(node, attrs)
|
60
|
-
else true
|
61
|
-
end
|
62
|
-
end
|
63
|
-
|
64
|
-
# @param node [RuboCop::AST::SendNode]
|
65
|
-
# @param attrs [Array<String>]
|
66
|
-
# @return [Boolean]
|
67
|
-
def replaceable_to_link?(node, attrs)
|
68
|
-
include_option?(node, :href) || attrs.include?('href')
|
69
|
-
end
|
70
|
-
|
71
|
-
# @param node [RuboCop::AST::SendNode]
|
72
|
-
# @param option [Symbol]
|
73
|
-
# @return [Boolean]
|
74
|
-
def include_option?(node, option)
|
75
|
-
node.each_descendant(:sym).find { |opt| opt.value == option }
|
76
|
-
end
|
77
|
-
end
|
78
|
-
end
|
79
|
-
end
|
80
|
-
end
|