ariejan / baseapp

Kick it!

This URL has Read+Write access

ariejan (author)
Mon Dec 22 05:50:02 -0800 2008
commit  87f38ca6fed635154f5cb5d50c9df09aafb2d9fe
tree    f27e5605fcee5ccb13711ecc07e8c5003471d062
parent  89422374684f30d6be6031ce5c8be0fe24f9a6f7
baseapp / lib / role_requirement_test_helper.rb
100644 87 lines (76 sloc) 3.372 kb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
# Include this is test_helper.rb to enable test-case helper support for RoleRequirement via:
# include RoleRequirementTestHelper
#
# RoleRequirementTestHelper uses the power of ruby to temporarily "hijack" your target action. (don't worry, it puts things back the way it was after it runs)
# This means that the only thing that will be tested is whether or not the action can be accessed with a given circumstances.
# Any authentication you implement inside of your action will be ignored.
#
module RoleRequirementTestHelper
 
  # Makes sure a user can access the given action
  #
  # Example:
  #
  # assert_user_can_access(:quentin, "index")
  #
  def assert_user_can_access(user, actions, params = {})
    assert_user_access_check(true, user, actions, params)
  end
  
  # Makes sure a user cant access the given action
  #
  # Example:
  #
  # assert_user_cant_access(:quentin, "destroy", :listing_id => 1)
  #
  def assert_user_cant_access(user, actions, params = {})
    assert_user_access_check(false, user, actions, params)
  end
  
  # Check a list of users against a set of actions with parameters.
  #
  # Parameters:
  # users_access_list - a hash where the key is the label for a fixture, and the value is a boolean.
  # actions - a list of actions to test against
  # params - a hash containing the parameters to pass to each test call to the controller.
  #
  # Example:
  # assert_user_access(
  # {:admin => true, :quentin => false },
  # [:show, :edit],
  # {:listing_id => 1})
  def assert_users_access(users_access_list, actions, params = {})
    users_access_list.each_pair {|user, access|
      assert_user_access_check(access, user, actions, params)
    }
  end
  
  alias :assert_user_cannot_access :assert_user_cant_access
 
private
  def assert_user_access_check(should_access, user, actions, params = {})
    params = HashWithIndifferentAccess.new(params)
    
    (Array===actions ? actions : [actions]).each { |action|
      # reset the controller, request, and response
      @controller = @controller.class.new
      @request = @request.class.new
      @response = @response.class.new
      login_as user
      if should_access
        assert request_passes_role_security_system?(action, params), "request to #{@controller.class}##{action} with user #{user} and params #{params.inspect} should have passed "
      else
        assert ! request_passes_role_security_system?(action, params), "request to #{@controller.class}##{action} with user #{user} and params #{params.inspect} should have been denied"
      end
    }
  end
  
  # This is the core of the test system.
  def request_passes_role_security_system?(action, params)
    did_it_pass = false
    
    action = action.to_s
    hijacker = Hijacker.new(@controller.class)
    
    begin
      assert hijacker.hijack_instance_method(action, "@last_action_passed='#{action}'; render :text => 'passed'"), "unable to hijack method '#{action}'. Are you sure the action exists?"
      get action, params
    rescue
      assert false, "error occurred while trying to access action '#{action}' -- #{$!.to_s}.\nCheck to make sure that you are passing needed parameters.\n#{$!.backtrace * "\n"} "
    ensure
      hijacker.restore
    end
    
    did_it_pass = (action.to_s == assigns(:last_action_passed)) # make sure it actually made it through
  end
end