diff --git a/lib/capybara.rb b/lib/capybara.rb index 5bdb1379..3ca07809 100644 --- a/lib/capybara.rb +++ b/lib/capybara.rb @@ -8,6 +8,7 @@ module Capybara class DriverNotFoundError < CapybaraError; end class ElementNotFound < CapybaraError; end class OptionNotFound < ElementNotFound; end + class UnselectNotAllowed < CapybaraError; end class NotSupportedByDriverError < CapybaraError; end class TimeoutError < CapybaraError; end class LocateHiddenElementError < CapybaraError; end diff --git a/lib/capybara/driver/rack_test_driver.rb b/lib/capybara/driver/rack_test_driver.rb index 27aacc75..673472a6 100644 --- a/lib/capybara/driver/rack_test_driver.rb +++ b/lib/capybara/driver/rack_test_driver.rb @@ -54,6 +54,20 @@ class Capybara::Driver::RackTest < Capybara::Driver::Base end end + def unselect(option) + if node['multiple'] != 'multiple' + raise Capybara::UnselectNotAllowed, "Cannot unselect option '#{option}' from single select box." + end + + if option_node = node.xpath(".//option[text()='#{option}']").first || + node.xpath(".//option[contains(.,'#{option}')]").first + option_node.remove_attribute('selected') + else + options = node.xpath(".//option").map { |o| "'#{o.text}'" }.join(', ') + raise Capybara::OptionNotFound, "No such option '#{option}' in this select box. Available options: #{options}" + end + end + def click if tag_name == 'a' driver.visit(self[:href].to_s) diff --git a/lib/capybara/node.rb b/lib/capybara/node.rb index f3932f92..acbc610c 100644 --- a/lib/capybara/node.rb +++ b/lib/capybara/node.rb @@ -29,6 +29,10 @@ module Capybara raise NotImplementedError end + def unselect(option) + raise NotImplementedError + end + def click raise NotImplementedError end diff --git a/lib/capybara/session.rb b/lib/capybara/session.rb index e79f24f2..7d4eec6a 100644 --- a/lib/capybara/session.rb +++ b/lib/capybara/session.rb @@ -96,6 +96,11 @@ module Capybara locate(:xpath, XPath.select(options[:from]), msg).select(value) end + def unselect(value, options={}) + msg = "cannot unselect option, no select box with id, name, or label '#{options[:from]}' found" + locate(:xpath, XPath.select(options[:from]), msg).unselect(value) + end + def attach_file(locator, path) msg = "cannot attach file, no file field with id, name, or label '#{locator}' found" locate(:xpath, XPath.file_field(locator), msg).set(path) diff --git a/spec/dsl/unselect_spec.rb b/spec/dsl/unselect_spec.rb new file mode 100644 index 00000000..ad1246a4 --- /dev/null +++ b/spec/dsl/unselect_spec.rb @@ -0,0 +1,48 @@ +shared_examples_for "unselect" do + describe "#unselect" do + before do + @session.visit('/form') + end + + context "with multiple select" do + it "should unselect an option from a select box by id" do + @session.unselect('Commando', :from => 'form_underwear') + @session.click_button('awesome') + extract_results(@session)['underwear'].should include('Briefs', 'Boxer Briefs') + extract_results(@session)['underwear'].should_not include('Commando') + end + + it "should unselect an option from a select box by label" do + @session.unselect('Commando', :from => 'Underwear') + @session.click_button('awesome') + extract_results(@session)['underwear'].should include('Briefs', 'Boxer Briefs') + extract_results(@session)['underwear'].should_not include('Commando') + end + + it "should favour exact matches to option labels" do + @session.unselect("Briefs", :from => 'Underwear') + @session.click_button('awesome') + extract_results(@session)['underwear'].should include('Commando', 'Boxer Briefs') + extract_results(@session)['underwear'].should_not include('Briefs') + end + end + + context "with single select" do + it "should raise an error" do + running { @session.unselect("English", :from => 'form_locale') }.should raise_error(Capybara::UnselectNotAllowed) + end + end + + context "with a locator that doesn't exist" do + it "should raise an error" do + running { @session.unselect('foo', :from => 'does not exist') }.should raise_error(Capybara::ElementNotFound) + end + end + + 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) + end + end + end +end diff --git a/spec/session_spec.rb b/spec/session_spec.rb index 01d31296..bc14a3c0 100644 --- a/spec/session_spec.rb +++ b/spec/session_spec.rb @@ -57,6 +57,7 @@ shared_examples_for "session" do it_should_behave_like "has_field" it_should_behave_like "select" it_should_behave_like "uncheck" + it_should_behave_like "unselect" it_should_behave_like "locate" it_should_behave_like "within" it_should_behave_like "current_url" diff --git a/spec/views/form.erb b/spec/views/form.erb index fe46b7fa..952c4a71 100644 --- a/spec/views/form.erb +++ b/spec/views/form.erb @@ -130,6 +130,16 @@

+

+ + +

+