Rspec Capybara - 登录(用户)无法正常工作

joe*_*k16 4 rspec ruby-on-rails

你好我有一个Rspec/Capybara测试即时尝试.

我是一个登录用户,作为管理员用户应该是向我的应用添加大小的唯一用户.

我只是无法测试登录用户.谁能明白为什么?

请查看下面的会话控制器.我有一个log_in方法.

错误是

Failures:

  1) adding size allow a admin user to add a size
     Failure/Error: log_in(admin)
     NoMethodError:
       undefined method `log_in' for #<RSpec::ExampleGroups::AddingSize:0x007f8e4fa828e0>
     # ./spec/features/sizes_features.rb:9:in `block (2 levels) in <top (required)>'
Run Code Online (Sandbox Code Playgroud)

测试

require "rails_helper"
RSpec.feature "adding size" do 

    let(:size01) { FactoryGirl.build :size01 }
    let(:user) { FactoryGirl.build :user }
    let(:admin) { FactoryGirl.create(:user, admin: true) }

    scenario "allow a admin user to add a size" do
        log_in(admin)
        size = create(:size01)
        visit new_size_path
        fill_in 'Title', with: "example"
        click_button 'Create Size'
        expect(current_path).to eql(sizes_path)
        expect(page).to have_content("example")
    end

    scenario "user can't add size" do
        log_in(user)
        visit sizes_path    
        expect(current_path).to eql(root_path)
        expect(page).to have_content("Rescricted Web Page")
    end

    scenario "vistor can't add size" do
        visit sizes_path    
        expect(current_path).to eql(root_path)
    end

end
Run Code Online (Sandbox Code Playgroud)

工厂女工

FactoryGirl.define do

  factory :user, :class => User do
        username "example" 
        email "example@example.com" 
        admin "false" 
        password_digest "<%= User.digest('password') %>"
      activated "true"
      activated_at "<%= Time.zone.now %>"
  end

end
Run Code Online (Sandbox Code Playgroud)

会话控制器.

module SessionsHelper

  # Logs in the given user.
  def log_in(user)
    session[:user_id] = user.id
  end

  # Returns the user corresponding to the remember token cookie.
  def current_user
    if (user_id = session[:user_id])
      @current_user ||= User.find_by(id: user_id)
    elsif (user_id = cookies.signed[:user_id])
      user = User.find_by(id: user_id)
      if user && user.authenticated?(:remember, cookies[:remember_token])
        log_in user
        @current_user = user
      end
    end
  end

  # Returns true if the user is logged in, false otherwise.
  def logged_in?
    !current_user.nil?
  end

  # Logs out the current user.
  def log_out
    session.delete(:user_id)
    @current_user = nil
  end

  # Remembers a user in a persistent session.
  def remember(user)
    user.remember
    cookies.permanent.signed[:user_id] = user.id
    cookies.permanent[:remember_token] = user.remember_token
  end

  # Returns true if the given user is the current user.
  def current_user?(user)
    user == current_user
  end

  # Forgets a persistent session.
  def forget(user)
    user.forget
    cookies.delete(:user_id)
    cookies.delete(:remember_token)
  end

  # Logs out the current user.
  def log_out
    forget(current_user)
    session.delete(:user_id)
    @current_user = nil
  end

  # Redirects to stored location (or to the default).
  def redirect_back_or(default)
    redirect_to(session[:forwarding_url] || default)
    session.delete(:forwarding_url)
  end

  # Stores the URL trying to be accessed.
  def store_location
    session[:forwarding_url] = request.url if request.get?
  end

end
Run Code Online (Sandbox Code Playgroud)

mad*_*cow 6

这就是为什么它不起作用:

无法通过测试访问会话和请求,访问响应受到限制.某些驱动程序允许访问响应标头和HTTP状态代码,但某些驱动程序(如Selenium)不提供此类功能.

来源:Capybara文档

您有两种选择:

  1. 如果您使用Devise进行身份验证,Devise会提供您应该使用的身份验证帮助程序.

  2. 否则,这就是我如何处理你的情况:

    而不是尝试直接操作会话,创建共享上下文或帮助程序,通过与登录表单交互登录用户,方式与浏览站点的用户相同.

    这是一种方法:

    规格/支持/ when_authenticated.rb

    RSpec.shared_context 'When authenticated' do
      background do
        authenticate
      end
    
      def authenticate
        visit '/sessions/new'
        within('form#session') do
          fill_in 'Email', :with => 'user@example.com'
          fill_in 'Password', :with => 'password'
        end
        click_button 'Sign in'
      end
    end
    
    Run Code Online (Sandbox Code Playgroud)

    然后,在您的功能规范中:

    RSpec.feature 'User does something' do
      include_context 'When authenticated'
    
      # examples
    end
    
    Run Code Online (Sandbox Code Playgroud)

    这具有在规范中的每个示例之前运行身份验证过程的效果.