I currently trying to test a symfony app that has secured pages, using functional tests.
When I browse the secured page, instead of a 200 HTTP
code, I get a 401 "Unauthorized" HTTP code
, meaning I'm trying to access a page without being authenticated/without having the right credentials.
Even if I log as a normal user, that have the proper symfony credentials, I still get a 401 error
.
//CapWebndfTestFunctional.class.php
class CapWebndfTestFunctional extends sfTestFunctional
{
/**
* Login as a user
* @param string $username User's username
*/
public function signInAs($username)
{
$user = Doctrine_Core::getTable('sfGuardUser')->findOneByUsername($username);
//force the context to be created
$this->browser->getContext(true)->getUser()->signIn($user);
$this->info(sprintf('Signin user using username "%s"', $username));
if ($user->getIsSuperAdmin())
{
$this->info('Beware, you are logged as a superadmin!');
}
return $this;
}
}
Test suite:
<?php
$browser = new CapWebndfTestFunctional(new sfBrowser());
$browser->
signInAs('superadmin')->
with('user')->begin()->
isAuthenticated()-> //ensure that I'm well authenticated
end()->
get('/document')-> //a secured page
with('request')->begin()->
isParameter('module', 'document')->
isParameter('action', 'index')->
end()->
with('response')->begin()->
isStatusCode(200)-> //as superadmin is a sfGuard superadmin, this should be 200;
end()->
// Here some other tests...
/* Outputs :
clem@ubuntu:/var/www/cap_webndf/trunk$ php symfony test:functional backend documentActions
> Signin user using username "superadmin"
> Beware, you are logged as a superadmin!
ok 1 - user is authenticated
# get /document
ok 2 - request parameter module is document
ok 3 - request parameter action is index
not ok 4 - status code is 200
# Failed test (./lib/vendor/symfony/lib/test/sfTesterResponse.class.php at line 412)
# got: 401
# expected: 200
*/
I'm really stuck on this one, so thank you for any help.
Edit: If you prefer, here is the used code on a gist
EDIT: What is the difference between going to the login page and sending a (fake) post request, and directly signin in using the dedicated sfGuard method?
I don't think you can use SignIn() like that as it would not set the cookie within the browser so on the next page you would be logged out again.
Whenever I have done functional testing with users I have gone to the login page and entered the username/password of the user and logged in as them.
I haven't tested this but something like this should work, I normally use test users and know their password
//CapWebndfTestFunctionnal.class.php
class CapWebndfTestFunctionnal extends sfTestFunctional
{
/**
* Login as a user
* @param string $username User's username
*/
public function signInAs($username)
{
$tempPassword = rand(1000, 9999999);
$user = Doctrine_Core::getTable('sfGuardUser')->findOneByUsername($username);
$oldPassword = $user->getPassword();
$user->setPassword($tempPassword);
$user->save();
$this->info(sprintf('Signin user using username "%s"', $username));
$this->post('/login', array('username' => $user->getUsername(), 'password' => $tempPassword))->isRedirected();
if ($user->getIsSuperAdmin())
{
$this->info('Beware, you are logged as a superadmin!');
}
$user->setPasswordHash($oldPassword);
$user->save();
return $this;
}
}