I'm trying to authenticate with a form_login through one test but after submitted the form it redirect to /login.
Symfony : 4.0.4, FOSUserBundle : 2.1.1
Does anynone have a clue ? (credentials and selectButton are ok)
<?php
namespace App\Tests\Controller;
use Symfony\Bundle\FrameworkBundle\Test\WebTestCase;
class CompanyControllerTest extends WebTestCase
{
/** #test */
public function companyDefaultAction_isWorking()
{
$client = static::createClient();
$crawler = $client->request('GET', '/login');
$form = $crawler->selectButton('Connexion')->form(array(
'_username' => '...',
'_password' => '...',
));
$client->submit($form);
$crawler = $client->followRedirect();
}
}
Forgot to define the environment variables for the test environment in phpunit.xml.dist :
<env name="DATABASE_URL" value="mysql://root:#127.0.0.1:3306/dbname" />
Related
Im trying to override FOSUser RegistrationController. In SF2 I used to copy the controller in my AppBundle\Controller and add bundle inheritance
class AppBundle extends Bundle
{
public function getParent()
{
return 'FOSUserBundle';
}
}
In symfony 3 the bundle inheritance is not supported anymore, and when I do the same as above, I end up with errors saying that symfony cannot find the services used in this controller (cannot autowire..)
Does anyone has an idea how to override FOSUser in SF3 please ?
<?php
// src/Acme/UserBundle/Controller/RegistrationController.php
namespace Acme\UserBundle\Controller;
use Symfony\Component\HttpFoundation\RedirectResponse;
use FOS\UserBundle\Controller\RegistrationController as BaseController;
class RegistrationController extends BaseController
{
public function registerAction()
{
$form = $this->container->get('fos_user.registration.form');
$formHandler = $this->container->get('fos_user.registration.form.handler');
$confirmationEnabled = $this->container->getParameter('fos_user.registration.confirmation.enabled');
$process = $formHandler->process($confirmationEnabled);
if ($process) {
$user = $form->getData();
/*****************************************************
* Add new functionality (e.g. log the registration) *
*****************************************************/
$this->container->get('logger')->info(
sprintf('New user registration: %s', $user)
);
if ($confirmationEnabled) {
$this->container->get('session')->set('fos_user_send_confirmation_email/email', $user->getEmail());
$route = 'fos_user_registration_check_email';
} else {
$this->authenticateUser($user);
$route = 'fos_user_registration_confirmed';
}
$this->setFlash('fos_user_success', 'registration.flash.user_created');
$url = $this->container->get('router')->generate($route);
return new RedirectResponse($url);
}
return $this->container->get('templating')->renderResponse('FOSUserBundle:Registration:register.html.twig', array(
'form' => $form->createView(),
));
}
}
from the official documentation
I'm not truly sure of my answer because i didnt override the FOS User Bundle but the Easy Admin Bundle in sf4. Here's what i did : create a new controller in src/Controller/MyCustomController. Next i extended MyCustomController with the Controller i wanted to overide :
<?php
namespace App\Controller;
use EasyCorp\Bundle\EasyAdminBundle\Controller\AdminController as BaseAdminController;
class MyCustomController extends BaseAdminController {}
?>
I guess you can do the same in sf3 with the FosUserBundle.
Hope i'm right !
I'm trying to test a form but i got unreachable field exception.
My controller's code :
class StudentController extends Controller
{
/**
* #Route("/student/new",name="create_new_student")
*/
public function newAction(Request $request){
$student = new Student();
$form = $this->createFormBuilder($student)->add('name',TextType::class)
->add('save',SubmitType::class,['label' => 'Create student'])->getForm();
$form->handleRequest($request);
if($form->isSubmitted()){
$student = $form->getData();
$name = $student->getName();
echo "Your name is ".$name;
die();
}
return $this->render(':Student:new.html.twig',['form' => $form->createView()]);
}
}
My StudentControllerTest :
class StudentControllerTest extends WebTestCase
{
public function testNew(){
$client = static::createClient();
$crawler = $client->request('POST','/student/new');
$form = $crawler->selectButton('Create student')->form();
$form['name'] = 'Student1';
$crawler = $client->submit($form);
$this->assertGreaterThan(0,$crawler->filter('html:contains("Your name is Student1")')->count());
}
}
When i run the test using phpunit i got :
InvalidArgumentException: Unreachable field "name"
I'm following the tutorial from https://symfony.com/doc/current/testing.html
You should use the $form['form_name[subject]'] syntax
public function testNew(){
$client = static::createClient();
//you should request it with GET method, it's more close to the reality
$crawler = $client->request('GET','/student/new');
$form = $crawler->selectButton('Create student')->form();
$form['form_name[name]'] = 'Student1';
// [...]
}
Try this way. Edit Test
$form = $crawler->selectButton('Create student')->form(['name' => 'Student1']);
Edit Controller:
...
$name = $student->getName();
return new Response("Your name is ". $name);
Do not kill what Symfony request.
I am using symfony 3.0 and phpunit 3.7.1.I want to submit a form via phpunit file.
File Name: abcControllerTest.php
<?php
namespace AbcBundle\Tests\Controller;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Bundle\FrameworkBundle\Test\WebTestCase;
use Symfony\Component\HttpFoundation\Request;
class AbcControllerTest extends WebTestCase {
public function testEmpty() {
$whereParams = array('params' => array(
'var' => '',
));
return $whereParams;
}
/**
* ABC Builder
* #depends testEmpty
*/
public function testAbc(array $whereParams) {
$client = static::createClient();
$crawler = $client->request('GET', $GLOBALS['host'] . '/abc/ac_file/param', $whereParams);
$buttonCrawlerNode = $crawler->selectButton('Submit');
$form = $buttonCrawlerNode->form();
$crawler = $client->submit($form);
}
}
I am testing export report functionality thats why i am just creating a submit button and trying to submit form on specific url with some parameter.
Error Message: InvalidArgumentException: The current node list is empty.
Anyone can suggest me what can i do?
When unit testing in Symfony 2, the controller I'm testing does not receive the service container causing the test to fail with the good old Call to a member function get() on a non-object
I can't use $this->forward from the testing controller as it also does not have the service container.
I found this reference but it seems as though I would be using it for the wrong reason, has anyone had any experience with this?
http://symfony.com/doc/current/book/testing.html#accessing-the-container
Edit: Here is my test:
<?php
namespace HvH\ClientsBundle\Tests\Controller;
use HvH\ClientsBundle\Controller\ClientsController;
use Symfony\Bundle\FrameworkBundle\Test\WebTestCase;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\HeaderBag;
use Symfony\Component\HttpFoundation\Session;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
class ClientsControllerTest extends WebTestCase
{
public function testGetClientsAction()
{
$client = static::createClient();
$container = $client->getContainer();
$session = $container->get('session');
$session->set('key', 'value');
$session->save();
$request = new Request;
$request->create('/clients/123456', 'GET', array(), array(), array(), array(), '');
$headers['X-Requested-With'] = "XMLHttpRequest";
$request->headers->add($headers);
/* This doesn't work */
/*
$controller = new Controller;
$status = $controller->forward( 'HvHClientsBundle:Clients:getClients', array('request' => $request) );
*/
$clients_controller = new ClientsController();
$status = $clients_controller->getClientsAction($request);
$this->assertEquals(200, $status);
}
}
Here is the part of the clients controller where it fails
<?php
namespace HvH\ClientsBundle\Controller;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Symfony\Component\HttpFoundation\Request;
use HvH\APIschemaBundle\Controller\Validation;
//FOSRestBundle
use FOS\RestBundle\View\View;
class ClientsController extends Controller
{
//Query all clients
public function getClientsAction(Request $request)
{
$request_type = $request->headers->get('X-Requested-With');
if($request_type != 'XMLHttpRequest') {
return $this->render('HvHDashboardBundle:Dashboard:dashboard.html.twig' );
}
//get any query strings
$query_strings = $request->query->all();
$definition = $this->get("service.handler")->definition_handler(__CLASS__, __FUNCTION__);
//once data has been prepared
return $this->get('fos_rest.view_handler')->handle($view);
}
}
I think the reason the controller isn't getting a container is because you are trying to instantiate and interact with it directly rather than simulating requests using the client (See the section on Functional Tests in the Testing section of the Symfony2 book).
You need something more like this (not sure if the route is correct):
public function testGetClientsAction()
{
$client = static::createClient();
$client->request(
'GET', '/clients/123456',
array(), /* request params */
array(), /* files */
array('X-Requested-With' => "XMLHttpRequest"),
);
$this->assertEquals(200, $client->getResponse()->getStatusCode());
}
Note also, the request() method returns a crawler instance which provides helper methods to verify the content of the response if required.
I have a app which uses subdomains to route to agencies:
foo.domain.dev -> Agency:showAction(foo)
bar.domain.dev -> Agency:showAction(bar)
domain.dev -> Agency:indexAction()
These each correspond to an Agency entity and controller.
I have a listener that listens for the onDomainParse event and writes the subdomain into the request attributes.
/**
* Listens for on domainParse event
* Writes to request attributes
*/
class SubdomainListener {
public function onDomainParse(Event $event)
{
$request = $event->getRequest();
$session = $request->getSession();
// Split the host name into tokens
$tokens = $this->tokenizeHost($request->getHost());
if (isset($tokens['subdomain'])){
$request->attributes->set('_subdomain',$tokens['subdomain']);
}
}
//...
}
I then use this in the controller to reroute to a show action:
class AgencyController extends Controller
{
/**
* Lists all Agency entities.
*
*/
public function indexAction()
{
// We reroute to show action here.
$subdomain = $this->getRequest()
->attributes
->get('_subdomain');
if ($subdomain)
return $this->showAction($subdomain);
$em = $this->getDoctrine()->getEntityManager();
$agencies = $em->getRepository('NordRvisnCoreBundle:Agency')->findAll();
return $this->render('NordRvisnCoreBundle:Agency:index.html.twig', array(
'agencies' => $agencies
));
}
// ...
}
My question is:
How do i fake this when doing a test with WebTestCase?
Visit the subdomain by overriding HTTP headers for the request and test for the right page:
Untested, may contain errors
class AgencyControllerTest extends WebTestCase
{
public function testShowFoo()
{
$client = static::createClient();
$crawler = $client->request('GET', '/', array(), array(), array(
'HTTP_HOST' => 'foo.domain.dev',
'HTTP_USER_AGENT' => 'Symfony/2.0',
));
$this->assertGreaterThan(0, $crawler->filter('html:contains("Text of foo domain")')->count());
}
}
Based on the Symfony docs on host-based routes, Testing your Controllers:
$crawler = $client->request(
'GET',
'/',
array(),
array(),
array('HTTP_HOST' => 'foo.domain.dev')
);
If you don't want to pad all your requests with array parameters, this might be better:
$client->setServerParameter('HTTP_HOST', 'foo.domain.dev');
$crawler = $client->request('GET', '/');
...
$crawler2 = $client->request('GET', /foo'); // still sends the HTTP_HOST
There's also a setServerParameters() method on the client, if you have a few parameters to change.