Symfony2 Test Controller with Login and Form Submission.

How to test a controller with Symfony2 login user and then submit the form

For this test with phpunit we are going to login in, then browse to the client edit form, fill in some values and redirect, then verify that  the record is updated with the crawler by filtering  values in  the redirected list page.

This sample works when using the Symfony2 Form object, otherwise values are null when the form is submitted. There is a work around to pass values when submitting a standard form, but it is un ugly one just hard code the post values this way:

$_POST['name']='foo';

But as I say it's un ugly one, I haven't yet found a better way.

Then, to login an user we need to pass an user object as the first parameter to the UsernamePasswordToken function, and we'll be using the entity repository to find the user.

For debugging purpose you can check client reponse like this:

var_dump($this->client->getResponse());

This will give you useful information to correct things.

namespace Acme\Client\Tests\Controller;

use Symfony\Bundle\FrameworkBundle\Test\WebTestCase;
use Symfony\Component\BrowserKit\Cookie;
use Symfony\Component\Security\Core\Authentication\Token\UsernamePasswordToken;
/**
 * Tests for DefaultController class
 *
 * 2013-12-17 freedelta
 */
class DefaultControllerTest extends WebTestCase
{
    private $em = null;
    private $client = null;

    public function setUp()
    {
        $this->client = static::createClient();
        $this->em = $this->client->getContainer()->get('doctrine')->getManager();
    }

    /**
    * 1. Login
     * 2. Browse to /client_edit Form
     * 3. Fill in some values
     * 4. Submit
     * 5. Verify redirect to list home page
     */
    public function testclient_edit()
    {
        $this->logIn();
        $crawler = $this->client->request('GET', '/client_edit/1');
        $this->assertTrue($this->client->getResponse()->isSuccessful());
        $this->assertGreaterThan(0, $crawler->filter('html:contains("Update client")')->count());

        // Select based on button value, or id or name for buttons
        $frm = $crawler->selectButton('Update')->form();
        $frm['Client[fname]'] = 'First Name';
$frm['Client[lname]'] = 'Last Name';
        $frm['Client[email]'] = 'email@email.com';

        // Submit and redirect
        $crawler = $this->client->submit($frm);
        $crawler = $this->client->followRedirect();

        // Assert that we are back in list page
        $this->assertGreaterThan(0, $crawler->filter('html:contains("email@email.com")')->count());
    }
/**
* Authenticate user
*/
    private function logIn()
    {
        $session = $this->client->getContainer()->get('session');  
        $userRepository =  $this->em->getRepository('AcmeUserBundle:User');

        // Find user with rights to modify client
        $user = $userRepository->find(6);
        $firewall = 'secured_area';
        $token = new UsernamePasswordToken($user, null, $firewall, array('ROLE_ADMIN'));      
        $session->set('_security_'.$firewall, serialize($token));
        $session->save();

        $cookie = new Cookie($session->getName(), $session->getId());
        $this->client->getCookieJar()->set($cookie);
    }

    protected function tearDown()
    { 
        unset($this->em);
    }
}