lib/rubocop/cop/capybara/specific_finders.rb in rubocop-capybara-2.18.0 vs lib/rubocop/cop/capybara/specific_finders.rb in rubocop-capybara-2.19.0
- old
+ new
@@ -6,75 +6,79 @@
# Checks if there is a more specific finder offered by Capybara.
#
# @example
# # bad
# find('#some-id')
- # find('[visible][id=some-id]')
+ # find('[id=some-id]')
+ # find(:css, '#some-id')
#
# # good
# find_by_id('some-id')
- # find_by_id('some-id', visible: true)
#
class SpecificFinders < ::RuboCop::Cop::Base
extend AutoCorrector
-
include RangeHelp
MSG = 'Prefer `find_by_id` over `find`.'
RESTRICT_ON_SEND = %i[find].freeze
# @!method find_argument(node)
def_node_matcher :find_argument, <<~PATTERN
- (send _ :find (str $_) ...)
+ (send _ :find $(sym :css)? (str $_) ...)
PATTERN
# @!method class_options(node)
def_node_search :class_options, <<~PATTERN
(pair (sym :class) $_ ...)
PATTERN
def on_send(node)
- find_argument(node) do |arg|
+ find_argument(node) do |sym, arg|
next if CssSelector.pseudo_classes(arg).any?
next if CssSelector.multiple_selectors?(arg)
- on_attr(node, arg) if attribute?(arg)
- on_id(node, arg) if CssSelector.id?(arg)
+ on_attr(node, sym, arg) if attribute?(arg)
+ on_id(node, sym, arg) if CssSelector.id?(arg)
end
end
private
- def on_attr(node, arg)
+ def on_attr(node, sym, arg)
attrs = CssSelector.attributes(arg)
return unless (id = attrs['id'])
return if attrs['class']
- register_offense(node, replaced_arguments(arg, id))
+ register_offense(node, sym, replaced_arguments(arg, id))
end
- def on_id(node, arg)
+ def on_id(node, sym, arg)
return if CssSelector.attributes(arg).any?
id = CssSelector.id(arg)
- register_offense(node, "'#{id}'",
+ register_offense(node, sym, "'#{id}'",
CssSelector.classes(arg.sub("##{id}", '')))
end
def attribute?(arg)
CssSelector.attribute?(arg) &&
CapybaraHelp.common_attributes?(arg)
end
- def register_offense(node, id, classes = [])
+ def register_offense(node, sym, id, classes = [])
add_offense(offense_range(node)) do |corrector|
corrector.replace(node.loc.selector, 'find_by_id')
- corrector.replace(node.first_argument,
- id.delete('\\'))
+ corrector.replace(node.first_argument, id.delete('\\'))
unless classes.compact.empty?
autocorrect_classes(corrector, node, classes)
end
+ corrector.remove(deletion_range(node)) unless sym.empty?
end
+ end
+
+ def deletion_range(node)
+ range_between(node.arguments[0].source_range.end_pos,
+ node.arguments[1].source_range.end_pos)
end
def autocorrect_classes(corrector, node, classes)
if (options = class_options(node).first)
append_options(classes, options)