How to test after_sign_in_path_for by minitest - ruby-on-rails

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

Related

Rails 6 Devise test helpers without RSpec

Devise test helpers with Rails 6 without Rspec doesn't seem to work. Here is the code, any idea why it might be getting errors?
Controller:
class VehiclesController < ApplicationController
before_action :authenticate_user!, only: [:new]
def index
#vehicles = Vehicle.all
end
def new
#vehicle = Vehicle.new
end
end
test/test_helper.rb
ENV['RAILS_ENV'] ||= 'test'
require_relative "../config/environment"
require "rails/test_help"
class ActiveSupport::TestCase
# Run tests in parallel with specified workers
parallelize(workers: :number_of_processors)
# Setup all fixtures in test/fixtures/*.yml for all tests in alphabetical order.
fixtures :all
include Devise::Test::IntegrationHelpers
end
user fixture:
valid_user:
first_name: "Toseef"
last_name: "zafar"
email: "exampleuser#gmail.com"
encrypted_password: <%= Devise::Encryptor.digest(User, '12345678') %>
controller test:
require "test_helper"
class VehiclesControllerTest < ActionDispatch::IntegrationTest
test "should be able to get to new form page" do
sign_in users(:valid_user)
get new_vehicles_url
assert_response :success
end
end
and this is the error I get:
Failure:
VehiclesControllerTest#test_should_be_able_to_get_to_new_form_page [/test/controllers/vehicles_controller_test.rb:12]:
Expected response to be a <2XX: success>, but was a <302: Found> redirect to <http://www.example.com/users/sign_in>
Response body: <html><body>You are being redirected.</body></html>
rails test test/controllers/vehicles_controller_test.rb:9
Also, I don't know why it would point to http://www.example.com
The devise user model has got confirmable hence when we do sign_in users(:valid_user) devise creates a user but because the user is not confirmed (i.e. no confirmation email link clicking is involved) when we go to a secured URL it takes us back to login because user hasn't confirmed through clicking on the link from the email.
The solution to this is to set confirmed_at value to Time.now before sign_in
e.g.
#user = users(:valid_user)
#user.confirmed_at = Time.now
sign_in #user
after doing that the tests passed! :)

How do I log in a user with Devise for Rails controller/integration unit tests?

All the other answers are wrong or out of date. I've tried several things. This is what I have:
require 'test_helper'
class DealsControllerTest < ActionDispatch::IntegrationTest
include Devise::Test::IntegrationHelpers
setup do
#deal = deals(:one)
#user = users(:one)
# https://github.com/plataformatec/devise/wiki/How-To:-Test-controllers-with-Rails-3-and-4-(and-RSpec)
##request.env["devise.mapping"] = Devise.mappings[:one]
#sign_in #user
#log_in_as #user
ApplicationController.allow_forgery_protection = false
post user_session_path, params: {user: {email: #user.email, password: #user.password}}
assert_select "p", "Invalid Email or password."
assert_response :redirect ############ line 16
#assert_text "Invalid Email or password."
assert_redirected_to root_url
end
Failure:
DealsControllerTest#test_should_destroy_deal [C:/Users/Chloe/workspace/fortuneempire/test/controllers/deals_controller_test.rb:16]:
Expected response to be a <3XX: redirect>, but was a <200: OK>
Since it passes the "Invalid email/password" test, that means the user is NOT logging in!
I tried these answers:
How to sign in a user using Devise from a Rails console?
How to sign_in for Devise to Test Controller with Minitest
https://github.com/plataformatec/devise/wiki/How-To:-Test-controllers-with-Rails-3-and-4-(and-RSpec)
Rails: Capybara can't log in user with Devise fixture data
This worked
require 'test_helper'
class DealsControllerTest < ActionDispatch::IntegrationTest
include Warden::Test::Helpers
setup do
#deal = deals(:one)
#user = users(:one)
# https://github.com/plataformatec/devise/wiki/How-To:-Test-with-Capybara
#user.confirmed_at = Time.now
#user.save
login_as(#user, :scope => :user)
end
teardown do
Warden.test_reset!
end

How to stub current_user in Rails 5?

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.

Login as a specific user with RSpec

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

How to sign_in for Devise to Test Controller with Minitest

I'm newbie to Rails Testing.
After following some tutorial online, I could able to setup and run testing for Model.
But when trying to test for Controller, Testing was failed as it is redirected to login page.
I've tried every instruction I can find on web to sign in for devise and still couldn't able to sign in and move forward.
Appreciate if someone could help and give me a direction to move forward.
AwardedBidsControllerTest
test_should_get_index FAIL (0.45s)
MiniTest::Assertion: Expected response to be a <:success>, but was <302>
Below is my setup
test/test_helper.rb
ENV["RAILS_ENV"] = "test"
require File.expand_path("../../config/environment", __FILE__)
require "rails/test_help"
require "minitest/rails"
require "minitest/reporters"
Minitest::Reporters.use!(
Minitest::Reporters::SpecReporter.new,
ENV,
Minitest.backtrace_filter
)
class ActiveSupport::TestCase
fixtures :all
include FactoryGirl::Syntax::Methods
end
class ActionController::TestCase
include Devise::TestHelpers
end
test/controllers/awarded_bids_controller_test.rb
require "test_helper"
class AwardedBidsControllerTest < ActionController::TestCase
test "should get index" do
user = create(:user)
sign_in user
get :index
assert_response :success
end
end
app/controllers/awarded_bids_controller.rb
class AwardedBidsController < ApplicationController
before_filter :authenticate_user!
def index
#awarded_bids = AwardedBid.all
respond_to do |format|
format.html # index.html.erb
format.json { render json: #awarded_bids }
end
end
end
test/factories/users.rb
#using :login instead of :email.
FactoryGirl.define do
factory :user do |u|
u.login "user"
u.name "Normal"
u.surname "User"
u.password "Abc2011"
end
end
Below is the version info.,
JRuby 1.7.21(Ruby 1.9.3)
Rails 3.2.22
Devise 3.0.4
Minitest 4.7.5
From integration_helpers.rb, for example:
class PostsTest < ActionDispatch::IntegrationTest
include Devise::Test::IntegrationHelpers
test 'authenticated users can see posts' do
sign_in users(:bob)
get '/posts'
assert_response :success
end
end
In your test_helper.rb file's ActiveSupport::TestCase class, add a new method log_in_as like this:
require "test_helper"
ENV["RAILS_ENV"] = "test"
require File.expand_path("../../config/environment", __FILE__)
require "rails/test_help"
require "minitest/rails"
require "minitest/reporters"
Minitest::Reporters.use!(
Minitest::Reporters::SpecReporter.new,
ENV,
Minitest.backtrace_filter
)
class ActiveSupport::TestCase
fixtures :all
include FactoryGirl::Syntax::Methods
# Returns true if a test user is logged in.
def is_logged_in?
!session[:user_id].nil?
end
# Logs in a test user.
def log_in_as(user, options = {})
password = options[:password] || 'password'
remember_me = options[:remember_me] || '1'
if integration_test?
post login_path, session: { email: user.email,
password: password,
remember_me: remember_me }
else
session[:user_id] = user.id
end
end
private
# Returns true inside an integration test.
def integration_test?
defined?(post_via_redirect)
end
end
class ActionController::TestCase
include Devise::TestHelpers
end
Then, use this log_in_as method instead of sign_in in your test:
require "test_helper"
class AwardedBidsControllerTest < ActionController::TestCase
test "should get index" do
user = create(:user)
log_in_as user
get :index
assert_response :success
end
end

Resources