Skip to content

Commit

Permalink
reduce unnecessary wirecalls
Browse files Browse the repository at this point in the history
  • Loading branch information
twalpole committed May 9, 2018
1 parent 170bc99 commit 8e2e291
Show file tree
Hide file tree
Showing 3 changed files with 35 additions and 20 deletions.
45 changes: 26 additions & 19 deletions lib/capybara/selector.rb
Original file line number Diff line number Diff line change
Expand Up @@ -136,11 +136,19 @@
Capybara.add_selector(:link) do
xpath(:title, :alt) do |locator, href: true, enable_aria_label: false, alt: nil, title: nil, **_options|
xpath = XPath.descendant(:a)
xpath = if href.nil?
xpath[!XPath.attr(:href)]
else
xpath[XPath.attr(:href)]
end
xpath = xpath[
case href
when nil, false
!XPath.attr(:href)
when true
XPath.attr(:href)
when Regexp
nil # needs to be handled in filter
else
XPath.attr(:href) == href.to_s
end
]

unless locator.nil?
locator = locator.to_s
matchers = [XPath.attr(:id) == locator,
Expand All @@ -150,20 +158,15 @@
matchers |= XPath.attr(:'aria-label').is(locator) if enable_aria_label
xpath = xpath[matchers]
end

xpath = xpath[find_by_attr(:title, title)]
xpath = xpath[XPath.descendant(:img)[XPath.attr(:alt) == alt]] if alt
xpath
end

filter(:href) do |node, href|
case href
when nil
true
when Regexp
node[:href].match href
else
node.first(:xpath, XPath.self[XPath.attr(:href) == href.to_s], minimum: 0)
end
# If not a Regexp it's been handled in the main XPath
href.is_a?(Regexp) ? node[:href].match(href) : true
end

describe do |**options|
Expand Down Expand Up @@ -380,10 +383,11 @@
options.sort == actual.sort
end

filter(:with_options) do |node, options|
finder_settings = { minimum: 0 }
finder_settings[:visible] = false unless node.visible?
options.all? { |option| node.first(:option, option, finder_settings) }
expression_filter(:with_options) do |expr, options|
options.each do |option|
expr = expr[Capybara::Selector.all[:option].call(option)]
end
expr
end

filter(:selected) do |node, selected|
Expand Down Expand Up @@ -422,8 +426,11 @@
options.sort == actual.sort
end

filter(:with_options) do |node, options|
options.all? { |option| node.find("//datalist[@id=#{node[:list]}]", visible: :all).first(:datalist_option, option) }
expression_filter(:with_options) do |expr, options|
options.each do |option|
expr = expr[XPath.attr(:list) == XPath.anywhere(:datalist)[Capybara::Selector.all[:datalist_option].call(option)].attr(:id)]
end
expr
end

describe do |options: nil, with_options: nil, **opts|
Expand Down
2 changes: 1 addition & 1 deletion lib/capybara/selenium/node.rb
Original file line number Diff line number Diff line change
Expand Up @@ -199,7 +199,7 @@ def path
parent = path.first
selector = node.tag_name
if parent
siblings = parent.find_xpath(node.tag_name)
siblings = parent.find_xpath(selector)
selector += "[#{siblings.index(node) + 1}]" unless siblings.size == 1
end
result.push selector
Expand Down
8 changes: 8 additions & 0 deletions lib/capybara/spec/session/has_selector_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,14 @@
end
end
end

context "datalist" do
it "should match options" do
@session.visit('/form')
expect(@session).to have_selector(:datalist_input, with_options: %w[Jaguar Audi Mercedes])
expect(@session).not_to have_selector(:datalist_input, with_options: %w[Ford Chevy])
end
end
end

Capybara::SpecHelper.spec '#has_no_selector?' do
Expand Down

0 comments on commit 8e2e291

Please sign in to comment.