0

RoR 튜토리얼 (9.4 장)을 작성하려고합니다. 모든 rspec 테스트가 녹색으로 바뀌면 작동하지 않습니다.테스트 실패 RoR 튜토리얼 (9.4 장)

Failures: 

    1) User pages index signup page with valid information after saving the user 
    Failure/Error: sign_in user 
    NoMethodError: 
     undefined method `email' for nil:NilClass 
    # ./spec/support/utilities.rb:23:in `sign_in' 
    # ./spec/requests/user_pages_spec.rb:12:in `block (3 levels) in <top (requi 
red)>' 

    2) User pages index signup page with valid information after saving the user 
    Failure/Error: sign_in user 
    NoMethodError: 
     undefined method `email' for nil:NilClass 
    # ./spec/support/utilities.rb:23:in `sign_in' 
    # ./spec/requests/user_pages_spec.rb:12:in `block (3 levels) in <top (requi 
red)>' 

    3) User pages index signup page with valid information after saving the user 
    Failure/Error: sign_in user 
    NoMethodError: 
     undefined method `email' for nil:NilClass 
    # ./spec/support/utilities.rb:23:in `sign_in' 
    # ./spec/requests/user_pages_spec.rb:12:in `block (3 levels) in <top (requi 
red)>' 

    4) Authentication signin with invalid information after visiting another page 

    Failure/Error: it { should_not have_selector('div.alert.alert-error') } 
     expected #has_selector?("div.alert.alert-error") to return false, got tru 
e 
    # ./spec/requests/authentication_pages_spec.rb:26:in `block (5 levels) in < 
top (required)>' 

Finished in 21.33 seconds 
81 examples, 4 failures 

utilities.rb :

include ApplicationHelper 

def valid_signin(user) 
    fill_in "Email", with: user.email 
    fill_in "Password", with: user.password 
    click_button "Sign in" 
end 

RSpec::Matchers.define :have_error_message do |message| 
    match do |page| 
    expect(page).to have_selector('div.alert.alert-error', text: message) 
    end 
end 

def sign_in(user, options={}) 
    if options[:no_capybara] 
    # Sign in when not using Capybara. 
    remember_token = User.new_remember_token 
    cookies[:remember_token] = remember_token 
    user.update_attribute(:remember_token, User.encrypt(remember_token)) 
    else 
    visit signin_path 
    fill_in "Email", with: user.email 
    fill_in "Password", with: user.password 
    click_button "Sign in" 
    end 
end 

user_page_spec.rb :

require 'spec_helper' 

describe "User pages" do 

    subject { page } 

    describe "index" do 

    let(:user) { FactoryGirl.create(:user) } 

    before do 
     sign_in user 
     visit users_path 
    end 

    it { should have_title('All users') } 
    it { should have_content('All users') } 

    describe "pagination" do 

     before(:all) { 30.times { FactoryGirl.create(:user) } } 
     after(:all) { User.delete_all } 

     it { should have_selector('div.pagination') } 

     it "should list each user" do 
     User.paginate(page: 1).each do |user| 
      expect(page).to have_selector('li', text: user.name) 
     end 
     end 
    end 

    describe "delete links" do 

     it { should_not have_link('delete') } 

     describe "delete links" do 

     it { should_not have_link('delete') } 

     describe "as an admin user" do 
     let(:admin) { FactoryGirl.create(:admin) } 
     before do 
      sign_in admin 
      visit users_path 
     end 

     it { should have_link('delete', href: user_path(User.first)) } 
     it "should be able to delete another user" do 
      expect do 
      click_link('delete', match: :first) 
      end.to change(User, :count).by(-1) 
     end 
     it { should_not have_link('delete', href: user_path(admin)) } 
     end 
    end 
    end 


    describe "profile page" do 
    let(:user) { FactoryGirl.create(:user) } 
    before { visit user_path(user) } 

    it { should have_content(user.name) } 
    it { should have_title(user.name) } 
    end 

    describe "signup page" do 

    before { visit signup_path } 

    let(:submit) { "Create my account" } 

    describe "with invalid information" do 
     it "should not create a user" do 
     expect { click_button submit }.not_to change(User, :count) 
     end 
    end 

    describe "with valid information" do 
     before do 
     fill_in "Name",   with: "Example User" 
     fill_in "Email",  with: "[email protected]" 
     fill_in "Password",  with: "foobar" 
     fill_in "Confirmation", with: "foobar" 
     end 

     it "should create a user" do 
     expect { click_button submit }.to change(User, :count).by(1) 
     end 

     describe "after saving the user" do 
     before { click_button submit } 
     let(:user) { User.find_by(email: '[email protected]') } 

     it { should have_link('Sign out') } 
     it { should have_title(user.name) } 
     it { should have_selector('div.alert.alert-success', text: 'Welcome') } 
     end 

    end 
    end 

    describe "edit" do 
    let(:user) { FactoryGirl.create(:user) } 
    before do 
     sign_in user 
     visit edit_user_path(user) 
    end 

    describe "page" do 
     it { should have_content("Update your profile") } 
     it { should have_title("Edit user") } 
     it { should have_link('change', href: 'http://gravatar.com/emails') } 
    end 

    describe "with valid information" do 
     let(:new_name) { "New Name" } 
     let(:new_email) { "[email protected]" } 
     before do 
     fill_in "Name",    with: new_name 
     fill_in "Email",   with: new_email 
     fill_in "Password",   with: user.password 
     fill_in "Confirm Password", with: user.password 
     click_button "Save changes" 
     end 

     it { should have_title(new_name) } 
     it { should have_selector('div.alert.alert-success') } 
     it { should have_link('Sign out', href: signout_path) } 
     specify { expect(user.reload.name).to eq new_name } 
     specify { expect(user.reload.email).to eq new_email } 
    end 
    end 
