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
.
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
Also works
user = create(:user) #FactoryBot allow(controller).to receive(:current_user).and_return(user)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With