Back to Repositories

Testing Trackable Authentication Module Implementation in Devise

This test suite validates the Trackable module functionality in Devise, focusing on user authentication tracking features. It ensures proper handling of user sign-in statistics, IP addresses, and timestamp tracking while maintaining data integrity.

Test Coverage Overview

The test suite comprehensively covers the Trackable module’s core functionality in Devise.

Key areas tested include:
  • Required fields validation for tracking user sign-ins
  • User sign-in statistics updates including IP addresses and timestamps
  • Persistence behavior of tracking data
  • Invalid record handling
  • Custom IP extraction functionality

Implementation Analysis

The testing approach utilizes ActiveSupport::TestCase with mock objects for request simulation.

Notable patterns include:
  • Stub method implementation for remote IP testing
  • State verification before and after tracking updates
  • Validation bypass testing
  • Inheritance-based override testing

Technical Details

Testing infrastructure includes:
  • Minitest framework integration
  • Mock object implementation for request simulation
  • ActiveSupport test helpers
  • Custom user model implementations
  • Devise model integration

Best Practices Demonstrated

The test suite exemplifies robust testing practices through:
  • Isolated test cases for specific functionality
  • Comprehensive state verification
  • Clear test case organization
  • Effective use of mock objects
  • Proper separation of concerns in testing different aspects

heartcombo/devise

test/models/trackable_test.rb

            
# frozen_string_literal: true

require 'test_helper'

class TrackableTest < ActiveSupport::TestCase
  test 'required_fields should contain the fields that Devise uses' do
    assert_equal [
      :current_sign_in_at,
      :current_sign_in_ip,
      :last_sign_in_at,
      :last_sign_in_ip,
      :sign_in_count
    ], Devise::Models::Trackable.required_fields(User)
  end

  test 'update_tracked_fields should only set attributes but not save the record' do
    user = create_user
    request = mock
    request.stubs(:remote_ip).returns("127.0.0.1")

    assert_nil user.current_sign_in_ip
    assert_nil user.last_sign_in_ip
    assert_nil user.current_sign_in_at
    assert_nil user.last_sign_in_at
    assert_equal 0, user.sign_in_count

    user.update_tracked_fields(request)

    assert_equal "127.0.0.1", user.current_sign_in_ip
    assert_equal "127.0.0.1", user.last_sign_in_ip
    assert_not_nil user.current_sign_in_at
    assert_not_nil user.last_sign_in_at
    assert_equal 1, user.sign_in_count

    user.reload

    assert_nil user.current_sign_in_ip
    assert_nil user.last_sign_in_ip
    assert_nil user.current_sign_in_at
    assert_nil user.last_sign_in_at
    assert_equal 0, user.sign_in_count
  end

  test "update_tracked_fields! should not persist invalid records" do
    user = UserWithValidations.new
    request = mock
    request.stubs(:remote_ip).returns("127.0.0.1")

    assert_not user.update_tracked_fields!(request)
    assert_not user.persisted?
  end

  test "update_tracked_fields! should not run model validations" do
    user = User.new
    request = mock
    request.stubs(:remote_ip).returns("127.0.0.1")

    user.expects(:after_validation_callback).never

    assert_not user.update_tracked_fields!(request)
  end

  test 'extract_ip_from should be overridable' do
    class UserWithOverride < User
      protected
        def extract_ip_from(request)
          "127.0.0.2"
        end
    end

    request = mock
    request.stubs(:remote_ip).returns("127.0.0.1")
    user = UserWithOverride.new

    user.update_tracked_fields(request)

    assert_equal "127.0.0.2", user.current_sign_in_ip
    assert_equal "127.0.0.2", user.last_sign_in_ip
  end
end