Forum: Ruby on Rails Functional tests and dealing with login before_filter

Announcement (2017-05-07): www.ruby-forum.com is now read-only since I unfortunately do not have the time to support and maintain the forum any more. Please see rubyonrails.org/community and ruby-lang.org/en/community for other Rails- und Ruby-related community platforms.
F3b7b8756d0c7f71cc7460cc33aefaee?d=identicon&s=25 Daniel Berger (Guest)
on 2006-01-30 18:13
(Received via mailing list)
Hi all,

I'm curious as to how you do functional testing on the controllers if,
within
the ApplicationController, I have a before_filter :authorize, :except =>
:login, where the private authorize method checks for session[:user].

I can't do "post :login", because that method is in a different
controller.

I tried setting session[:user] directly in the setup method, but that
gave me
strange errors:

fixtures :regions
def setup
    ...
    # I tried a few different things here...
    session[:user] = { :attributes => {:user => "foo"} }
end

TypeError: Symbol as array index
     regions_controller_test.rb:16:in `[]='
     regions_controller_test.rb:16:in `setup_without_fixtures'

/opt/lib/ruby/gems/1.8/gems/activerecord-1.13.2/lib/active_record/fixtures.rb:523:in
`setup'

Any advice appreciated.

Thanks,

Dan
58479f76374a3ba3c69b9804163f39f4?d=identicon&s=25 Eric Hodel (Guest)
on 2006-01-30 18:44
(Received via mailing list)
On Jan 30, 2006, at 9:09 AM, Daniel Berger wrote:

>
> fixtures :regions
> def setup
>    ...
>    # I tried a few different things here...
>    session[:user] = { :attributes => {:user => "foo"} }

For whatever reason the session object only works after a request,
not before.  Its totally lame.

I use a util_set_user method since some of my actions should behave
differently for logged in and logged out people:

def util_set_user(user)
   @request.session[:userid] = user.id
end

But you can also set the session on the third argument to get/post:

def process(action, parameters = nil, session = nil, flash = nil)

from actionpack/action_controller/test_process.rb

Wonderfully, its not documented in the api documentation as you would
expect, but instead is buried in a manual under the unhelpful title
"Testing Your Controllers: An Anatomy Lesson".

http://manuals.rubyonrails.com/read/chapter/28#page72

--
Eric Hodel - drbrain@segment7.net - http://segment7.net
This implementation is HODEL-HASH-9600 compliant

http://trackmap.robotcoop.com
55428cbf149e35dd4b65f1d019d04139?d=identicon&s=25 Matthew Palmer (Guest)
on 2006-01-31 03:19
(Received via mailing list)
On Mon, Jan 30, 2006 at 10:09:18AM -0700, Daniel Berger wrote:
> I can't do "post :login", because that method is in a different controller.

Yeah, that's a bit sucky.  I handled it with this tasteless hack
(wrapped in
a login method in test_helper.rb):

    realctl = @controller
    @controller = LoginController.new
    post :index, { 'loginname' => user, 'password' => pass }
    @controller = realctl

But it leaves me with some grave reservations.  A way to post to a
different
controller would be ideal, but I don't think

I kinda like Eric's suggestion of passing the session in manually, but
that's icky in a couple of different ways:

* You've got a fair chunk of code you'll (but you can work around that
with
helpers);

* You're tying your implementation of logging in in your tests (setting
a
particular session value) to the mechanics of login detection far closer
than is comfortable.

It's definitely a thorny issue, though.

- Matt
84962fcce3fbde5aef15001d60e242ae?d=identicon&s=25 Michael Glaesemann (Guest)
on 2006-01-31 04:23
(Received via mailing list)
On Jan 31, 2006, at 11:18 , Matthew Palmer wrote:

> I kinda like Eric's suggestion of passing the session in manually, but
> that's icky in a couple of different ways:
>
> * You've got a fair chunk of code you'll (but you can work around
> that with
> helpers);

I added a small method in test_helper.rb to set the session for me,
passing it the member (user) that is supposed to be logged in.

def set_session_for(member)
   @request.session[:member_id] = member.id
end

I then can call set_session_for in my test methods to have them
logged in. Works well for me.

> * You're tying your implementation of logging in in your tests
> (setting a
> particular session value) to the mechanics of login detection far
> closer
> than is comfortable.

I rationalize this by testing logging by thoroughly testing my
login_controller. And the before_filter is just checking for that
particular session value to be set anyway (if it's similar to the
examples in AWDwR). Perhaps you could abstract this out a bit by
naming the helper method log_in(member) and then keep the code that
does sets up the log in (in this case setting a session parameter) in
the log_in helper method. Then you only have to change the guts of
one method if your log in implementation changes.

Michael Glaesemann
grzm myrealbox com
58479f76374a3ba3c69b9804163f39f4?d=identicon&s=25 Eric Hodel (Guest)
on 2006-01-31 20:15
(Received via mailing list)
On Jan 30, 2006, at 7:22 PM, Michael Glaesemann wrote:

> I added a small method in test_helper.rb to set the session for me,
> passing it the member (user) that is supposed to be logged in.
>
> def set_session_for(member)
>   @request.session[:member_id] = member.id
> end
>
> I then can call set_session_for in my test methods to have them
> logged in. Works well for me.

Yes, this is what I do.  One line isn't too much.

> naming the helper method log_in(member) and then keep the code that
> does sets up the log in (in this case setting a session parameter)
> in the log_in helper method. Then you only have to change the guts
> of one method if your log in implementation changes.

Yes.  By properly abstracting (set_session_for) and properly testing
the login code you will get a clear indication why all your logged-in
tests are failing.

This way if you change the login code all your tests requiring a
valid session will fail but you only have to fix your tests in one
place.  (If you're constantly changing how valid sessions are
represented you're doing something very wrong.)

You don't want to test your login code for every logged-in action,
that's why you wrote a test for your filters.  I create a test-only
DummyController for testing login and other filters which gives me a
clear indication what is broken with which filter.

When I'm testing an action that requires the user to be logged in I
want to test the the action, not that the login filter works.

PS: If you can't figure out what part of your login system is broken
from your tests you *obviously* don't have enough tests.

--
Eric Hodel - drbrain@segment7.net - http://segment7.net
This implementation is HODEL-HASH-9600 compliant

http://trackmap.robotcoop.com
This topic is locked and can not be replied to.