14

Rails 3,黄瓜 0.9.4,水豚 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.com适用于一个场景cucumber features/subdomain.featurewww.example.comcucumber features

Scenario: subdomain scenario
  Given I visit subdomain "subdomain"

在这两种情况下!

我不知道原因...

有没有用 capybara 测试子域的最佳方法?

4

3 回答 3

13

Okay, here is what should be a fairly straightforward and easy to understand hack of Capybara that yields the desired behavior, namely to be able to create a new session each time you switch subdomains. This is useful for sites where a user registers on one domain (which results in a subdomain being created for his account) and then ends up needing to navigate over to that subdomain.

First of all (and this part is fairly common to the other solutions out there) go ahead and give yourself a way to change Capybara.default_host in a Cucumber step. I did it like this:

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

Stick this step into your Cucumber feature at the point where you want the new subdomain to be used. For example:

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

Now for the magical monkeypatching that makes this work. Basically, you want Capybara to be smart enough to detect when the subdomain has changed and reset its RackTest session object.

# 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

This patch works with Capybara 0.4.1.1 and will probably not work with different versions unless modified. Good luck.

于 2011-02-21T06:05:54.920 回答
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
于 2013-03-29T20:53:49.130 回答
1

遇到了同样的问题,我的测试有时不得不在子域之间来回切换或重定向。

鉴于此步骤:

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

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

hassox有一个rack-test的分支,可确保 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")应用程序重定向到不同的主机。

于 2011-04-10T08:10:19.377 回答