Search code examples
phpsymfonytestingsymfony-formsfunctional-testing

Why can't I get value-attribute of form input in functional test (Symfony 5.1)?


I am writing a functional test for a form in phpunit with the DomCrawler Component in a Symfony 5.1 application. I read the docs as well as previous questions (another), but I can't get it to work.

The test should check:

  • Login (works)
  • Goto user overview (works)
  • Click edit for first item in user list (works)
  • Check if the data displayed in the form is correct (fails)

I am able to get all attributes of the form input, except for the value attribute. The url of the form edit page is /user-action?user=2.

My test looks like this:

public function testIfDisplayedInfosAreCorrect() 
{ 
  $crawler = $this->client->clickLink('Edit'); // from user overview -> click edit
    
  // $crawler->getUri() returns "/user-action?user=2" at this point (which is fine)
  // $crawler->filter('#user_firstname')->attr('class') returns the class names of the form input
  // $crawler->filter('#user_firstname')->attr('value') returns null
    
  $form = $crawler->selectButton('Save')->form();
  $firstName = $form->get('user[firstname]')->getValue(); // returns null
  $this->assertSame("Admin", $firstName); // fails 
}

Why can't I get the value of the form element? I hope it's clear what I mean, please let me know otherwise.

Edit: Dumping all values with $form->getValues(); also returns empty strings for all input fields.

Edit 2: The controller looks as following:

    /**
     * @Route("/user-action", name="app_user_action")
     */
    public function createAndEditUser(
        Request $request, 
        EntityManagerInterface $entityManager,
        SluggerInterface $slugger,
        UserPasswordEncoderInterface $passwordEncoder,
        UserHelper $userHelper): Response
    {   
        if(isset($_GET['user'])) {
            $user = $entityManager->getRepository(User::class)->find($_GET['user']);
            $email = $user->getEmail();
        } else {
            $user = new User();
            $email = '';
        }

        $form = $this->createForm(UserType::class, $user);
        
        $form->handleRequest($request);

        if ($form->isSubmitted() && $form->isValid()) 
        {
            // parse input 
            // create or edit object
            // flush into db

            return $this->redirectToRoute('app_users');
        }

        return $this->render('pages/user/action.html.twig', [
            'form' => $form->createView(),
            'email' => $email
        ]);
    }

Edit: Solution: Thanks to @DonCallisto's hint to use parameter converters, I removed the $_GET and used Symonfy's annotations for routing, which solved the problem of not being able to have if(isset($_GET['user'])) resolve to true.


Solution

  • if(isset($_GET['user'])) will return false, so you have not a single data inside the form.

    BTW you should not use $_GET, but you can take advantage of ParamConverter and eventually pass user id inside URL.