Testing custom devise session controller using RSpec - ruby-on-rails-4

I'm using a custom Devise SessionsController:
#custom_sessions_controller.rb
class CustomSessionsController < Devise::SessionsController
end
In my routes.rb devise is set up like this:
#routes.rb
devise_for :custom_users, {
:singular => 'custom_user',
:class_name => 'CustomUser',
:path => "/",
:path_names => { :sign_in => 'login', :sign_out => 'logout' },
:controllers => { :sessions => "custom_sessions" }
}
I would like to write a simple rspec test:
#custom_sessions_controller_spec.rb
require 'rails_helper'
describe CustomSessionsController, :type => :controller do
describe "login" do
before do
setup_controller_for_warden
#request.env["devise.mapping"] = Devise.mappings[:custom_user]
#my_user = FactoryGirl.create(:custom_user) # creates user with valid credentials
end
it "should succeed with valid credentials" do
sign_in #my_user
curr_user = assigns(:current_custom_user)
expect(curr_user).to eq(#my_user)
expect(response).to be_success
end
end
end
In my rails_helper.rb the following lines are present:
require 'devise'
...
RSpec.configure do |config|
...
config.include Devise::TestHelpers, :type => :controller
config.include Warden::Test::Helpers , :type => :controller
...
The problem is that curr_user in the test is alway nil. What am I doing wrong? Or how to test a custom devise session controller? Or how to log in in - other - tests using a custom devise session?

instead of:
describe CustomSessionsController, :type => :controller do
try:
RSpec.describe CustomSessionsController, :type => :controller do
Hope it works!

Using
#controller.current_custom_user
instead of
assigns(:current_custom_user)
seems to work.

Related

Devise issue after migrating to Rails 4.0

I'm getting this error after upgrading to Rails 4.0 from 3.2.1:
Invalid route name, already in use: 'new_user_session'
I have this in my routes file:
devise_for :users, :controllers => { :omniauth_callbacks => "users/omniauth_callbacks", :registrations => "registrations", :confirmations => "confirmations", :passwords => "passwords"}
devise_for :users do
get '/users/auth/:provider' => 'users/omniauth_callbacks#passthru'
get '/users/logout' => 'users#logout'
end
How do I need to write it now to make it correct?
Thank you
There is a conflict because the the devise_for part of the first two lines try to do the same thing (i.e. create the same devise route names, causing new_user_session to already be in use).
You can either:
Remove the first line
Make the second line devise_for :users, :controllers => { :omniauth_callbacks => "users/omniauth_callbacks", :registrations => "registrations", :confirmations => "confirmations", :passwords => "passwords"} do
or
Make the second line devise_scope instead of devise_for

What's the correct way to override Devise registration route

My route.rb file has this line:
devise_for :users,
:controllers => { registrations: 'register' },
:path => '',
:path_names => {
:sign_in => 'login',
:sign_out => 'logout',
:sign_up => 'register'
}
sing_in and sing_out overriding works well, but sing_up doesn't.
If I visit /register I obtain an uninitialized constant RegisterController.
I'm sure that I'm doing something wrong, but I'm pretty new to Rails and I don't understand very well what that code do. It comes out from many search on Google...
update 1
I follow also this official guide: https://github.com/plataformatec/devise/wiki/How-To:-Change-the-default-sign_in-and-sign_out-routes#another-simple-way-to-do-the-same-thing
update 2
Ok, I don't know way I added the :controllers params to the previous code, but after removed it
devise_for :users,
:path => '',
:path_names => {
:sign_in => 'login',
:sign_out => 'logout',
:sign_up => 'register'
}
And now if I run rake routes | grep devise on my console I got this:
cancel_user_registration GET /cancel(.:format) devise/registrations#cancel
user_registration POST / devise/registrations#create
new_user_registration GET /register(.:format) devise/registrations#new
edit_user_registration GET /edit(.:format) devise/registrations#edit
PATCH / devise/registrations#update
PUT / devise/registrations#update
DELETE / devise/registrations#destroy
And as you can see now the route for the creation of a user is POST /, and I'm sure that this is not a good thing... right? And the major problem is here: GET /have to be the homepage and not the get-all-users-page.
may the :path => '' introduce errors?
I'm not sure the path_names param is what you should be doing. You can assign the controller methods using:
devise_scope :user do
get '/logout', :to => 'devise/sessions#destroy', :as => :destroy_user_session
post '/signin', :to => 'devise/sessions#create', :as => :user_session
end

undefined method `registrationsController' for Devise:Module

I am getting the following error with navigating to my sign in/signup pages:
undefined method `registrationsController' for Devise:Module
/users/registrations_controller.rb
class Users::RegistrationsController < Devise::registrationsController
# def new
# super
# end
# def create
# super
# end
end
/config/routes.rb
Rails.application.routes.draw do
get 'spotkeys/spot_page'
root 'spotkeys#index'
get 'index' => 'spotkeys#index'
get 'dashboard' => 'spotkeys#dashboard'
post 'dashboard' => 'spotkeys#dashboard'
get 'settings' => 'spotkeys#settings'
get 'key_settings' => 'spotkeys#key_settings'
get 'qr_codes/new'
get 'qr_codes/create'
get 'settings' => 'spotkeys#settings'
get 'key_settings' => 'spotkeys#key_settings'
match 'dashboard' => 'spotkeys#dashboard', as: :new_spotkey, via: [:get, :post]
get 'signup', to: 'users/registrations#new', :as => :new_user_session
post 'signin', to: 'users/sessions#create', :as => :user_session
delete 'signout', to: 'users/sessions#destroy'
resources :qr_codes, only: [:new, :create]
resources :spotkeys
resources :keys
devise_for :users,
:controllers => { :registrations => 'users/registrations',
:confirmations => 'users/confirmations',
:sessions => 'users/sessions',
:omniauth_callbacks => 'omniauth_callbacks'
},
:to => 'users/sessions#destroy', :as => :destroy_user_session,
:skip => [:sessions] do
end
end
I am using:
rails 4.2.0
ruby 2.1.5p273
Your inheritance is defined wrong. You mistyped the lowercase r instead of the uppercase R in the parent class. You should define your controller like this:
class Users::RegistrationsController < Devise::RegistrationsController

Loading and using devise macros in rspec tests

Following the instructions at https://github.com/plataformatec/devise/wiki/How-To:-Test-controllers-with-Rails-3-and-4-%28and-RSpec%29, I have set up some macros in a file spec/support/rspec_macros.rb:
module ControllerMacros
def login_admin
before(:each) do
#request.env["devise.mapping"] = Devise.mappings[:user]
sign_in FactoryGirl.create(:user, role: 4)
end
end
def login_user
before(:each) do
#request.env["devise.mapping"] = Devise.mappings[:user]
sign_in FactoryGirl.create(:user)
end
end
end
(Note that in my app, "admin" is a role -- role 4 -- that any user can be assigned to, and yes, once I get this working I'll DRY this up and get rid of the magic number).
However, putting login_admin into my spec doesn't work: it can't see login_admin.
So, following the advice at ControllerMacros cannot be seen in RSpec I add
config.include ControllerMacros, :type => :controller
to my spec_helper.rb file. Now ControllerMacros is an uninitialized constant, so following the advice at rspec not working with devise user authentication I add:
require 'support/controller_macros'
to my spec_helper file, and I find that I'm back where I started with undefined local variable or method login_admin
Help! How do I get to the macro? And is there one single place where the whole process is documented?
For info, the relevant bits of my spec_helper file are:
require 'rubygems'
require 'factory_girl'
require 'support/controller_macros'
require 'devise'
RSpec.configure do |config|
config.include Devise::TestHelpers, :type => :controller
config.include ControllerMacros, :type => :controller
end
And my spec file is:
require 'rails_helper'
RSpec.describe UsersController, :type => :controller do
describe "GET show" do
login_admin
it "returns http success" do
user = User.first
get :show, id: user[:id]
expect(response).to be_success
end
end
end
Make sure that rails_helper.rb loads files in spec/support folder.
If not add that line to your rails_helper.rb:
Dir[Rails.root.join('spec/support/**/*.rb')].each { |f| require f }`
after require 'rspec/rails' and move devise config to rails_helper.rb
RSpec.configure do |config|
config.include Devise::TestHelpers, :type => :controller
config.include ControllerMacros, :type => :controller
end

Rails4 Upgrading Devise Extend Controller

When Upgrading rails application from 3.2.17 to 4.0.4, I am getting this errors
default_controller_and_action': 'Sessions' is not a supported controller name. This can lead to potential routing problems. See http://guides.rubyonrails.org/routing.html#specifying-a-controller-to-use (ArgumentError)
In my routes file content
devise_for :users, :controllers => { :sessions => "Sessions", :passwords => "Passwords", :registrations => "registrations" } , :path => '', :path_names => {
:sign_in => 'login',
:sign_out => 'logout'
}
root :to => "children#index"
And SessionsController is extended from devise controller as follow
class SessionsController < Devise::SessionsController
...........................
....................
end
Why I am getting Sessions is not supported controller name ? I have try to change it in routes and controller but still facing same problem.
Solve this issues. This issues was due to case sensitive. We have to use small letter instead of Capital letter. For example, not Sessions but sessions. I was using Sessions in routes file but I have change it as sessions. The above code can written as
devise_for :users, :controllers => { :sessions => "sessions", :passwords => "passwords", :registrations => "registrations" } , :path => '', :path_names => {
:sign_in => 'login',
:sign_out => 'logout'
}