Skip to content

Commit

Permalink
Completely rewrote Authlogic::Testing, it's now called Authlogic::Tes…
Browse files Browse the repository at this point in the history
…tCase. Testing Authlogic is much easier now. Please see Authlogic::TestCase for more info.
  • Loading branch information
binarylogic committed Mar 26, 2009
1 parent 56e9dd1 commit 26e57e6
Show file tree
Hide file tree
Showing 20 changed files with 202 additions and 158 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.rdoc
Expand Up @@ -4,6 +4,7 @@
* Fixed human_name for the model to use its own human name and not delegate to the associated model. Translation should be under authlogic.models.user_session (or whatever the name of your session is).
* Fixed human_attribute_name to use Authlogic keys for translation instead of ActiveRecord: authlogic.attributes.user_session.login
* For transitioning from restful_authentication, set the REST_AUTH_SITE_KEY to '' if it doesn't exist, instead of nil.
* Completely rewrote Authlogic::Testing, it's now called Authlogic::TestCase. Testing Authlogic is much easier now. Please see Authlogic::TestCase for more info.

== 2.0.2 released 2009-3-24

Expand Down
9 changes: 5 additions & 4 deletions Manifest.txt
Expand Up @@ -54,7 +54,10 @@ lib/authlogic/session/session.rb
lib/authlogic/session/timeout.rb
lib/authlogic/session/unauthorized_record.rb
lib/authlogic/session/validation.rb
lib/authlogic/testing/test_unit_helpers.rb
lib/authlogic/test_case.rb
lib/authlogic/test_case/mock_controller.rb
lib/authlogic/test_case/mock_cookie_jar.rb
lib/authlogic/test_case/mock_request.rb
lib/authlogic/version.rb
shoulda_macros/authlogic.rb
test/acts_as_authentic_test/base_test.rb
Expand All @@ -65,6 +68,7 @@ test/acts_as_authentic_test/magic_columns_test.rb
test/acts_as_authentic_test/password_test.rb
test/acts_as_authentic_test/perishable_token_test.rb
test/acts_as_authentic_test/persistence_token_test.rb
test/acts_as_authentic_test/restful_authentication_test.rb
test/acts_as_authentic_test/session_maintenance_test.rb
test/acts_as_authentic_test/single_access_test.rb
test/authenticates_many_test.rb
Expand All @@ -79,9 +83,6 @@ test/fixtures/users.yml
test/libs/company.rb
test/libs/employee.rb
test/libs/employee_session.rb
test/libs/mock_controller.rb
test/libs/mock_cookie_jar.rb
test/libs/mock_request.rb
test/libs/ordered_hash.rb
test/libs/project.rb
test/libs/user.rb
Expand Down
8 changes: 4 additions & 4 deletions README.rdoc
Expand Up @@ -62,18 +62,18 @@ These modules are for the acts_as_authentic method you call in your model. It co

These modules are for the "session side" of authentication. They create a new domain for session logic, allowing you to create, destroy, and ultimately manage your sessions.

