select_option/unselect_option are now called on option node

This means that we can move the find object into
Capybara::Node instead of Capybara::Driver::Node
which gives us AJAX waiting and preference for
exact matches for free.
This commit is contained in:
Jonas Nicklas 2010-08-14 13:42:53 +02:00
parent 183da5278d
commit 8d341948fd
9 changed files with 62 additions and 74 deletions

View File

@ -25,28 +25,19 @@ class Capybara::Driver::Celerity < Capybara::Driver::Base
native.set(value)
end
def select_option(option)
native.select(option)
rescue
options = find("//option").map { |o| "'#{o.text}'" }.join(', ')
raise Capybara::OptionNotFound, "No such option '#{option}' in this select box. Available options: #{options}"
def select_option
native.click
end
def unselect_option(option)
unless native.multiple?
raise Capybara::UnselectNotAllowed, "Cannot unselect option '#{option}' from single select box."
def unselect_option
unless select_node.native.multiple?
raise Capybara::UnselectNotAllowed, "Cannot unselect option from single select box."
end
# FIXME: couldn't find a clean way to unselect, so clear and reselect
selected_options = native.selected_options
if unselect_option = selected_options.detect { |value| value == option } ||
selected_options.detect { |value| value.index(option) }
native.clear
(selected_options - [unselect_option]).each { |value| native.select_value(value) }
else
options = find("//option").map { |o| "'#{o.text}'" }.join(', ')
raise Capybara::OptionNotFound, "No such option '#{option}' in this select box. Available options: #{options}"
end
selected_nodes = select_node.find('.//option[@selected]')
select_node.native.clear
selected_nodes.each { |n| n.click unless n.path == path }
end
def click
@ -83,6 +74,14 @@ class Capybara::Driver::Celerity < Capybara::Driver::Base
if all_nodes.empty? then [] else driver.find(all_nodes) end
end
protected
# a reference to the select node if this is an option node
def select_node
find('./ancestor::select').first
end
end
attr_reader :app, :rack_server

View File

@ -24,11 +24,11 @@ module Capybara
raise NotImplementedError
end
def select_option(option)
def select_option
raise NotImplementedError
end
def unselect_option(option)
def unselect_option
raise NotImplementedError
end

View File

@ -51,32 +51,18 @@ class Capybara::Driver::RackTest < Capybara::Driver::Base
end
end
def select_option(option)
if native['multiple'] != 'multiple'
native.xpath(".//option[@selected]").each { |node| node.remove_attribute("selected") }
end
if option_node = native.xpath(".//option[text()=#{Capybara::XPath.escape(option)}]").first ||
native.xpath(".//option[contains(.,#{Capybara::XPath.escape(option)})]").first
option_node["selected"] = 'selected'
else
options = native.xpath(".//option").map { |o| "'#{o.text}'" }.join(', ')
raise Capybara::OptionNotFound, "No such option '#{option}' in this select box. Available options: #{options}"
def select_option
if select_node['multiple'] != 'multiple'
select_node.find(".//option[@selected]").each { |node| node.native.remove_attribute("selected") }
end
native["selected"] = 'selected'
end
def unselect_option(option)
if native['multiple'] != 'multiple'
raise Capybara::UnselectNotAllowed, "Cannot unselect option '#{option}' from single select box."
end
if option_node = native.xpath(".//option[text()=#{Capybara::XPath.escape(option)}]").first ||
native.xpath(".//option[contains(.,#{Capybara::XPath.escape(option)})]").first
option_node.remove_attribute('selected')
else
options = native.xpath(".//option").map { |o| "'#{o.text}'" }.join(', ')
raise Capybara::OptionNotFound, "No such option '#{option}' in this select box. Available options: #{options}"
def unselect_option
if select_node['multiple'] != 'multiple'
raise Capybara::UnselectNotAllowed, "Cannot unselect option from single select box."
end
native.remove_attribute('selected')
end
def click
@ -106,6 +92,11 @@ class Capybara::Driver::RackTest < Capybara::Driver::Base
private
# a reference to the select node if this is an option node
def select_node
find('./ancestor::select').first
end
def type
native[:type]
end

View File

