How do I stub current_user in Rails 5?
I expected this:
#controller.stub :current_user, mock_user do
end
to work, but there is no #controller in ActionDispatch::IntegrationTest? I use sorcery gem for authentication.
You could try the wiki example:
class TeamsControllerTest < ActionController::TestCase
include Sorcery::TestHelpers::Rails::Integration
include Sorcery::TestHelpers::Rails::Controller
setup do
#team = teams(:one)
#user = users(:one)
login_user(user = #user, route = login_url) # replace with your login url path
end
test "should get index" do
get :index
assert_response :success
assert_not_nil assigns(:teams)
end
That will set your test user as current_user.
Related
I changed the default behavior of after_sign_in_path_for method like this:
class ApplicationController < ActionController::Base
private
def after_sign_in_path_for(resource)
return admin_root_path if resource.is_a?(AdminUser)
request.referrer || root_path
end
end
It works find and now I want to test it by minitest.
But I couldn't figure out how to write integration test for it.
Although there is an answer for rspec, I couln't rewrite for minitest.
How to test after_sign_in_path_for(resource)?
How can I write the test for after_sign_in_path_for by minitest?
Rails: 5.1
devise: 4.5.0
require 'test_helper'
class ApplicationControllerTest < ActionDispatch::IntegrationTest
include Devise::Test::IntegrationHelpers
setup do
2.times{ create(:post) }
#user = create(:user)
#admin_user = create(:admin_user)
end
test "should redirect to '/posts/1' after login" do
# get "/posts/1"
# sign_in(#user)
# test return back "/posts/1"
end
test "should redirect to '/posts/2' after login" do
# get "/posts/2"
# sign_in(#user)
# test return back "/posts/2"
end
test "should redirect to admin root page after login" do
# sign_in(#adminuser)
# test go to admin root page
end
end
You can test them like so:
require 'test_helper'
class ApplicationControllerTest < ActionDispatch::IntegrationTest
include Devise::Test::IntegrationHelpers
setup do
#user = create(:user)
#admin_user = create(:admin_user)
end
test "should redirect to current page after login" do
sign_in(#user)
get :index
assert_redirected_to controller: "home", action: "index"
end
test "should redirect to admin root page after login" do
sign_in(#adminuser)
get :index
assert_redirected_to controller: "admin", action: "index"
end
end
assert_redirected_to API docs
I am trying to spec the following.
I need to return all entities that are linked to the logged in user. Subsequently I need to create the user before the fact and then ensure that the specific user is logged in. I am struggling to achieve this with controller macros. My specs are failing as follows
1) Yougov::Surveys::ProfilesController GET :index returns all profiles linked to the loged in user with the same country and client as the linked survey
Failure/Error: sign_in user
RuntimeError:
Could not find a valid mapping for nil
# /Users/donovan.thomson/.rvm/gems/ruby-2.2.2#insight-app/gems/devise-2.2.8/lib/devise/mapping.rb:42:in `find_scope!'
# /Users/donovan.thomson/.rvm/gems/ruby-2.2.2#insight-app/gems/devise-2.2.8/lib/devise/test_helpers.rb:46:in `sign_in'
# ./spec/support/controller_macros.rb:17:in `block in login_specific_user'
So a basic scaffolding of my controller looks as follows :
class ProfilesController < ApplicationController
def index
render json: Profile.where(user_id: current_user.id)
end
end
I assume this means the user is not being logged in as I would expect
My spec is as follows
require 'spec_helper'
describe ProfilesController, type: :controller do
before do
#user = FactoryGirl.create :user
#profile = FactoryGirl.create :profile, user: #user
FactoryGirl.create :profile
end
describe "GET :index" do
login_specific_user(#user)
it "returns all profiles linked to the loged in user with the same country and client as the linked survey" do
get :index
expect(response.body).to eq(#profile.to_json)
end
end
end
My controller macro's are as follows:
module ControllerMacros
def login_admin
before :each do
sign_in ControllerMacros.get_user(#request, :admin, :admin_user)
end
end
def login_user
before :each do
sign_in ControllerMacros.get_user(#request, :user)
end
end
def login_specific_user(user)
before :each do
sign_in user
end
end
class << self
def get_user(req, mapping, type=mapping)
req.env["devise.mapping"] = Devise.mappings[mapping]
user = FactoryGirl.create(type)
user.confirm!
user
end
end
end
I solved this by not using controller macros and just adding the following to my before block
before do
#user = FactoryGirl.create :user
#user.confirm!
sign_in #user
end
I had devise generate controllers for users with the console command rails generate devise:controllers users, and when I try to run a simple test for registrations_controller.rb my console outputs the error:
RuntimeError: #controller is nil: make sure you set it in your test's
setup method.
I am new to devise, but everything has seemed pretty straightforward so I don't really see why this isn't working.
This is app/controllers/users/registrations_controller.rb :
class RegistrationsController < Devise::RegistrationsController
# GET /resource/sign_up
def new
super
#user = User.new
end
end
This is config/routes.rb :
Rails.application.routes.draw do
devise_for :users, controllers: { registrations: 'users/registrations'}
devise_scope :users do
root 'users/registrations#new'
get "sign_up", to: "users/registrations#new"
end
end
And this is test/controllers/registrations_controller_test.rb
require 'test_helper'
class RegistrationsControllerTest < ActionController::TestCase
include Devise::TestHelpers
def setup
#user = users(:user1)
end
test "should get new" do
get :new
assert_response :success
end
end
Any help you can provide is appreciated very much!
Per the Devise docs: "If you are testing Devise internal controllers or a controller that inherits from Devise's, you need to tell Devise which mapping should be used before a request." https://github.com/plataformatec/devise#test-helpers
class RegistrationsControllerTest < ActionController::TestCase
include Devise::TestHelpers
def setup
request.env['devise.mapping'] = Devise.mappings[:user]
#user = users(:user1)
end
test "should get new" do
get :new
assert_response :success
end
end
You may also need to prefix your test class like so:
class Users::RegistrationsControllerTest < ActionController::TestCase
...
end
I'm trying to do integration test for our login process we have overwrite session create process like this:
module UsersDashboard
class SessionsController < Devise::SessionsController
protect_from_forgery :except => [:create, :mfa_callback, :authenticate]
def test
session[:test] = 'doodoo'
self.resource = warden.authenticate!(auth_options)
render text: 'hi'
end
# Used for User Dashboard login
def create
current_user = warden.authenticate!(auth_options)
resource = current_user
current_user.update_attribute(:mfa_authenticated, false)
# some code here
session[:channel] = 'some value'
p "session channel in create: #{session[:channel]}, #{session.class}"
redirect_url = 'some value here'
redirect_to redirect_url
end
end
and here is my test code:
require 'test_helper'
include Warden::Test::Helpers
class DashboardOkTest < ActionDispatch::IntegrationTest
test "Dashboard sign in and visiting various pages inside dashboard " do
post_via_redirect '/users_dashboard/sessions/mani'
p session[:test]
mani = users(:mani)
post_via_redirect '/users/sign_in', 'user[email]' => mani.email, 'user[password]' => '123456'
assert_response :success
assert_equal '/mfa/index', path
assert_select '#choose-mfa-method', 'Choose Your Acceptto Multi-Factor Auth Method:'
login_as mani, scope: :user
p "session: #{session[:channel]}, #{session.inspect}"
assert request.query_parameters.has_key?(:channel)
tfa = Tfa.find_by_channel(request.query_parameters[:channel])
assert tfa
tfa.update_attribute(:status, 'approved')
get "/users_dashboard/sessions/authenticate?channel=#{tfa.channel}"
end
end
as you can see in the output:
"doodoo"
"session channel in create: 123, ActionDispatch::Request::Session"
"session: , #<ActionDispatch::Request::Session:0x7fabecaa9458 not yet loaded>"
"session channel is nil"
session[:channel] doesn't work and session is not loaded yet! interesting point is I have created a test method in Session Controller as you can see and if we set session[:test] before calling self.resource = warden.authenticate!(auth_options) session works and it prints 'doodoo' but it's not the case for create method if we set session[:channel] before self.resource = warden.authenticate!(auth_options) it still doesn't work.
It looks like devise has some kind of wrapper that nullifies session after create call. and all this just happens in test while session and everything else works in development server in web.
Any idea how to set a session for test inside create method?
I'm writing tests with rspec for my application controller in my rails app (written in Rails 4) and I'm running into a problem where it doesn't recognize the route for the HTTP request I'm sending. I know there's a way to do this using MyApp::Application.routes but I'm not able to get it working.
#application_controller_spec.rb
require 'spec_helper'
class TestController < ApplicationController
def index; end
end
describe TestController do
before(:each) do
#first_user = FactoryGirl.create(:user)
# this is to ensure that all before_filters are run
controller.stub(:first_time_user)
controller.stub(:current_user)
end
describe 'first_time_user' do
before(:each) do
controller.unstub(:first_time_user)
end
context 'is in db' do
before(:each) do
#user = FactoryGirl.create(:user)
controller.stub(:current_user).and_return(#user)
end
it 'should not redirect' do
get :index
response.should_not be_redirect
end
end
context 'is not in db' do
context 'session[:cas_user] does not exist' do
it 'should return nil' do
get :index
expect(assigns(:current_user)).to eq(nil)
end
end
it "should redirect_to new_user_path" do
controller.stub(:current_user, redirect: true).and_return(nil)
get :index
response.should be_redirect
end
end
end
The error I'm getting right now is
No route matches {:action=>"index", :controller=>"test"}
I would add the test#index route to config/routes.rb, but it doesn't recognize the Test Controller, so I want to do something like
MyApp::Application.routes.append do
controller :test do
get 'test/index' => :index
end
end
but I'm not sure where to add this or if this even works in rspec. Any help would be great!
If you are trying to test your ApplicationController, see this RSpec documentation about it. You will need to define methods like index inside the test, but it works well.