Reputation: 4896
I am writing a functional test for a page that requires user authentication. I am using the sfDoctrineGuard plugin.
How do I authenticate a user in my test?
Do I have to enter every test through the sign in screen?
Here is my incorrect code:
$b->post('/sfGuardAuth/signin',
array('signin[password]' => 'password',
'signin[username]' => 'user',
'signin[_csrf_token]' => '7bd809388ed8bf763fc5fccc255d042e'))->
with('response')->begin()->
checkElement('h2', 'Welcome Humans')->
end()
Thank you
Upvotes: 4
Views: 1375
Reputation:
The tricky part about doing a signin is that the test browser wipes out the context object before each request (see sfBrowser::call()).
You can authenticate the user by injecting a listener which will call the user's signIn()
method when the context.load_factories
event fires during context initialization:
function signin( sfEvent $event )
{
/* @var $user sfGuardSecurityUser */
if( ! $user = $event->getSubject()->getUser() )
{
throw new RuntimeException('User object not created.');
}
if( ! $user instanceof sfGuardSecurityUser )
{
throw new LogicException(sprintf(
'Cannot log in %s; sfGuardSecurityUser expected.',
get_class($user)
));
}
if( $user->isAuthenticated() )
{
$user->signOut();
}
/* Magic happens here: */
$user->signIn($desired_user_to_log_in_as);
$event->getSubject()->getEventDispatcher()->notify(new sfEvent(
$this,
'application.log',
array(sprintf('User is logged in as "%s".', $user->getUsername()))
));
}
/* Set signin() to fire when the browser inits the context for subsequent
* requests.
*/
$b->addListener('context.load_factories', 'signin');
This will cause the browser to sign in the user for all subsequent requests. Note that sfBrowser
does not have a removeListener()
method.
Adapted from sfJwtPhpUnitPlugin (FD: I'm the lead dev for this project).
Upvotes: 6
Reputation: 237865
Yes, you do have to sign in to carry out tests. Fortunately, this is much simpler than the method you illustrate above. See the "better and simpler way" on this blog post.
You could make the signin
method part of any TestFunctional
class according to how you've structured your tests.
Upvotes: 3