@ -35,26 +35,15 @@ class Capybara::Driver::Selenium < Capybara::Driver::Base
end
end
def select_option(option)
option_node = native.find_element(:xpath, ".//option[normalize-space(text())=#{Capybara::XPath.escape(option)}]") || native.find_element(:xpath, ".//option[contains(.,#{Capybara::XPath.escape(option)})]")
option_node.select
rescue
options = native.find_elements(:xpath, ".//option").map { |o| "'#{o.text}'" }.join(', ')
raise Capybara::OptionNotFound, "No such option '#{option}' in this select box. Available options: #{options}"
def select_option
native.select
end
def unselect_option(option)
if native['multiple'] != 'multiple'
raise Capybara::UnselectNotAllowed, "Cannot unselect option '#{option}' from single select box."
end
begin
option_node = native.find_element(:xpath, ".//option[normalize-space(text())=#{Capybara::XPath.escape(option)}]") || native.find_element(:xpath, ".//option[contains(.,#{Capybara::XPath.escape(option)})]")
option_node.clear
rescue
options = native.find_elements(:xpath, ".//option").map { |o| "'#{o.text}'" }.join(', ')
raise Capybara::OptionNotFound, "No such option '#{option}' in this select box. Available options: #{options}"
def unselect_option
if select_node['multiple'] != 'multiple'
raise Capybara::UnselectNotAllowed, "Cannot unselect option from single select box."
end
native.clear
end
def click
@ -79,6 +68,11 @@ class Capybara::Driver::Selenium < Capybara::Driver::Base
private
# a reference to the select node if this is an option node
def select_node
find('./ancestor::select').first
end
def type
self[:type]
end

View File

@ -113,22 +113,18 @@ module Capybara
##
#
# Select the given option if the element is a select box
# Select this node if is an option element inside a select tag
#
# @param [String] option The option to select
#
def select_option(option)
base.select_option(option)
def select_option
base.select_option
end
##
#
# Unselect the given option if the element is a select box
# Unselect this node if is an option element inside a multiple select tag
#
# @param [String] option The option to unselect
#
def unselect_option(option)
base.unselect_option(option)
def unselect_option
base.unselect_option
end
##

View File

@ -106,8 +106,10 @@ module Capybara
# @param [String] locator Which check box to uncheck
#
def select(value, options={})
msg = "cannot select option, no select box with id, name, or label '#{options[:from]}' found"
find(:xpath, XPath.select(options[:from]), :message => msg).select_option(value)
no_select_msg = "cannot select option, no select box with id, name, or label '#{options[:from]}' found"
no_option_msg = "cannot select option, no option with text '#{value}' in select box '#{options[:from]}'"
select = find(:xpath, XPath.select(options[:from]), :message => no_select_msg)
select.find(:xpath, XPath.option(value), :message => no_option_msg).select_option
end
##
@ -121,8 +123,10 @@ module Capybara
# @param [String] locator Which check box to uncheck
#
def unselect(value, options={})
msg = "cannot unselect option, no select box with id, name, or label '#{options[:from]}' found"
find(:xpath, XPath.select(options[:from]), :message => msg).unselect_option(value)
no_select_msg = "cannot unselect option, no select box with id, name, or label '#{options[:from]}' found"
no_option_msg = "cannot unselect option, no option with text '#{value}' in select box '#{options[:from]}'"
select = find(:xpath, XPath.select(options[:from]), :message => no_select_msg)
select.find(:xpath, XPath.option(value), :message => no_option_msg).unselect_option
end
##

View File

@ -59,7 +59,7 @@ shared_examples_for "select" do
context "with an option that doesn't exist" do
it "should raise an error" do
running { @session.select('Does not Exist', :from => 'form_locale') }.should raise_error(Capybara::OptionNotFound)
running { @session.select('Does not Exist', :from => 'form_locale') }.should raise_error(Capybara::ElementNotFound)
end
end

View File

@ -47,7 +47,7 @@ shared_examples_for "unselect" do
context "with an option that doesn't exist" do
it "should raise an error" do
running { @session.unselect('Does not Exist', :from => 'form_underwear') }.should raise_error(Capybara::OptionNotFound)
running { @session.unselect('Does not Exist', :from => 'form_underwear') }.should raise_error(Capybara::ElementNotFound)
end
end
end

View File

@ -137,6 +137,10 @@ module Capybara
input_field(:file, locator, options)
end
def option(name)
append(".//option[normalize-space(text())=#{s(name)}]").append(".//option[contains(.,#{s(name)})]")
end
protected
def input_field(type, locator, options={})