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