diff --git a/README.rdoc b/README.rdoc index e8ac7481..4c0a344a 100644 --- a/README.rdoc +++ b/README.rdoc @@ -372,6 +372,7 @@ The following people have dedicated their time and effort to Capybara: * Joseph Wilk * Matt Wynne * Piotr Sarnacki +* Pavel Gabriel == License: diff --git a/lib/capybara.rb b/lib/capybara.rb index 5bdb1379..0e5e9b7f 100644 --- a/lib/capybara.rb +++ b/lib/capybara.rb @@ -14,7 +14,7 @@ module Capybara class InfiniteRedirectError < TimeoutError; end class << self - attr_accessor :debug, :asset_root, :app_host, :run_server + attr_accessor :debug, :asset_root, :app_host, :run_server, :default_host attr_accessor :default_selector, :default_wait_time, :ignore_hidden_elements def default_selector diff --git a/lib/capybara/driver/rack_test_driver.rb b/lib/capybara/driver/rack_test_driver.rb index 1e9f0755..900bcf92 100644 --- a/lib/capybara/driver/rack_test_driver.rb +++ b/lib/capybara/driver/rack_test_driver.rb @@ -39,7 +39,10 @@ class Capybara::Driver::RackTest < Capybara::Driver::Base end def select(option) - node.xpath(".//option[@selected]").each { |node| node.remove_attribute("selected") } + if node['multiple'] != 'multiple' + node.xpath(".//option[@selected]").each { |node| node.remove_attribute("selected") } + end + if option_node = node.xpath(".//option[text()='#{option}']").first || node.xpath(".//option[contains(.,'#{option}')]").first option_node["selected"] = 'selected' @@ -93,9 +96,16 @@ class Capybara::Driver::RackTest < Capybara::Driver::Base merge_param!(params, input['name'].to_s, input['value'].to_s) if input['checked'] end node.xpath(".//select").map do |select| - option = select.xpath(".//option[@selected]").first - option ||= select.xpath('.//option').first - merge_param!(params, select['name'].to_s, (option['value'] || option.text).to_s) if option + if select['multiple'] == 'multiple' + options = select.xpath(".//option[@selected]") + options.each do |option| + merge_param!(params, select['name'].to_s, (option['value'] || option.text).to_s) + end + else + option = select.xpath(".//option[@selected]").first + option ||= select.xpath('.//option').first + merge_param!(params, select['name'].to_s, (option['value'] || option.text).to_s) if option + end end node.xpath(".//input[@type='file']").map do |input| unless input['value'].to_s.empty? @@ -179,6 +189,10 @@ class Capybara::Driver::RackTest < Capybara::Driver::Base private + def build_rack_mock_session # :nodoc: + Rack::MockSession.new(app, Capybara.default_host) + end + def current_path request.path rescue "" end diff --git a/lib/capybara/rails.rb b/lib/capybara/rails.rb index 2911d60d..1313c471 100644 --- a/lib/capybara/rails.rb +++ b/lib/capybara/rails.rb @@ -9,3 +9,4 @@ Capybara.app = Rack::Builder.new do end.to_app Capybara.asset_root = Rails.root.join('public') +Capybara.default_host = "http://test.host" diff --git a/lib/capybara/session.rb b/lib/capybara/session.rb index 68be4adf..e79f24f2 100644 --- a/lib/capybara/session.rb +++ b/lib/capybara/session.rb @@ -113,9 +113,12 @@ module Capybara kind, scope = Capybara.default_selector, kind unless scope scope = XPath.from_css(scope) if kind == :css locate(:xpath, scope, "scope '#{scope}' not found on page") - scopes.push(scope) - yield - scopes.pop + begin + scopes.push(scope) + yield + ensure + scopes.pop + end end def within_fieldset(locator) diff --git a/spec/dsl/select_spec.rb b/spec/dsl/select_spec.rb index cdadf26f..994da94d 100644 --- a/spec/dsl/select_spec.rb +++ b/spec/dsl/select_spec.rb @@ -42,5 +42,20 @@ shared_examples_for "select" do running { @session.select('Does not Exist', :from => 'form_locale') }.should raise_error(Capybara::OptionNotFound) end end + + context "with multiple select" do + it "should select one option" do + @session.select("Ruby", :from => 'Language') + @session.click_button('awesome') + extract_results(@session)['languages'].should == ['Ruby'] + end + + it "should select multiple options" do + @session.select("Ruby", :from => 'Language') + @session.select("Javascript", :from => 'Language') + @session.click_button('awesome') + extract_results(@session)['languages'].should include('Ruby', 'Javascript') + end + end end end diff --git a/spec/dsl/within_spec.rb b/spec/dsl/within_spec.rb index ef1a0654..69eb68fb 100644 --- a/spec/dsl/within_spec.rb +++ b/spec/dsl/within_spec.rb @@ -76,6 +76,19 @@ shared_examples_for "within" do end }.should raise_error(Capybara::ElementNotFound) end + + it "should restore the scope when an error is raised" do + running { + @session.within("//div[@id='for_bar']") do + running { + running { + @session.within("//div[@id='doesnotexist']") do + end + }.should raise_error(Capybara::ElementNotFound) + }.should_not change { @session.has_xpath?("//div[@id='another_foo']") }.from(false) + end + }.should_not change { @session.has_xpath?("//div[@id='another_foo']") }.from(true) + end end context "with forms" do diff --git a/spec/views/form.erb b/spec/views/form.erb index 8dfca239..df4ca967 100644 --- a/spec/views/form.erb +++ b/spec/views/form.erb @@ -120,6 +120,16 @@
++ + +
+