end 
end 

authentication_pages_spec.rb :

이 오류와 함께 번들 간부 RSpec에 사양을 실행/네이 실패 할 수
require 'spec_helper' 

describe "Authentication" do 

    subject { page } 

    describe "signin page" do 
    before { visit signin_path } 

    it { should have_content('Sign in') } 
    it { should have_title('Sign in') } 
    end 

describe "signin" do 

    before { visit signin_path } 

    describe "with invalid information" do 
     before { click_button "Sign in" } 

     it { should have_title('Sign in') } 
     it { should have_selector('div.alert.alert-error') } 

     describe "after visiting another page" do 
     before { click_link "Home" } 
     it { should_not have_selector('div.alert.alert-error') } 
     end 
    end 


    describe "with valid information" do 
     let(:user) { FactoryGirl.create(:user) } 
     before { sign_in user } 

     it { should have_title(user.name) } 
     it { should have_link('Users',  href: users_path) } 
     it { should have_link('Profile',  href: user_path(user)) } 
     it { should have_link('Settings', href: edit_user_path(user)) } 
     it { should have_link('Sign out', href: signout_path) } 
     it { should_not have_link('Sign in', href: signin_path) } 



    describe "follower by signout" do 
     before {click_link "Sign out"} 
     it {should have_link('Sign in')} 
     end 
    end 
    end 

describe "authorization" do 

    describe "for non-signed-in users" do 
     let(:user) { FactoryGirl.create(:user) } 

     describe "when attempting to visit a protected page" do 
     before do 
      visit edit_user_path(user) 
      fill_in "Email", with: user.email 
      fill_in "Password", with: user.password 
      click_button "Sign in" 
     end 

     describe "after signing in" do 

      it "should render the desired protected page" do 
      expect(page).to have_title('Edit user') 
      end 
     end 
     end 

     describe "in the Users controller" do 

     describe "visiting the edit page" do 
      before { visit edit_user_path(user) } 
      it { should have_title('Sign in') } 
     end 


     describe "submitting to the update action" do 
      before { patch user_path(user) } 
      specify { expect(response).to redirect_to(signin_path) } 
     end 
     end 
     describe "visiting the user index" do 
      before { visit users_path } 
      it { should have_title('Sign in') } 
     end 

    end 

    describe "as wrong user" do 
     let(:user) { FactoryGirl.create(:user) } 
     let(:wrong_user) { FactoryGirl.create(:user, email: "[email protected]") } 
     before { sign_in user, no_capybara: true } 

     describe "submitting a GET request to the Users#edit action" do 
     before { get edit_user_path(wrong_user) } 
     specify { expect(response.body).not_to match(full_title('Edit user')) } 
     specify { expect(response).to redirect_to(root_url) } 
     end 

     describe "submitting a PATCH request to the Users#update action" do 
     before { patch user_path(wrong_user) } 
     specify { expect(response).to redirect_to(root_url) } 
     end 
    end 

    describe "as non-admin user" do 
     let(:user) { FactoryGirl.create(:user) } 
     let(:non_admin) { FactoryGirl.create(:user) } 

     before { sign_in non_admin, no_capybara: true } 

     describe "submitting a DELETE request to the Users#destroy action" do 
     before { delete user_path(user) } 
     specify { expect(response).to redirect_to(root_url) } 
     end 
    end 
    end 
end 

user.r B

class User < ActiveRecord::Base 
    has_secure_password 
    before_save { self.email = email.downcase } 
    before_create :create_remember_token 
    validates :name, presence: true, length: { maximum: 50 } 
    VALID_EMAIL_REGEX = /\A[\w+\-.][email protected][a-z\d\-]+(\.[a-z]+)*\.[a-z]+\z/i 
    validates :email, presence: true, format: { with: VALID_EMAIL_REGEX }, 
        uniqueness: { case_sensitive: false } 
    has_secure_password 
    validates :password, length: { minimum: 6 } 

    def User.new_remember_token 
    SecureRandom.urlsafe_base64 
    end 

    def User.encrypt(token) 
    Digest::SHA1.hexdigest(token.to_s) 
    end 

    private 

    def create_remember_token 
     self.remember_token = User.encrypt(User.new_remember_token) 
    end 

