使用 Capybara 测试多域 Rails 3 应用程序

发布于 2024-10-12 17:28:44 字数 1296 浏览 5 评论 0原文

我想测试我的多域 RoR3 应用程序。

这是我的 test_helper.rb

ENV["RAILS_ENV"] = "test"

require File.expand_path('../../config/environment', __FILE__)
require 'rails/test_help'
require 'capybara/rails'
require 'blueprints'

class ActiveSupport::TestCase

end

class ActionDispatch::IntegrationTest
  include Capybara

  def host
    "http://#{subdomain}.lvh.me:3000"
  end

  def subdomain
    @subdomain ? @subdomain : 'demostore'
  end

  def visit(url)
    super("http://#{subdomain}.lvh.me:3000#{url}")
  end
end

和我的集成测试:

require 'test_helper'

class ProductsTest < ActionDispatch::IntegrationTest

  def setup
    @subdomain = 'demostore'
    # creating stuff
  end

  def teardown
    # deleting stuff
  end

  test "user views product list" do
    visit('/')
    assert page.has_css?('ul.product-listing')
    assert page.has_xpath?("//ul[@class='product-listing']/li", :count => 12)
  end

  test "user views product page" do
    product = Product.first

    visit('/')
    find(:xpath, "//ul[@class='product-listing']/li/a[1]").click
    save_and_open_page
  end

end

我确信链接存在。单击和填充内容时出现问题。

click_link('Existent link title')

也不起作用。

我认为默认的 Capybara 驱动程序 Rack::Test 可能对这个多域的东西有问题?

I want to test my multidomain RoR3 App.

Here's my test_helper.rb

ENV["RAILS_ENV"] = "test"

require File.expand_path('../../config/environment', __FILE__)
require 'rails/test_help'
require 'capybara/rails'
require 'blueprints'

class ActiveSupport::TestCase

end

class ActionDispatch::IntegrationTest
  include Capybara

  def host
    "http://#{subdomain}.lvh.me:3000"
  end

  def subdomain
    @subdomain ? @subdomain : 'demostore'
  end

  def visit(url)
    super("http://#{subdomain}.lvh.me:3000#{url}")
  end
end

And my integration test:

require 'test_helper'

class ProductsTest < ActionDispatch::IntegrationTest

  def setup
    @subdomain = 'demostore'
    # creating stuff
  end

  def teardown
    # deleting stuff
  end

  test "user views product list" do
    visit('/')
    assert page.has_css?('ul.product-listing')
    assert page.has_xpath?("//ul[@class='product-listing']/li", :count => 12)
  end

  test "user views product page" do
    product = Product.first

    visit('/')
    find(:xpath, "//ul[@class='product-listing']/li/a[1]").click
    save_and_open_page
  end

end

And I'm sure the link exists. There is problem with clicking and filling stuff.

click_link('Existent link title')

doesn't work too.

I think the default Capybara's driver Rack::Test could have problems with this multidomain stuff?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(6

月牙弯弯 2024-10-19 17:28:44

在您的设置中,调用该rack::test 函数,这将更改主机的值。嗯,它更改了关于虚假 Web 请求返回的主机。

host! "#{store.subdomain}.example.com"

In your setup, call this rack::test function, which will change your host's value. Well, it changes the host that gets returned about the fake web request.

host! "#{store.subdomain}.example.com"
过期以后 2024-10-19 17:28:44

问题是我正在使用多域的东西,所以我必须使用 lvh.me 来解析 localhost。您可以通过在 /etc/hosts 中进行设置来执行相同的操作

127.0.0.1 subdomain.yourapp.local

,然后使用此域。

我已经用这样的东西覆盖了水豚的访问方法:

def visit(link)
  super("mysubdomain.lvh.me:3000#{link}")
end

但问题仍然存在,因为当水豚单击示例链接时,未使用访问方法并且未请求我的主机。哪一个是?我不知道——可能是默认的。

所以解决方案是在 Capybara 设置中设置主机和端口:

class ActionDispatch::IntegrationTest
  include Capybara

  Capybara.default_host = "subdomain.yourapp.local"
  Capybara.server_port = 3000
  # ... rest of stuff here
end

The problem was that i'm using multidomain stuff so I had to use lvh.me which resolves localhost. You can do the same think by setting in Your /etc/hosts

127.0.0.1 subdomain.yourapp.local

and then use this domain.

I've overwritten Capybara's visit method with sth like that:

def visit(link)
  super("mysubdomain.lvh.me:3000#{link}")
end

but problem persisted because when Capybara clicked for example link, the visit method was not used and my host was not requested. Which was? I don't know - probably the default one.

So solution is to set host and port in Capybara settings:

class ActionDispatch::IntegrationTest
  include Capybara

  Capybara.default_host = "subdomain.yourapp.local"
  Capybara.server_port = 3000
  # ... rest of stuff here
end
祁梦 2024-10-19 17:28:44

显然这是机架测试的问题。

但是 hassox 的一个分支刚刚为我解决了这个问题。
如果您想检查更改是什么,这只是一些真正重要的提交。

这就是我的 Gemfile 的样子:

group :test, :cucumber do
  gem 'rack-test', :git => "https://github.com/hassox/rack-test.git"
  gem 'capybara', '= 0.4.1.2'
  gem 'capybara-envjs', '= 0.4.0'
  gem 'cucumber-rails', '>= 0.3.2'
  gem 'pickle', '>= 0.3.4'
end

然后我只需确保

visit('http://my_subdomain.example.com')

按照我的步骤进行即可。现在我试图了解什么会使 url 助手与子域一起工作。

Apparently it's a problem with rack-test.

But there is a fork of it by hassox that just solved it for me.
It's just a couple of commits that really matter, in case you want to check what the changes are.

