Rails integration test with the devise gem

devise::test helpers
devise gem rails api
devise rb
devise controller
devise registerable
rails authentication
devise configure_permitted_parameters
rails controller test authentication

I want to write an rails integration test (with ActionDispatch::IntegrationTest). I am using devise for authentication and machinist for test models. I cannot successfully sign in.

Here is a simple example:

class UserFlowsTest < ActionDispatch::IntegrationTest
  setup do
    User.make
  end
  test "sign in to the site" 
    # sign in
    post_via_redirect 'users/sign_in', :email => 'foo@bar.com', :password => 'qwerty'    
    p flash
    p User.all
end

Here is the debug output:

Loaded suite test/integration/user_flows_test
Started
{:alert=>"Invalid email or password."}
[#<User id: 980190962, email: "", encrypted_password: "", password_salt: "", reset_password_token: nil, remember_token: nil, remember_created_at: nil, sign_in_count: 0, current_sign_in_at: nil, last_sign_in_at: nil, current_sign_in_ip: nil, last_sign_in_ip: nil, created_at: "2010-11-27 16:44:10", updated_at: "2010-11-27 16:44:10">, #<User id: 980190963, email: "foo@bar.com", encrypted_password: "$2a$10$vYSpjIfAd.Irl6eFvhJL0uAwp4qniv5gVl4O.Hnw/BUR...", password_salt: "$2a$10$vYSpjIfAd.Irl6eFvhJL0u", reset_password_token: nil, remember_token: nil, remember_created_at: nil, sign_in_count: 0, current_sign_in_at: nil, last_sign_in_at: nil, current_sign_in_ip: nil, last_sign_in_ip: nil, created_at: "2010-11-27 17:09:13", updated_at: "2010-11-27 17:09:13">]
"/unauthenticated"
F

Here is my blueprints.rb:

require 'machinist/active_record'
require 'sham'

User.blueprint do
  email {"foo@bar.com"}
  password {"qwerty"}
end

The reason it doesn't work is devise creates form field names as

'user[email]'
'user[password]'

and post_via_redirect expects those names as arguments. So following statement would make a successful login.

post_via_redirect 'users/sign_in', 'user[email]' => 'foo@bar.com', 'user[password]' => 'qwerty' 

Devise::TestHelpers inclusion in Rails 5 · Issue #3913 · heartcombo , It looks like in Rails 5 you can add gem 'rails-controller-testing' to keep using the old controller tests. I haven't tried this but it might help someone. Devise works with multiple Ruby and Rails versions, and ActiveRecord and Mongoid ORMs, which means you can run the test suite with some modifiers: DEVISE_ORM and BUNDLE_GEMFILE.

First of all, with devise, you may have to "confirm" the user.

you can do something like this:

user = User.make!
user.confirmed_at = Time.now
user.save!

Here is an example without Machinist (but you just have to replace the user creation code portion with the part above):

into test_integration_helper:

require "test_helper"
require "capybara/rails"

    module ActionController
      class IntegrationTest
        include Capybara

        def sign_in_as(user, password)
           user = User.create(:password => password, :password_confirmation => password, :email => user)
           user.confirmed_at = Time.now 
           user.save!
           visit '/'
           click_link_or_button('Log in')
           fill_in 'Email', :with => user.email
           fill_in 'Password', :with => password
           click_link_or_button('Sign in')
           user      
         end 
         def sign_out
            click_link_or_button('Log Out')   
         end
      end
    end

And into your integration_test:

require 'test_integration_helper'

class UsersIntegrationTest < ActionController::IntegrationTest

  test "sign in and then sign out" do 
    #this helper method is into the test_integration_helper file                   
    sign_in_as("lolz@gmail.com", "monkey")         
    assert page.has_content?('Signed in successfully'), "Signed in successfully"

    sign_out         
    assert page.has_content?('Signed out successfully'), "Signed out successfully" 
  end
end

A simple login test with Rails, Devise and Minitest, For Rails developers, it seems to be often that you use Devise gem for and you'​re going to test controller methods (or views, integration tests). However, you ought to test the parts of your app which interface with Devise, to ensure that Devise is presented with correct data, and to ensure that Devise remains in general working order. Also, your own app’s tests are very likely to depend on your having a logged-in user, on whose behalf, the various operations of controller, acceptance, integration and view tests, are performed.

I don't have a sample integration test in the book for Devise, but I think the code in the step definition in the Cucumber chapter will also work if you have Webrat/Capybara installed:

@user = User.create!(:email => "email@email.com",  
            :password => "password",  
            :password_confirmation => "password")
visit "login"  
fill_in("user_email", :with => @user.email)  
fill_in("user_password", :with => "password") 
click_button("Sign In")

A simple login test with RSpec, Devise, FactoryBot in Rails, For Rails developers, it seems to be often that you use Devise gem for and you'​re going to test controller methods (or views, integration tests). rvm use 1.9.3-p125@devise-integration-signin. gem install rails rails new devise-integration-signin cd devise-integration-signin mate . Add gem 'devise' to Gemfile. bundle install. rails generate devise:install rails generate devise user. bundle exec rake db:migrate. include Devise helper (not really needed here) in test_helper.rb. Add fixture

In case anyone else has a similar problem...

I was in a similar situation (migrating from Authlogic), and had this exact same problem. The issue was in the devise.rb initializer. By default it sets up your test environment to use only 1 stretch during the encryption/decryption of passwords. I honestly don't know what a stretch is, but for Devise to work with old Authlogic encrypted passwords, the stretches has to be 20. Since I was trying to sign in a user that originally had their password encrypted by Authlogic in my test, Devise needs to use 20 stretches in test also. I changed the config like below:

# Limiting the stretches to just one in testing will increase the performance of
# your test suite dramatically. However, it is STRONGLY RECOMMENDED to not use
# a value less than 10 in other environments.
-  config.stretches = Rails.env.test? ? 1 : 20
+  config.stretches = 20

Module: Devise::Test::ControllerHelpers, Do not use `Devise::Test::ControllerHelpers` in integration tests. Examples class PostsTest < ActionController::TestCase include Devise  rails new integration-testing-minitest We’ll need to add Capybara to our Gemfile in the group test. This can be done at the bottom of the file. Note that we’re using a gem called minitest-rails-capybara, which integrates Capybara with Minitest and Rails.

Since you are using ActionDispatch::IntegrationTest, you can include the Devise::Test::IntegrationHelpers module and use the sign_in method instead (which you can pass a user to):

class UserFlowsTest < ActionDispatch::IntegrationTest
  include Devise::Test::IntegrationHelpers

  test "sign in to the site" do
    sign_in users(:one)
  end
end

Setting up Rails testing with rspec, devise, and the gang, group :development, :test do gem 'rspec-rails' gem 'factory_girl_rails' is the rails integration with factory_girl. guard-rspec is rspec integration  RailsApps Testing is a utility gem to use during development. You can remove it after setting up your test framework. It was originally written for use by the Rails Composer tool. Use Rails Composer to build any of the RailApps example applications for use as starter apps.

How to use Devise Test Helpers (Example), Getting started - Controller filters and helpers - Configuring Models - Strong To run the test suite, go into Devise's top-level directory and run Inside the gemfiles directory, we have one for each version of Rails we support. This gem brings back assigns to your controller tests as well as assert_template to both controller and integration tests. Note: This gem is only useful once assigns and assert_template have been removed from Rails. Installation. Add this line to your application's Gemfile: gem 'rails-controller-testing' And then execute: $ bundle Or install it

heartcombo/devise: Flexible authentication solution for Rails with , Setup and test Rails 6.0 with RSpec, FactoryBot, and Devise First, add the latest RSpec gem to your Gemfile : Gemfile Create controller test. Testing Rails ApplicationsThis guide covers built-in mechanisms in Rails for testing your application.After reading this guide, you will know: Rails testing terminology. How to write unit, functional, integration, and system tests for your application. Other popular testing approaches and plugins.

Setup and test Rails 6.0 with RSpec, FactoryBot, and Devise , Tagged with ruby, rails, testing, authentication. Previously, I wrote a blog post on how to create an authentication system for Rails API with the devise_token_auth gem. risafj image #rails #ruby #devisetokenauth #​authentication How do you write controller tests for functions that require authentication? Integration testing Devise with RSpec and Capybara 1 minute read I use Rails quite a bit for development and recently noticed that my unit tests were quite indepth but that my integration tests were lacking. So I recently had a flick through Rails Test Prescriptions, then took a gander at other people’s code on Github, and decided

Comments
  • I recently began reading Rails Test Prescriptions (pragprog.com/titles/nrtest/rails-test-prescriptions). Fairly early in the book, Noel mentions he will be using Devise for authentication. I jumped over to github.com to look at his sample application (github.com/noelrappin/huddle) to see if he solves this problem. While he doesn't feature any integration tests I'm posting it here for reference.
  • I've also switched (back) to using AuthLogic (github.com/binarylogic/authlogic) for authentication in my application. I've used it before and like it much better than Devise.
  • Just in case it helps - in my case because it was an integration test of JSON only post_via_redirect 'users/sign_in', user: { email: "foo@bar.com", password: "qwerty" }, format: :json worked.
  • Thanks for response. I'll have to dig up that project again and see how this works. +1 for now.
  • Thanks for response. I'll have to dig up that project again and see how this works. +1 for now. Also, thanks for the good read :)