Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

RSpec: how to stub inherited method current_user (w/o Devise)?

I have a controller based on MHartl's RoR4 Tutorial

And just like MHartl, I'm not using Devise, I rolled my own authentication system

Having trouble with the RSpec for UsersController#Edit since the view has a call to current_user.admin? and the controller calls @path_switch = path_switch

I keep getting RSpec errors along the lines of:

1) User Pages Edit   Failure/Error: visit edit_user_path(user)  NoMethodError:    undefined method `admin?' for nil:NilClass  # ./app/controllers/users_controller.rb:106:in `path_switch'  # ./app/controllers/users_controller.rb:53:in `edit'  # ./spec/requests/user_pages_spec.rb:54:in `block (3 levels) in <top (required)>' 

UsersController:

class UsersController < ApplicationController   ...   def edit     @user = User.find(params[:id])     @path_switch ||= path_switch                        #error   end   ...   def path_switch     if current_user.admin?                               #error       users_path     else       root_path     end   end end 

I found this really helpful article that gives me hope that I'm on the right track, but I can't get it to work.

Here's as far as I've gotten (updated):

user_pages_spec.rb:

require 'spec_helper' require 'support/utilities'  describe "User Pages" do   #include SessionsHelper    let(:user) { FactoryGirl.create(:user) }   let(:current_user) {user}    subject { page }    describe "Edit" do     before do       sign_in(user)       visit edit_user_path(user)      end      it '(check links and content)' do       should have_button('Submit')       should have_link('Cancel')       should have_content(user.fname+"\'s profile")     end    ...   end ... end 

But current_user is still coming back nil

Any help/guidance is appreciated. Thanks!


Adding include SessionsHelper to the top describe block of my user_pages_edit.rb seems to try and use the sign_in(path) from that helper. Creating an issue between RSpec and cookies.permanent. So that's a bust.

unfortunately, this brings me right back to my .admin? error.

There are two calls to current_user.admin?

One is in the controller:

  def path_switch     if current_user.admin?    #error current_user == nil       users_path     else       root_path     end   end 

One is in the view as ERB:

<% if current_user.admin? %>   <div class="row  col-xs-6 col-sm-6 col-md-3">     <div class="input-group input-selector">     ... 

All I need to do is figure out how to set current_user.admin = true and pass it to the controller (and then hopefully the view) so that the page can load. To do that, all I need to do is set current_user = user because user.admin == true.

like image 953
Chiperific Avatar asked Jul 02 '14 03:07

Chiperific


2 Answers

If you are doing unit testing of your controller you can simply stub your current_user in a before block, like this:

let(:user) { ... }  # RSpec version <= 2 syntax: before { controller.stub(:current_user) { user } }  # RSpec version >= 3 syntax: before { allow(controller).to receive(:current_user) { user } } 

If you are doing feature or request testing, I advise you to perform a real log-in by creating a user in your database, then passing through your log-in page with this user credentials


Here you seem to be doing a feature test, you should write a helper that perform the creation of the user record and go through the log-in.

Additionally in feature testing to gain a lot of time while running your test, do not hesitate to group your assertions in the same block. Clearly, instead of:

it { should have_button('Submit')} it { should have_link('Cancel')} it { should have_content(user.fname+"\'s profile")} 

You can write

it 'check links and content' do   should have_button('Submit')   should have_link('Cancel')   should have_content(user.fname+"\'s profile") end 

That will avoid to generate several session of your feature environment, and also to log-in several times

like image 79
Benj Avatar answered Sep 19 '22 22:09

Benj


Also works

user = create(:user) #FactoryBot  allow(controller).to receive(:current_user).and_return(user) 
like image 25
user2322409 Avatar answered Sep 19 '22 22:09

user2322409