This is how my Gemfile looks:

group :test, :cucumber do
  gem 'rack-test', :git => "https://github.com/hassox/rack-test.git"
  gem 'capybara', '= 0.4.1.2'
  gem 'capybara-envjs', '= 0.4.0'
  gem 'cucumber-rails', '>= 0.3.2'
  gem 'pickle', '>= 0.3.4'
end

And then I just make sure to

visit('http://my_subdomain.example.com')

in my steps. Now I'm trying to understand what would make url helpers work with subdomains.

咽泪装欢 2024-10-19 17:28:44

这是一个快速设置,可以帮助您...

rails 3.2+ 使用黄瓜水豚和 pow 设置测试自定义子域:

https: //gist.github.com/4465773

Here's a quick setup that may help you out...

rails 3.2+ testing custom subdomains using cucumber capybara with pow setup:

https://gist.github.com/4465773

方圜几里 2024-10-19 17:28:44

我想分享我发现的这个问题的一个很好的解决方案。它涉及创建一个辅助方法来在 URL 前面添加所需的子域,不会覆盖任何 Capybara 方法,并与 Rack::Test 和 capybara-webkit 驱动程序配合使用。事实上,它甚至可以在不使用 Capybara 的规格中工作。 (来源:http://minimul.com/capybara-and-subdomains.html

Spec Helper 方法

# spec/support/misc.helpers.rb
def hosted_domain(options = {})
  path = options[:path] || "/" # use root path by default
  subdomain = options[:subdomain] || 'www'
  if example.metadata[:js]
    port = Capybara.current_session.driver.server_port
    url = "http://#{ subdomain }.lvh.me:#{ port }#{ path }"
  else
    url = "http://#{ subdomain }.example.com#{ path }"
  end
end


为了说明它的用途,这里有两个示例:

在功能规范中使用(有水豚)

require 'spec_helper'

describe "Accounts" do
  # Creates an account using a factory which sequences
  # account subdomain names
  # Additionally creates users associated with the account
  # using FactoryGirl's after callbacks (see FactoryGir docs)
  let (:account) { FactoryGirl.create(:account_with_users) })

  it "allows users to sign in" do
    visit hosted_domain(path: new_sessions_path, subdomain: account.subdomain)

    user = account.users.first

    fill_in "email", with: user.email
    fill_in "password", with: user.password
    click_button "commit"

    # ... the rest of your specs
  end
end

在请求规范中使用(没有水豚)

#spec/requests/account_management_spec.rb
require "spec_helper"

describe "Account management" do
  # creates an account using a factory which sequences
  # account subdomain names
  let (:account) { FactoryGirl.create(:account) })

  it "shows the login page" do
    get hosted_domain(path: "/login", subdomain: account.subdomain)
    expect(response).to render_template("sessions/new")
  end

end

I'd like to share what I found to be a great solution for this problem. It involves creating a helper method to prepend URLs with the desired subdomain, doesn't overwrite any Capybara methods, and works with the Rack::Test and capybara-webkit drivers. In fact, it will even work in specs which do not even use Capybara. (source: http://minimul.com/capybara-and-subdomains.html)

The Spec Helper Method

# spec/support/misc.helpers.rb
def hosted_domain(options = {})
  path = options[:path] || "/" # use root path by default
  subdomain = options[:subdomain] || 'www'
  if example.metadata[:js]
    port = Capybara.current_session.driver.server_port
    url = "http://#{ subdomain }.lvh.me:#{ port }#{ path }"
  else
    url = "http://#{ subdomain }.example.com#{ path }"
  end
end

And to illustrate it's use, here are two examples:

Used in a Feature Spec (with Capybara)

require 'spec_helper'

describe "Accounts" do
  # Creates an account using a factory which sequences
  # account subdomain names
  # Additionally creates users associated with the account
  # using FactoryGirl's after callbacks (see FactoryGir docs)
  let (:account) { FactoryGirl.create(:account_with_users) })

  it "allows users to sign in" do
    visit hosted_domain(path: new_sessions_path, subdomain: account.subdomain)

    user = account.users.first

    fill_in "email", with: user.email
    fill_in "password", with: user.password
    click_button "commit"

    # ... the rest of your specs
  end
end

Used in a Request Spec (without Capybara)

#spec/requests/account_management_spec.rb
require "spec_helper"

describe "Account management" do
  # creates an account using a factory which sequences
  # account subdomain names
  let (:account) { FactoryGirl.create(:account) })

  it "shows the login page" do
    get hosted_domain(path: "/login", subdomain: account.subdomain)
    expect(response).to render_template("sessions/new")
  end

end
圈圈圆圆圈圈 2024-10-19 17:28:44

一个简单而干净的解决方案是覆盖您提供给 Capybara 的访问方法的 url。它与 *.lvh.me 域配合得很好,它会将您重定向到本地主机:

describe "Something" do

  def with_subdomain(link)
    "http://subdomain.lvh.me:3000#{link}"
  end

  it "should do something" do
    visit with_subdomain(some_path)
  end

end

或者您可以通过在规范之前重新定义 app_host 来执行相同的操作:

Capybara.app_host = 'http://sudbomain.lvh.me:3000'
..
visit(some_path)

A simple and clean solution is to override the urls you provide to Capybara's visit method. It works well with *.lvh.me domains, which will redirect you to localhost:

describe "Something" do

  def with_subdomain(link)
    "http://subdomain.lvh.me:3000#{link}"
  end

  it "should do something" do
    visit with_subdomain(some_path)
  end

end

Or you could do the same by redefining app_host before a spec:

Capybara.app_host = 'http://sudbomain.lvh.me:3000'
..
visit(some_path)
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文