* Authlogic::Session::BruteForceProtection - Disables accounts after a certain number of consecutive failed login attempted.
* Authlogic::Session::Callbacks - Your tools to extend Authlogic, lets you hook in and add/modify behavior, on top of overriding methods.
* Authlogic::Session::BruteForceProtection - Disables accounts after a certain number of consecutive failed logins attempted.
* Authlogic::Session::Callbacks - Your tools to extend, change, or add onto Authlogic. Lets you hook in and do just about anything you want.
* Authlogic::Session::Cookies - Authentication via cookies.
* Authlogic::Session::Existence - Creating, saving, and destroying objects.
* Authlogic::Session::HttpAuth - Authentication via basic HTTP authentication.
* Authlogic::Session::Id - Allows sessions to be separated by an id, letting you have multiple sessions for a single user.
* Authlogic::Session::MagicColumns - Maintains "magic" database columns, similar to created_at and updated_at for ActiveRecord.
* Authlogic::Session::MagicStates - Automatically validates based on the records states: active, approved, and confirmed.
* Authlogic::Session::MagicStates - Automatically validates based on the records states: active?, approved?, and confirmed?. If those methods exist for the record.
* Authlogic::Session::Params - Authentication via params, aka single access token.
* Authlogic::Session::Password - Authentication via a traditional username and password.
* Authlogic::Session::Persistence - Persisting sessions / finding sessions.
* Authlogic::Session::Session - Authentication via the session.
* Authlogic::Session::Session - Authentication via the session, the controller session that is.
* Authlogic::Session::Timeout - Automatically logging out after a certain period of inactivity.
* Authlogic::Session::UnauthorizedRecord - Handles authentication by passing an ActiveRecord object.
* Authlogic::Session::Validation - Validation / errors.
Expand Down
21 changes: 16 additions & 5 deletions lib/authlogic/session/callbacks.rb
@@ -1,8 +1,16 @@
module Authlogic
module Session
# Just like in ActiveRecord you have before_save, before_validation, etc. You have similar callbacks with Authlogic, see the METHODS constant below. The order of execution is as follows:
# Between these callsbacks and the configuration, this is the contract between me and you to safely
# modify Authlogic's behavior. The ONLY reason these things will change is during a big version upgrade.
# For example, going from v1.X.X to 2.0.0.
#
# Here is the order they execute
# Check out the sub modules of Authlogic::Session. They are very concise, clear, and to the point. More
# importantly they use the same API that you would use to extend Authlogic. That being said, they are great
# examples of how to extend Authlogic and add / modify behavior. These modules could easily be pulled out
# into their own plugin and become an "add on" without any change.
#
# Now to the point of this module. Just like in ActiveRecord you have before_save, before_validation, etc.
# You have similar callbacks with Authlogic, see the METHODS constant below. The order of execution is as follows:
#
# before_persisting
# persist
Expand All @@ -27,11 +35,13 @@ module Session
# [save record if record.changed?]
#
# before_destroy
# [save record if record.changed?]
# destroy
# after_destroy
#
# Notice the "save record if changed?" lines above. This helps with performance. If you need to make changes to the associated record, there is no need to save the record, Authlogic will do it for you.
# This allow multiple modules to modify the record and execute as few queries as possible.
# Notice the "save record if changed?" lines above. This helps with performance. If you need to make
# changes to the associated record, there is no need to save the record, Authlogic will do it for you.
# This allows multiple modules to modify the record and execute as few queries as possible.
#
# **WARNING**: unlike ActiveRecord, these callbacks must be set up on the class level:
#
Expand All @@ -41,7 +51,8 @@ module Session
# # ..etc
# end
#
# You can NOT define a "before_validation" method, this is bad practice and does not allow Authlogic to extend properly with multiple extensions. Please ONLY use the method above.
# You can NOT define a "before_validation" method, this is bad practice and does not allow Authlogic
# to extend properly with multiple extensions. Please ONLY use the method above.
module Callbacks
METHODS = [
"before_persisting", "persist", "after_persisting",
Expand Down
1 change: 1 addition & 0 deletions lib/authlogic/session/existence.rb
Expand Up @@ -42,6 +42,7 @@ module InstanceMethods
# the user to authenticate again if it is needed.
def destroy
before_destroy
save_record
errors.clear
@record = nil
after_destroy
Expand Down
64 changes: 64 additions & 0 deletions lib/authlogic/test_case.rb
@@ -0,0 +1,64 @@
require "authlogic/test_case/mock_cookie_jar"
require "authlogic/test_case/mock_request"
require "authlogic/test_case/mock_controller"

module Authlogic
# This is a collection of methods and classes that help you easily test Authlogic. In fact, I use these same tools
# to test the internals of Authlogic.
#
# Some important things to keep in mind when testing:
#
# Authlogic requires a "connection" to your controller. In the same manner that ActiveRecord requires a connection to
# your database. It can't do anything until it gets connnected. That being said, Authlogic will raise an
# Authlogic::Session::Activation::NotActivatedError any time you try to instantiate an object without a "connection".
# So before you do anything with Authlogic, you need to connect it. Let's walk through how to do this in tests:
#
# === Functional tests
#
# You shouldn't have to do anything. Authlogic automatically sets a before_filter in your ApplicationController that
# conntects Authlogic to the controller. So as soon as you make a request in your tests, it will connect Authlogic
# for you.
#
# === Integration tests
#
# Again, just like functional tests, you don't have to do anything. As soon as you make a request, Authlogic will be
# conntected.
#
# === Unit tests
#
# Now here is the tricky part of testing. Since there really is no controller here you need to "fake" Authlogic into
# thinking there is. Don't worry, because the Authlogic::TestCase takes care of this for you. Just do the following
# in your test's setup and you are good to go:
#
# setup :activate_authlogic
#
# activate_authlogic is a method provided to you by this TestCase module.
#
# You can even test off of this controller to make sure everything is good. For example:
#
# ben = users(:ben)
# assert_nil controller.session["user_credentials"]
# assert UserSession.create(ben)
# assert_equal controller.session["user_credentials"], ben.persistence_token
#
# You also get the "controller" method to use in your tests as well. Now you have everything you need to properly test in unit tests.
#
# === How to use
#
# Just require the file in your test_helper.rb file.
#
# require "authlogic/test_case"
module TestCase
# Activates authlogic with an Authlogic::TestCase::MockController object.
def activate_authlogic
Authlogic::Session::Base.controller = controller
end

# The Authlogic::TestCase::MockController object passed to Authlogic to activate it.
def controller
@controller ||= Authlogic::TestCase::MockController.new
end
end

::Test::Unit::TestCase.send(:include, TestCase)
end
39 changes: 39 additions & 0 deletions lib/authlogic/test_case/mock_controller.rb
@@ -0,0 +1,39 @@
module Authlogic
module TestCase
class MockController < ControllerAdapters::AbstractAdapter
attr_accessor :http_user, :http_password
attr_writer :request_content_type

def initialize
end

def authenticate_with_http_basic(&block)
yield http_user, http_password
end

def cookies
@cookies ||= MockCookieJar.new
end

def cookie_domain
nil
end

def params
@params ||= {}
end

def request
@request ||= MockRequest.new
end

def request_content_type
@request_content_type ||= "text/html"
end

def session
@session ||= {}
end
end
end
end
14 changes: 14 additions & 0 deletions lib/authlogic/test_case/mock_cookie_jar.rb
@@ -0,0 +1,14 @@
module Authlogic
module TestCase
class MockCookieJar < Hash
def [](key)
hash = super
hash && hash[:value]
end

def delete(key, options = {})
super(key)
end
end
end
end
9 changes: 9 additions & 0 deletions lib/authlogic/test_case/mock_request.rb
@@ -0,0 +1,9 @@
module Authlogic
module TestCase
class MockRequest
def remote_ip
"1.1.1.1"
end
end
end
end
39 changes: 0 additions & 39 deletions lib/authlogic/testing/test_unit_helpers.rb

This file was deleted.

36 changes: 18 additions & 18 deletions test/acts_as_authentic_test/session_maintenance_test.rb
Expand Up @@ -18,49 +18,49 @@ def test_updating_session_with_failed_magic_state
def test_update_session_after_password_modify
ben = users(:ben)
UserSession.create(ben)
old_session_key = @controller.session["user_credentials"]
old_cookie_key = @controller.cookies["user_credentials"]
old_session_key = controller.session["user_credentials"]
old_cookie_key = controller.cookies["user_credentials"]
ben.password = "newpass"
ben.password_confirmation = "newpass"
assert ben.save
assert @controller.session["user_credentials"]
assert @controller.cookies["user_credentials"]
assert_not_equal @controller.session["user_credentials"], old_session_key
assert_not_equal @controller.cookies["user_credentials"], old_cookie_key
assert controller.session["user_credentials"]
assert controller.cookies["user_credentials"]
assert_not_equal controller.session["user_credentials"], old_session_key
assert_not_equal controller.cookies["user_credentials"], old_cookie_key
end

def test_no_session_update_after_modify
ben = users(:ben)
UserSession.create(ben)
old_session_key = @controller.session["user_credentials"]
old_cookie_key = @controller.cookies["user_credentials"]
old_session_key = controller.session["user_credentials"]
old_cookie_key = controller.cookies["user_credentials"]
ben.first_name = "Ben"
assert ben.save
assert_equal @controller.session["user_credentials"], old_session_key
assert_equal @controller.cookies["user_credentials"], old_cookie_key
assert_equal controller.session["user_credentials"], old_session_key
assert_equal controller.cookies["user_credentials"], old_cookie_key
end

def test_creating_other_user
ben = users(:ben)
UserSession.create(ben)
old_session_key = @controller.session["user_credentials"]
old_cookie_key = @controller.cookies["user_credentials"]
old_session_key = controller.session["user_credentials"]
old_cookie_key = controller.cookies["user_credentials"]
assert User.create(:login => "awesome", :password => "saweet", :password_confirmation => "saweet", :email => "awesome@saweet.com")
assert_equal @controller.session["user_credentials"], old_session_key
assert_equal @controller.cookies["user_credentials"], old_cookie_key
assert_equal controller.session["user_credentials"], old_session_key
assert_equal controller.cookies["user_credentials"], old_cookie_key
end

def test_updating_other_user
ben = users(:ben)
UserSession.create(ben)
old_session_key = @controller.session["user_credentials"]
old_cookie_key = @controller.cookies["user_credentials"]
old_session_key = controller.session["user_credentials"]
old_cookie_key = controller.cookies["user_credentials"]
zack = users(:zack)
zack.password = "newpass"
zack.password_confirmation = "newpass"
assert zack.save
assert_equal @controller.session["user_credentials"], old_session_key
assert_equal @controller.cookies["user_credentials"], old_cookie_key
assert_equal controller.session["user_credentials"], old_session_key
assert_equal controller.cookies["user_credentials"], old_cookie_key
end

def test_resetting_password_when_logged_out
Expand Down
35 changes: 0 additions & 35 deletions test/libs/mock_controller.rb

This file was deleted.

1 comment on commit 26e57e6

@joshpencheon
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cool – I had been a bit puzzled how to test Authlogic previously and bodged something together, but this should make life a lot easier. Thanks. :-)

Please sign in to comment.