diff --git a/lib/capybara.rb b/lib/capybara.rb index 3cfd2988..f39de404 100644 --- a/lib/capybara.rb +++ b/lib/capybara.rb @@ -212,6 +212,7 @@ Capybara.configure do |config| config.default_wait_time = 2 config.ignore_hidden_elements = false config.prefer_visible_elements = true + config.default_host = "http://www.example.com" end Capybara.register_driver :rack_test do |app| diff --git a/lib/capybara/driver/rack_test_driver.rb b/lib/capybara/driver/rack_test_driver.rb index 09df7e3f..dacfdf17 100644 --- a/lib/capybara/driver/rack_test_driver.rb +++ b/lib/capybara/driver/rack_test_driver.rb @@ -56,7 +56,7 @@ class Capybara::Driver::RackTest < Capybara::Driver::Base def click if tag_name == 'a' method = self["data-method"] || :get - driver.process(method, self[:href].to_s) + driver.follow(method, self[:href].to_s) elsif (tag_name == 'input' and %w(submit image).include?(type)) or ((tag_name == 'button') and type.nil? or type == "submit") Form.new(driver, form).submit(self) @@ -190,6 +190,7 @@ class Capybara::Driver::RackTest < Capybara::Driver::Base include ::Rack::Test::Methods attr_reader :app + attr_accessor :current_host alias_method :response, :last_response alias_method :request, :last_request @@ -200,16 +201,39 @@ class Capybara::Driver::RackTest < Capybara::Driver::Base end def visit(path, attributes = {}) + reset_host! process(:get, path, attributes) end + def submit(method, path, attributes) + path = request_path if not path or path.empty? + process(method, path, attributes) + end + + def follow(method, path, attributes = {}) + return if path.gsub(/^#{request_path}/, '').start_with?('#') + process(method, path, attributes) + end + def process(method, path, attributes = {}) - return if path.gsub(/^#{request_path}/, '') =~ /^#/ - path = request_path + path if path =~ /^\?/ + new_uri = URI.parse(path) + current_uri = URI.parse(current_url) + + path = request_path + path if path.start_with?('?') + path = current_host + path if path.start_with?('/') + + if new_uri.host + @current_host = new_uri.scheme + '://' + new_uri.host + end + send(method, to_binary(path), to_binary( attributes ), env) follow_redirects! end + def reset_host! + @current_host = (Capybara.app_host || Capybara.default_host) + end + def current_url request.url rescue "" end @@ -236,12 +260,6 @@ class Capybara::Driver::RackTest < Capybara::Driver::Base end end - def submit(method, path, attributes) - path = request_path if not path or path.empty? - send(method, to_binary(path), to_binary(attributes), env) - follow_redirects! - end - def find(selector) html.xpath(selector).map { |node| Node.new(self, node) } end @@ -256,6 +274,7 @@ class Capybara::Driver::RackTest < Capybara::Driver::Base alias_method :source, :body def reset! + reset_host! clear_rack_mock_session end @@ -278,10 +297,6 @@ private @html = nil end - def build_rack_mock_session # :nodoc: - Rack::MockSession.new(app, Capybara.default_host || "www.example.com") - end - # Rack::Test::Methods does not provide methods for manipulating the session # list so these must be manipulated directly. def clear_rack_mock_session diff --git a/lib/capybara/session.rb b/lib/capybara/session.rb index 6098c4ff..e57d2090 100644 --- a/lib/capybara/session.rb +++ b/lib/capybara/session.rb @@ -112,7 +112,8 @@ module Capybara # @return [String] Host of the current page # def current_host - URI.parse(current_url).host + uri = URI.parse(current_url) + "#{uri.scheme}://#{uri.host}" end ## diff --git a/lib/capybara/spec/session/current_host_spec.rb b/lib/capybara/spec/session/current_host_spec.rb index 3f19a81a..136f6198 100644 --- a/lib/capybara/spec/session/current_host_spec.rb +++ b/lib/capybara/spec/session/current_host_spec.rb @@ -1,9 +1,61 @@ shared_examples_for "current_host" do + after do + Capybara.app_host = nil + end + describe '#current_host' do it "is affected by visiting a page directly" do - @session.visit('http://capybara-testapp.heroku.com/') - @session.body.should include('Hello world') - @session.current_host.should == 'capybara-testapp.heroku.com' + @session.visit('http://capybara-testapp.heroku.com/host') + @session.body.should include('Current host is http://capybara-testapp.heroku.com') + @session.current_host.should == 'http://capybara-testapp.heroku.com' + end + + it "returns to the default host when visiting a relative url" do + @session.visit('http://capybara-testapp.heroku.com/host') + @session.body.should include('Current host is capybara-testapp.heroku.com') + @session.current_host.should == 'http://capybara-testapp.heroku.com' + @session.visit('/host') + @session.body.should include('Current host is http://www.example.com') + @session.current_host.should == 'http://www.example.com' + end + + it "is affected by setting Capybara.app_host" do + Capybara.app_host = "http://capybara-testapp.heroku.com" + @session.visit('/host') + @session.body.should include('Current host is http://capybara-testapp.heroku.com') + @session.current_host.should == 'http://capybara-testapp.heroku.com' + Capybara.app_host = "http://capybara1.elabs.se" + @session.visit('/host') + @session.body.should include('Current host is http://capybara1.elabs.se') + @session.current_host.should == 'http://capybara1.elabs.se' + end + + it "is unaffected by following a relative link" do + @session.visit('http://capybara-testapp.heroku.com/host_links') + @session.click_link('Relative Host') + @session.body.should include('Current host is http://capybara-testapp.heroku.com') + @session.current_host.should == 'http://capybara-testapp.heroku.com' + end + + it "is affected by following an absolute link" do + @session.visit('http://capybara-testapp.heroku.com/host_links') + @session.click_link('Absolute Host') + @session.body.should include('Current host is http://capybara2.elabs.se') + @session.current_host.should == 'http://capybara2.elabs.se' + end + + it "is unaffected by posting through a relative form" do + @session.visit('http://capybara-testapp.heroku.com/host_links') + @session.click_button('Relative Host') + @session.body.should include('Current host is http://capybara-testapp.heroku.com') + @session.current_host.should == 'http://capybara-testapp.heroku.com' + end + + it "is affected by posting through an absolute form" do + @session.visit('http://capybara-testapp.heroku.com/host_links') + @session.click_button('Absolute Host') + @session.body.should include('Current host is http://capybara2.elabs.se') + @session.current_host.should == 'http://capybara2.elabs.se' end end end diff --git a/lib/capybara/spec/test_app.rb b/lib/capybara/spec/test_app.rb index 394e9ed0..d66f7bb2 100644 --- a/lib/capybara/spec/test_app.rb +++ b/lib/capybara/spec/test_app.rb @@ -22,6 +22,10 @@ class TestApp < Sinatra::Base redirect '/landed' end + get '/host' do + "Current host is #{request.domain}" + end + get '/redirect/:times/times' do times = params[:times].to_i if times.zero? diff --git a/lib/capybara/spec/views/host_links.erb b/lib/capybara/spec/views/host_links.erb new file mode 100644 index 00000000..b57a865f --- /dev/null +++ b/lib/capybara/spec/views/host_links.erb @@ -0,0 +1,12 @@ +

+ Relative Host + Absolute Host +

+ +
+

+
+ +
+

+