Rails,Capybara和子域名:如何访问某些子域名

时间:2010-11-18 17:51:40

标签: ruby-on-rails-3 cucumber integration-testing capybara subdomain

Rails 3,Cucumber 0.9.4,Capybara 0.4.0

我想用子域测试我的功能。我找到了解决方案:

Given /^I visit subdomain "(.+)"$/ do |sub|
  Capybara.default_host = "#{sub}.example.com" #for Rack::Test
  Capybara.app_host = "http://#{sub}.example.com:9887" if Capybara.current_driver == :culerity
end

如果我运行cucumber features/subdomain.feature,它会起作用,但如果我运行cucumber features则会失败!这是令人难以置信的,但这是真的。我记录了当前网址,subdomain.example.comcucumber features/subdomain.featurewww.example.comcucumber features,其中一个方案为

Scenario: subdomain scenario
  Given I visit subdomain "subdomain"

在这两种情况下!

我不知道原因......

有没有最好的方法来测试带有水豚的子域?

3 个答案:

答案 0 :(得分:13)

好的,这里应该是一个相当简单易懂的Capybara黑客产生所需的行为,即每次切换子域时都能创建一个新的会话。这对于用户在一个域上注册(导致为其帐户创建子域)的站点非常有用,然后最终需要导航到该子域。

首先(这部分与其他解决方案相当普遍)继续并给自己一个方法来改变Cucumber步骤中的Capybara.default_host。我是这样做的:

Then /^I switch the subdomain to (\w+)$/ do |s|
  Capybara.default_host = "#{s}.smackaho.st"
end

将此步骤粘贴到您希望使用新子域的位置的黄瓜功能中。例如:

When I open the email
Then I should see "http://acme.rightbonus.com/users/confirmation" in the email body

Given I switch the subdomain to acme
When I follow "Click here to finish setting up your account" in the email
Then I should be on the user confirmation page for acme

现在进行神奇的monkeypatching使这项工作。基本上,您希望Capybara足够智能,以检测子域何时发生更改并重置其RackTest会话对象。

# features/support/capybara.rb

class Capybara::Driver::RackTest
  # keep track of the default host you started with
  def initialize(app)
    raise ArgumentError,
      "rack-test requires a rack application, but none was given" unless app
    @app = app
    @default_host = Capybara.default_host
  end

  def process(method, path, attributes = {})
    reset_if_host_has_changed
    path = ["http://", @default_host, path].join
    return if path.gsub(/^#{request_path}/, '') =~ /^#/
    path = request_path + path if path =~ /^\?/
    send(method, to_binary(path), to_binary( attributes ), env)
    follow_redirects!
  end

  private

  def build_rack_mock_session # :nodoc:
    puts "building a new Rack::MockSession for " + Capybara.default_host
    Rack::MockSession.new(app, Capybara.default_host || "www.example.com")
  end

  def reset_if_host_has_changed
    if @default_host != Capybara.default_host
      reset! # clears the existing MockSession
      @default_host = Capybara.default_host
    end
  end
end

此补丁适用于Capybara 0.4.1.1,除非经过修改,否则可能不适用于不同的版本。祝你好运。

答案 1 :(得分:5)

如果您的需求不包含任何与会话相关的内容,并且您所访问的所有内容都访问了不同的子域名,那么我写了这个函数:

def visit_with_subdomain(uri, options = {})
  domain = Capybara.default_host
  port = Capybara.server_port
  subdomain = options[:subdomain]
  visit "http://#{subdomain}.#{domain}:#{port}#{uri}"
end

您可以这样称呼它:

visit_with_subdomain some_path, subdomain: some_subdomain

答案 2 :(得分:1)

有同样的问题,我的测试有时必须在子域之间来回切换或重定向。

给出这一步:

When /^(?:|I )go to "(.+)"$/ do |url|
  visit url
end

When I go to "http://mysubdomain.example.org"适用于机架测试,但如果您被应用程序重定向或按照指向其他路径的链接,则主机将恢复为default_host。

hassox有一个fork of rack-test可确保机架测试跟踪上一个请求中使用的主机。

所以,在我的Gemfile中,在要求capybara之前:

  gem 'rack-test', :git => "https://github.com/hassox/rack-test.git"

现在,如果我需要点击特定的子域名(或者应用程序将我重定向到一个,例如 secure.myapp.com/sign_in ),我确信该功能可以更像浏览器会表现出来:它会让我留在当前的子域名,直到我使用capybara的visit("somesubdomain.example.org") - 或者被应用程序重定向到其他主机。