end 

factories.rb :

FactoryGirl.define do 
    factory :user do 
    sequence(:name) { |n| "Person #{n}" } 
    sequence(:email) { |n| "person_#{n}@example.com"} 
    password "foobar" 
    password_confirmation "foobar" 

    factory :admin do 
     admin true 
    end 
    end 
end 

레일 본체 시험 : I가 변경 users_controller.rb 지금은 단지 3 (1-3) 결함이

irb(main):001:0> **user = FactoryGirl.build(:user)** 
=> #<User id: nil, name: "Person 1", email: "[email protected]", created_at: 
nil, updated_at: nil, password_digest: "$2a$04$LiRdaarU6QaX9PJa1uFjE.5e44SYRsmy1 
OMY8A4EKZow...", remember_token: nil, admin: false> 

irb(main):002:0> **user.valid?** 
    User Exists (1.0ms) SELECT 1 AS one FROM "users" WHERE LOWER("users"."email") 
= LOWER('[email protected]') LIMIT 1 
=> true 

irb(main):003:0> **user.errors** 
=> #<ActiveModel::Errors:0x49dd678 @base=#<User id: nil, name: "Person 1", email 
: "[email protected]", created_at: nil, updated_at: nil, password_digest: "$2 
a$04$LiRdaarU6QaX9PJa1uFjE.5e44SYRsmy1OMY8A4EKZow...", remember_token: nil, admi 
n: false>, @messages={}> 

users_controller.rb :

  class UsersController < ApplicationController 
    before_action :signed_in_user, only: [:index, :edit, :update, :destroy] 
    before_action :correct_user, only: [:edit, :update] 
    before_action :admin_user,  only: :destroy 

    def index 
    @users = User.paginate(page: params[:page]) 
    end 

    def show 
    @user = User.find(params[:id]) 
    end 

    def new 
    @user = User.new 
    end 

    def create 
    @user = User.new(user_params) 
    if @user.save 
     sign_in @user 
     flash[:success] = "Welcome to the Sample App!" 
     redirect_to @user 
    else 
     render 'new' 
    end 
    end 

    def edit 
    end 

    def update 
    if @user.update_attributes(user_params) 
     flash[:success] = "Profile updated" 
     redirect_to @user 
     # Handle a successful update. 
    else 
     render 'edit' 
    end 
    end 

    def destroy 
    User.find(params[:id]).destroy 
    flash[:success] = "User deleted." 
    redirect_to users_url 
    end 

    private 

    def user_params 
     params.require(:user).permit(:name, :email, :password, 
            :password_confirmation) 
    end 

    # Before filters 

    def signed_in_user 
     unless signed_in? 
     store_location 
     redirect_to signin_url, notice: "Please sign in." 
     end 
    end 


    def correct_user 
     @user = User.find(params[:id]) 
     redirect_to(root_url) unless current_user?(@user) 
    end 


    def admin_user 
     redirect_to(root_url) unless current_user.admin? 
    end 

end 

실제 프로젝트 버전 - https://tranquil-waters-6116.herokuapp.com. 어쩌면 실패 이유를 찾는데 도움이 될 것입니다/

+0

실제 코드를 공유하고 테스트 결과가 아닌 실패한 테스트를 수행해야합니다. –

+0

@GraemeMcLean Ok – detskai

+0

'app/models/user.rb' – yoppuyoppu

답변

1

user_page_spec.rb에있는 end 문 중 하나가 잘못되었습니다. describe "index" 블록은 describe "profile page" 전에 끝나야합니다.

테스트 먼저 로그인 유저가 없어야하므로 즉

describe "index" do 
    ... 
    describe "pagination" do 
    ... 
    end 

    describe "delete links" do 
    ... 
    end 
end 

describe "profile page" do 
    ... 
end 

describe "signup page" do 
    ... 
end 

etc. 

가입은 가입 신규 사용자이다.

참고 : 오류의 원인이되지는 않지만 내부에 중첩 된 describe "delete links"도 두 번 있습니다. 그것은 단지 테스트를 반복합니다.

1

VALID_EMAIL_REGEX를 다르게 정의했기 때문에 factory :userspec/factories.rb에 정의 된 것을 볼 수 있다면 좋을 것입니다.

는 우선, 당신은 원래의 정규식 조건을 되돌릴 수 : 검증 부분이 factory :user와 함께 작동

VALID_EMAIL_REGEX = /\A[\w+\-.][email protected][a-z\d\-.]+\.[a-z]+\z/i 

또는

가 그것을 참조하십시오.

두 번째 has_secure_password을 안전한쪽에 두십시오.

+0

두 번째 has_secure_password를 제거하고 VALID_EMAIL_REGEX를 변경했습니다. 그러나 여전히 4 가지 실패가 있습니다. – detskai

관련 문제