Ruby-on-rails 如何使用 Rspec 和 Capybara 测试重定向
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/10955474/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to test for a redirect with Rspec and Capybara
提问by Mohamad
I don't know what I'm doing wrong, but every time I try to test for a redirect, I get this error: "@request must be an ActionDispatch::Request"
我不知道我做错了什么,但是每次我尝试测试重定向时,都会收到此错误:“@request must be an ActionDispatch::Request”
context "as non-signed in user" do
it "should redirect to the login page" do
expect { visit admin_account_url(account, host: get_host(account)) }.to redirect_to(signin_path)
end
end
1) AdminAccountPages Admin::Accounts#show as non-signed in user should redirect to the login page
Failure/Error: expect { visit admin_account_url(account, host: get_host(account)) }.to redirect_to(signin_path)
ArgumentError:
@request must be an ActionDispatch::Request
# ./spec/requests/admin_account_pages_spec.rb:16:in `block (4 levels) in <top (required)>'
I'm using RSpec-rails (2.9.0) with Capybara (1.1.2) and Rails 3.2. I would appreciate it if someone could also explain why this is happening; why can't I use the expect in such a way?
我将 RSpec-rails (2.9.0) 与 Capybara (1.1.2) 和 Rails 3.2 一起使用。如果有人也能解释为什么会发生这种情况,我将不胜感激;为什么我不能以这种方式使用期望?
回答by Sagiv Ofek
Capybara is not a rails-specific solution so it doesn't know anything about rails's rendering logic.
Capybara 不是特定于 rails 的解决方案,因此它对 rails 的渲染逻辑一无所知。
Capybara is meant specifically for Integration testing, which is essentially running tests from the viewpoint of an end-user interacting with a browser. In these tests, you should not be asserting templates because an end-user can't see that deep into your application. What you should instead be testing is that an action lands you on the correct path.
Capybara 专门用于集成测试,它本质上是从与浏览器交互的最终用户的角度运行测试。在这些测试中,您不应断言模板,因为最终用户无法深入了解您的应用程序。相反,您应该测试的是某个动作是否让您走上了正确的道路。
current_path.should == new_user_path
page.should have_selector('div#erro_div')
回答by The Whiz of Oz
you can do it this way:
你可以这样做:
expect(current_path).to eql(new_app_user_registration_path)
回答by Zippie
Rspec 3:
规格 3:
The easiest way to test for the current path is with:
测试当前路径的最简单方法是:
expect(page).to have_current_path('/login?status=invalid_token')
expect(page).to have_current_path('/login?status=invalid_token')
The have_current_pathhas an advantage over this approach:
在have_current_path拥有这种方法的优点:
expect(current_path).to eq('/login')
expect(current_path).to eq('/login')
because you can include query params.
因为您可以包含查询参数。
回答by Art Shayderov
The error message @request must be an ActionDispatch::Requesttells you that rspec-rails matcher redirect_to(it delegates to Rails assert_redirected_to) expects it to be used in Rails functional tests (should mix in ActionController::TestCase). The code you posted looks like rspec-rails request spec. So redirect_tois not available.
错误消息@request must be an ActionDispatch::Request告诉您 rspec-rails 匹配器redirect_to(它委托给 Rails assert_redirected_to)期望它在 Rails 功能测试中使用(应该混合使用ActionController::TestCase)。您发布的代码看起来像 rspec-rails 请求规范。所以redirect_to不可用。
Checking for redirect is not supported in rspec-rails request specs, but is supported in Rails integration tests.
rspec-rails 请求规范不支持检查重定向,但 Rails 集成测试支持。
Whether you should explicitly check for how redirect was made (that it is was a 301 response and not a 307 response and not some javascript) is completely up to you.
您是否应该明确检查重定向是如何进行的(它是 301 响应而不是 307 响应而不是某些 javascript)完全取决于您。
回答by Max
Here is hackish solution that i found
这是我发现的骇人听闻的解决方案
# spec/features/user_confirmation_feature.rb
feature 'User confirmation' do
scenario 'provide confirmation and redirect' do
visit "/users/123/confirm"
expect(page).to have_content('Please enter the confirmation code')
find("input[id$='confirmation_code']").set '1234'
do_not_follow_redirect do
click_button('Verify')
expect(page.driver.status_code).to eq(302)
expect(page.driver.browser.last_response['Location']).to match(/\/en\//[^\/]+\/edit$/)
end
end
protected
# Capybara won't follow redirects
def do_not_follow_redirect &block
begin
options = page.driver.instance_variable_get(:@options)
prev_value = options[:follow_redirects]
options[:follow_redirects] = false
yield
ensure
options[:follow_redirects] = prev_value
end
end
end

