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

pdg*_*137 7 ruby rspec ruby-on-rails capybara poltergeist

如果我url_for在功能规范中调用,它将返回以http://www.example.com/开头的绝对URL .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"
Run Code Online (Sandbox Code Playgroud)

运行以下命令:

bundle
rails new myapp -O
cd myapp
rm Gemfile Gemfile.lock
rails generate controller Test test
rails generate rspec:install
mkdir spec/features
Run Code Online (Sandbox Code Playgroud)

注释掉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
Run Code Online (Sandbox Code Playgroud)

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

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

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

从RSpec示例调用ActionDispatch :: Routing :: UrlFor.url_for.它only_path违约是假的.

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

通过添加www.example.com为默认主机,对rspec-rails gem的这种提交可能导致了这个问题.关于为什么这个主机是一个合适/有用的选择,没有任何解释.

Ale*_*hey 5

出现此问题的原因如下:

  1. 您正在使用Poltergeist,它使用PhantomJS,它完全能够打开任何URL。
  2. 您正在使用url_for辅助程序,该辅助程序需要知道应该为其生成url的域。当在Rails视图或控制器中使用时,Rails会根据用于发出请求的内容来提供域。当在视图或控制器之外时(例如在ActionMailer或Capybara测试中),域是未知的。Capybara将未知域默认为example.com。

因此,一切都按预期方式进行。现在,它恰巧不是您希望它工作的方式。但是,如果您希望它正常工作,则应执行以下操作之一:

  1. 使用path_onlyurl_for中的选项来告诉它不要使用主机部分。
  2. 使用hosturl_for中的选项来指定正确的主机。

  • 这是不令人满意的,因为在视图或控制器中,“ only_path”默认为true,并且一切都按预期工作。但在规范中,将其修改为默认为false。为什么规范中有这种特殊行为,似乎只能破坏事物?是的,在这个简单的示例中,我当然可以添加“ only_path:true”,但是我最终希望能够调用自己的帮助器方法,而这些方法又会调用“ url_for”;我被迫执行您的策略是编写这些方法的替代版本,仅用于测试。 (3认同)

Aar*_*n K 1

这就是这些宝石的工作原理。这http://example.com与您的应用程序无关。一般来说,您的应用程序中不应该有完全硬编码的路径。Rails 尝试确定您的本地域(对于规范,这是example.com,它是可配置的)并从中创建路径。

这里的想法是你有一个可能会改变的基本 URL。比如说,对于暂存,我使用 Heroku 本地应用程序:randomname-123-staging.heroku.com。我的网址将以此为前缀。然而,在生产中我拥有一个域名。我的网址将以mydomain.com. 对于我来说,必须根据环境基域更新所有 URL 是没有意义的;这应该(并且确实)由 Rails 提供。

通过使用通用域(应该保证不会解析为真实 IP ),规范可以帮助您针对这种可能性进行编码。