在Rails / Capybara / Poltergeist规范中使用url_for将驱动程序发送到example.com而不是app

时间:2014-04-18 23:18:45

标签: ruby-on-rails ruby rspec capybara poltergeist

如果我在功能规范中调用url_for,则会返回以http://www.example.com/开头的绝对网址。 Capybara很乐意尝试在该网站上加载页面,但这与我的应用程序无关。以下是重现问题的最小步骤:

从这个Gemfile开始:

source 'https://rubygems.org'

gem "sqlite3"
gem "jquery-rails"
gem "draper"
gem "rails", '4.1.0'
gem "therubyracer"
gem "uglifier"
gem "rspec-rails"
gem "capybara"
gem "poltergeist"
gem "launchy"

运行以下命令:

bundle
rails new myapp -O
cd myapp
rm Gemfile Gemfile.lock
rails generate controller Test test
rails generate rspec:install
mkdir spec/features

注释spec/spec_helper.rb中的行,表示不使用ActiveRecord时应将其删除,然后使用以下内容创建spec/features/feature_spec.rb

require 'capybara/poltergeist'

Capybara.configure do |config|
  config.javascript_driver = :poltergeist
end

require 'spec_helper'

describe "nothing", js: true do
  specify do
    visit(url_for(controller: :test, action: :test))
    save_and_open_page
  end
end

最后,运行rake spec,您将看到在浏览器中弹出example.com页面。我已将此行为验证回Rails 3.2.17。

为什么会发生这种情况,是否有办法获取正在测试的应用的网址而不是example.com?

编辑:我发现的一些事情更多:

从RSpec示例调用

ActionDispatch::Routing::UrlFor.url_for。它有only_path默认为false。

ActionView::RoutingUrlFor是您获得的版本,例如视图。它有only_path默认为true,效果更好。

通过添加www.example.com作为默认主机,

This commit到rspec-rails gem可能会导致问题。关于为什么这个主机是一个合适/有用的选择,没有任何解释。

2 个答案:

答案 0 :(得分:4)

问题表现出以下原因:

  1. 您使用的是使用PhantomJS的Poltergeist,它完全可以打开任何网址。
  2. 您正在使用url_for帮助程序,它需要知道应该为其生成URL的域。在Rails视图或控制器中使用时,Rails会根据用于发出请求的内容提供域。当在视图或控制器之外时,例如在ActionMailer或Capybara测试中,域名是未知的。 Capybara将未知域名默认为example.com。
  3. 所以一切都按照应有的方式运作。现在,它恰好不是您想要它的工作方式。但是,如果您希望它按照您的方式工作,您应该执行以下操作之一:

    1. 使用url_for中的path_only选项告诉它不要使用主机部分。
    2. 使用url_for中的host选项指定正确的主机。

答案 1 :(得分:1)

这就是这些宝石的工作方式。 http://example.com与您的应用无关。通常,您的应用中不应该有完全硬编码的路径。 Rails尝试确定您的本地域(对于规范example.com,这是可配置的)并创建路径。

这里的想法是你有一个可能会改变的基本URL。比如,对于暂存我使用Heroku本地应用程序:randomname-123-staging.heroku.com。我的网址将以此为前缀。但是,在制作中我拥有一个域名。我的网址将以mydomain.com开头。我不得不根据环境基础域更新所有URL;这应该是由Rails提供的。

通过使用通用域supposed to be guaranteed to not resolve to a real IP,规范可以帮助您编写这种可能性。