如何使用Rspec和Capybara测试重定向

Moh*_*mad 22 ruby rspec ruby-on-rails capybara

我不知道我做错了什么,但每当我尝试测试重定向时,我都会收到此错误:"@request必须是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)>'
Run Code Online (Sandbox Code Playgroud)

我正在使用带有Capybara(1.1.2)和Rails 3.2的RSpec-rails(2.9.0).如果有人能解释为什么会这样,我将不胜感激; 为什么我不能以这种方式使用期望?

Sag*_*fek 38

Capybara不是特定于rails的解决方案,所以它对rails的渲染逻辑一无所知.

Capybara专门用于集成测试,它实质上是从最终用户与浏览器交互的角度运行测试.在这些测试中,您不应该断言模板,因为最终用户无法深入了解您的应用程序.你应该测试的是一个动作让你走上正确的道路.

current_path.should == new_user_path
page.should have_selector('div#erro_div')
Run Code Online (Sandbox Code Playgroud)

  • 对于较新版本的 Capybara,这不再有效。我有 2.10.1 并且有一个新方法 `have_current_path` 可以使用:`expect(page).to have_current_path(new_user_path)` (2认同)

The*_* Oz 16

你可以这样做:

expect(current_path).to eql(new_app_user_registration_path)
Run Code Online (Sandbox Code Playgroud)


Art*_*rov 11

错误消息@request must be an ActionDispatch::Request告诉您rspec-rails匹配器redirect_to(它委托给Rails assert_redirected_to)期望它在Rails功能测试中使用(应该混入ActionController::TestCase).您发布的代码看起来像rspec-rails请求规范.所以redirect_to不可用.

rspec-rails请求规范不支持检查重定向,但Rails集成测试支持.

是否应该明确检查重定向是如何进行的(它是301响应而不是307响应而不是某些javascript)完全取决于您.


Zip*_*pie 11

Rspec 3:

测试当前路径的最简单方法是:

expect(page).to have_current_path('/login?status=invalid_token')

have_current_path拥有这种方法的优点:

expect(current_path).to eq('/login')

因为你可以包含查询参数.


Max*_*Max 5

这是我发现的hackish解决方案

# 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
Run Code Online (Sandbox Code Playgroud)

  • 如果您的重定向恰好是外部链接,这会有所帮助 (2认同)