Back to Repositories

Testing Database Authentication Mechanisms in Devise

This integration test suite validates Devise’s database authentication functionality, focusing on email case sensitivity, whitespace handling, and authentication key validation. The tests ensure robust user authentication behavior across different configuration scenarios.

Test Coverage Overview

The test suite comprehensively covers database authentication edge cases in Devise:

  • Email case sensitivity validation
  • Whitespace handling in credentials
  • Custom authentication key configurations
  • Error message handling and localization
  • Paranoid mode behavior testing

Implementation Analysis

The testing approach utilizes Devise’s IntegrationTest framework to validate authentication flows. It employs configuration swapping patterns to test different Devise settings and uses translation helpers for internationalization testing.

Key patterns include user creation fixtures, authentication state verification, and form interaction testing.

Technical Details

  • Uses Minitest framework with Devise test helpers
  • Implements Warden authentication verification
  • Utilizes translation storage helpers
  • Employs configuration swapping for different test scenarios
  • Includes callback testing for database authentication

Best Practices Demonstrated

The test suite exemplifies high-quality integration testing practices by isolating different authentication scenarios and thoroughly testing edge cases.

  • Comprehensive error message testing
  • Configuration-dependent behavior validation
  • Proper test isolation using swap helpers
  • Clear test naming conventions

heartcombo/devise

test/integration/database_authenticatable_test.rb

            
# frozen_string_literal: true

require 'test_helper'

class DatabaseAuthenticationTest < Devise::IntegrationTest
  test 'sign in with email of different case should succeed when email is in the list of case insensitive keys' do
    create_user(email: '[email protected]')

    sign_in_as_user do
      fill_in 'email', with: '[email protected]'
    end

    assert warden.authenticated?(:user)
  end

  test 'sign in with email of different case should fail when email is NOT the list of case insensitive keys' do
    swap Devise, case_insensitive_keys: [] do
      create_user(email: '[email protected]')

      sign_in_as_user do
        fill_in 'email', with: '[email protected]'
      end

      assert_not warden.authenticated?(:user)
    end
  end

  test 'sign in with email including extra spaces should succeed when email is in the list of strip whitespace keys' do
    create_user(email: ' [email protected] ')

    sign_in_as_user do
      fill_in 'email', with: '[email protected]'
    end

    assert warden.authenticated?(:user)
  end

  test 'sign in with email including extra spaces should fail when email is NOT the list of strip whitespace keys' do
    swap Devise, strip_whitespace_keys: [] do
      create_user(email: '[email protected]')

      sign_in_as_user do
        fill_in 'email', with: ' [email protected] '
      end

      assert_not warden.authenticated?(:user)
    end
  end

  test 'sign in should not authenticate if not using proper authentication keys' do
    swap Devise, authentication_keys: [:username] do
      sign_in_as_user
      assert_not warden.authenticated?(:user)
    end
  end

  test 'sign in with invalid email should return to sign in form with error message' do
    store_translations :en, devise: { failure: { admin: { not_found_in_database: 'Invalid email address' } } } do
      sign_in_as_admin do
        fill_in 'email', with: '[email protected]'
      end

      assert_contain 'Invalid email address'
      assert_not warden.authenticated?(:admin)
    end
  end

  test 'sign in with invalid password should return to sign in form with error message' do
    sign_in_as_admin do
      fill_in 'password', with: 'abcdef'
    end

    assert_contain 'Invalid Email or password'
    assert_not warden.authenticated?(:admin)
  end

  test 'when in paranoid mode and without a valid e-mail' do
    swap Devise, paranoid: true do
      store_translations :en, devise: { failure: { not_found_in_database: 'Not found in database' } } do
        sign_in_as_user do
          fill_in 'email', with: '[email protected]'
        end

        assert_not_contain 'Not found in database'
        assert_contain 'Invalid Email or password.'
      end
    end
  end

  test 'error message is configurable by resource name' do
    store_translations :en, devise: { failure: { admin: { invalid: "Invalid credentials" } } } do
      sign_in_as_admin do
        fill_in 'password', with: 'abcdef'
      end

      assert_contain 'Invalid credentials'
    end
  end

  test 'valid sign in calls after_database_authentication callback' do
    user = create_user(email: ' [email protected] ')

    User.expects(:find_for_database_authentication).returns user
    user.expects :after_database_authentication

    sign_in_as_user do
      fill_in 'email', with: '[email protected]'
    end
  end
end