diff --git a/lib/capybara/node/finders.rb b/lib/capybara/node/finders.rb index 93776e58..7f3c4205 100644 --- a/lib/capybara/node/finders.rb +++ b/lib/capybara/node/finders.rb @@ -31,7 +31,7 @@ module Capybara def find(*args) query = Capybara::Queries::SelectorQuery.new(*args) synchronize(query.wait) do - if query.match == :smart or query.match == :prefer_exact + if (query.match == :smart or query.match == :prefer_exact) and query.supports_exact? result = query.resolve_for(self, true) result = query.resolve_for(self, false) if result.empty? && !query.exact? else diff --git a/lib/capybara/queries/selector_query.rb b/lib/capybara/queries/selector_query.rb index 5bac5b0f..60341212 100644 --- a/lib/capybara/queries/selector_query.rb +++ b/lib/capybara/queries/selector_query.rb @@ -27,6 +27,9 @@ module Capybara end @expression = @selector.call(@locator) + + warn_exact_usage(@expression.to_s) + assert_valid_keys end @@ -79,6 +82,7 @@ module Capybara end def exact? + return false if !supports_exact? if options.has_key?(:exact) @options[:exact] else @@ -125,6 +129,11 @@ module Capybara end end + # @api private + def supports_exact? + @expression.respond_to? :to_xpath + end + private def valid_keys @@ -150,6 +159,13 @@ module Capybara raise ArgumentError, "invalid option #{match.inspect} for :match, should be one of #{VALID_MATCH.map(&:inspect).join(", ")}" end end + + def warn_exact_usage(expression) + if options.has_key?(:exact) && !supports_exact? + warn "The :exact option only has an effect on queries using the XPath#is method. Using it with the query \"#{expression}\" has no effect." + end + expression + end end end end diff --git a/lib/capybara/spec/session/find_spec.rb b/lib/capybara/spec/session/find_spec.rb index a8a67ddd..ea89c325 100644 --- a/lib/capybara/spec/session/find_spec.rb +++ b/lib/capybara/spec/session/find_spec.rb @@ -235,6 +235,12 @@ Capybara::SpecHelper.spec '#find' do Capybara.exact = false @session.find(:xpath, XPath.descendant(:input)[XPath.attr(:id).is("est_fiel")]) end + + it "warns when the option has no effect" do + expect_any_instance_of(Kernel).to receive(:warn). + with('The :exact option only has an effect on queries using the XPath#is method. Using it with the query "#test_field" has no effect.') + @session.find(:css, '#test_field', exact: true) + end end context "with :match option" do @@ -292,7 +298,7 @@ Capybara::SpecHelper.spec '#find' do end it "raises an error if there is no match" do expect do - @session.find(:css, ".does-not-exist", :match => :smart, :exact => false) + @session.find(:xpath, XPath.descendant[XPath.attr(:class).is("does-not-exist")], :match => :smart, :exact => false) end.to raise_error(Capybara::ElementNotFound) end end @@ -319,7 +325,7 @@ Capybara::SpecHelper.spec '#find' do end it "raises an error if there is no match" do expect do - @session.find(:css, ".does-not-exist", :match => :smart, :exact => true) + @session.find(:xpath, XPath.descendant[XPath.attr(:class).is("does-not-exist")], :match => :smart, :exact => true) end.to raise_error(Capybara::ElementNotFound) end end @@ -345,7 +351,7 @@ Capybara::SpecHelper.spec '#find' do end it "raises an error if there is no match" do expect do - @session.find(:css, ".does-not-exist", :match => :prefer_exact, :exact => false) + @session.find(:xpath, XPath.descendant[XPath.attr(:class).is("does-not-exist")], :match => :prefer_exact, :exact => false) end.to raise_error(Capybara::ElementNotFound) end end @@ -371,7 +377,7 @@ Capybara::SpecHelper.spec '#find' do end it "raises an error if there is no match" do expect do - @session.find(:css, ".does-not-exist", :match => :prefer_exact, :exact => true) + @session.find(:xpath, XPath.descendant[XPath.attr(:class).is("does-not-exist")], :match => :prefer_exact, :exact => true) end.to raise_error(Capybara::ElementNotFound) end end