[Stories] Login and subdomain

I’ve just begin using rspec stories, and i m encountering some
problems. In my application i have different subdomains in which
specific users can log in, for example an admin will go to
admin.myapp.com/authenticate/login, and an user belonging to a
specific company will log in company.myapp.com/authenticate/login, and
of course both have a different login process.

To perform some actions the user has to be logged in, and this is
where the problem comes, how to test these actions ?

  • Is there a way to set a user as logged in ? (that would definitely
    be very convenient)

So far I have tried to do the following :

post “/authenticate/login”,
{:login => user_email,
:password => password }

but the problem is that it doesn’t use the correct subdomain and the
login, as expected in that case, fails, so how to define the correct
subdomain ?

Thank you in advance for your help.

On Wed, Mar 5, 2008 at 4:30 PM, Bastien [email protected]
wrote:

  • Is there a way to set a user as logged in ? (that would definitely
    subdomain ?
    RailsStory wraps ActionController::IntegrationTest, which delegates
    calls to ActionController::Integration::Session. Check out the rdoc
    (Peak Obsession)
    and you’ll see a host! method
    (Peak Obsession).
    So …

host! “whatever subdomain”
post “/authenticate/login”, …

Cheers,
David

I think you can also use:

post “/authentication/login”,
{ :login => user_email,
:password => password },
:host => “company.example.com

Op 5-mrt-08, om 23:30 heeft Bastien het volgende geschreven:

Thanks David, this works just fine. I would rather do some stubbing
there if it’s possible though. I tried :

ApplicationController.stub!
(:user_authentication_required).and_return(true)

(which is the filter called before each action that checks whether the
user is logged in or not)
But it doesn’t work. When I do this :

class ApplicationController
def user_authentication_required
return true
end
end

it works fine (but I find it quite dirty to redefine my method that
way). Aren’t this two solutions supposed to give me the same result ?
Is something wrong with my stubbing ?

On Thu, Mar 6, 2008 at 7:12 AM, Bastien [email protected]
wrote:

Thanks David, this works just fine. I would rather do some stubbing
there if it’s possible though. I tried :

ApplicationController.stub!
(:user_authentication_required).and_return(true)

try
controller.stub!(…)

Pat

You should not stub the authentication method in a story. The story
should test the whole application framework, that way your story might
look like this:

Given a user from company x
When logging in
And requesting some page
Then the application should do all the stuff it should

In the given step you set your host, user name and password and you
create that user.
In the when steps you make the login request and then you can start
doing the stuff you really want to test here as you’ll have the
session you want at that moment.

Regards
Ivo D.

Op 6-mrt-08, om 16:12 heeft Bastien het volgende geschreven:

On Thu, Mar 6, 2008 at 7:23 AM, Pat M. [email protected] wrote:

On Thu, Mar 6, 2008 at 7:12 AM, Bastien [email protected] wrote:

Thanks David, this works just fine. I would rather do some stubbing
there if it’s possible though. I tried :

ApplicationController.stub!
(:user_authentication_required).and_return(true)

try
controller.stub!(…)

Perhaps I should explain why this is. stub! adds a stubbed method to
an object. In Ruby, classes are objects as well, so what you’ve done
is to stub a method on the ApplicationController class object itself -
effectively creating a class method. When you override the method
yourself, you’re overriding an instance method. So in order to stub
out the method for a request, you want to stub it on the instance of
the controller being used in the test. That controller instance is
made available to you through a method named “controller”.

Pat

Thanks for your help.
I tried the controller.stub!(…) as well, and it doesn’t work.

Ivo I totally agree with you and I’ll follow your recommendations,
thanks.

(Would still be nice to know if the stubbing could work or if it’s
intended not to)

On Thu, Mar 6, 2008 at 10:38 AM, Pat M. [email protected] wrote:

In the given step you set your host, user name and password and you
create that user.
In the when steps you make the login request and then you can start
doing the stuff you really want to test here as you’ll have the
session you want at that moment.

That’s a little too dogmatic for me. You needn’t go through the
entire stack every story, and you needn’t go through the entire app
path either.

IMO you should be simulating as much as possible what the user is
doing. If they have to go through path a, b, c … to get to Z, then
so be it. This involves keeping a well-factored set of helpers which
can be used to navigate the app just like a user would.

The only things you probably should be stubbing in a story are third
party components your site may have to integrate with that aren’t
realistic to be run for every story (for the most part, there are
other exceptions as well I know). I would avoid stubbing core
functionality related to your site,

On Thu, Mar 6, 2008 at 7:27 AM, Ivo D. [email protected] wrote:

create that user.
In the when steps you make the login request and then you can start
doing the stuff you really want to test here as you’ll have the
session you want at that moment.

That’s a little too dogmatic for me. You needn’t go through the
entire stack every story, and you needn’t go through the entire app
path either.

That said, I think you want to keep stubbing to an absolute minimum.
I only stub out stuff that hits external services - even then I have a
“full integration mode” that runs the same tests but DOES hit the real
services (assuming they provide a sandbox or I have some other
innocuous way to mess with stuff).

Sometimes I’m lazy about the login step and will do
controller.send(:current_user=, User.find(1)) if I don’t feel there’s
any benefit at all to making a login request.

Pat

I found it a little confusing to stub my authentication filters as well,
but
figured it out with a little help from the interwebs:

in spec_helper i have this:

describe “a controller requiring login”, :shared => true do
it “should have login_required set in the before filter” do
controller.class.before_filters.should include(:login_required)
end
end

def mock_login_required(allow_user_to_pass=true)
controller.stub!(:login_required).and_return(allow_user_to_pass)
end

Then, in any spec where i want to mock that filter, i just write

it_should_behave_like “a controller requiring login”

at the top of the describe block.

Sorry, i can’t remember the web page where i found this solution but
respect
to whoever posted it :slight_smile:

We do something very very similar but rather then
it_should_behave_like we wrap it in a it_requires_login method…

describe SomeController do
it_requires_login
end

Zach

On Fri, Mar 7, 2008 at 11:53 AM, Max W.

Oh, sorry, and this line in your specs to actually mock the filter:

mock_login_required

:slight_smile:

Thanks to all of you, I added the login as a part of the story and now
it works smoothly.

In case it isn’t clear… I agree with Ivo’s statement:

“You should not stub the authentication method in a story. The story
should test the whole application framework”.

emphasis on “story”

Zach