How to test form submission with wrong values using Symfony crawler component and PHPUnit? -- [Question Asked]

Issue

When you’re using the app through the browser, you send a bad value, the system checks for errors in the form, and if something goes wrong (it does in this case), it redirects with a default error message written below the incriminated field.

This is the behaviour I am trying to assert with my test case, but I came accross an \InvalidArgumentException I was not expecting.

I am using the symfony/phpunit-bridge with phpunit/phpunit v8.5.23 and symfony/dom-crawler v5.3.7.
Here’s a sample of what it looks like :

public function testPayloadNotRespectingFieldLimits(): void
{
    $client = static::createClient();

    /** @var SomeRepository $repo */
    $repo = self::getContainer()->get(SomeRepository::class);
    $countEntries = $repo->count([]);
    
    $crawler = $client->request(
        'GET',
        '/route/to/form/add'
    );
    $this->assertResponseIsSuccessful(); // Goes ok.

    $form = $crawler->filter('[type=submit]')->form(); // It does retrieve my form node.
    
    // This is where it's not working.
    $form->setValues([
        'some[name]' => 'Someokvalue',
        'some[color]' => 'SomeNOTOKValue', // It is a ChoiceType with limited values, where 'SomeNOTOKValue' does not belong. This is the line that throws an \InvalidArgumentException.
    )];

    // What I'd like to assert after this
    $client->submit($form);
    $this->assertResponseRedirects();
    $this->assertEquals($countEntries, $repo->count([]));
}

Here’s the exception message I get :

InvalidArgumentException: Input "some[color]" cannot take "SomeNOTOKValue" as a value (possible values: "red", "pink", "purple", "white").
vendor/symfony/dom-crawler/Field/ChoiceFormField.php:140
vendor/symfony/dom-crawler/FormFieldRegistry.php:113
vendor/symfony/dom-crawler/Form.php:75

The ColorChoiceType tested here is pretty standard :

public function configureOptions(OptionsResolver $resolver): void
{
    $resolver->setDefaults([
        'choices' => ColorEnumType::getChoices(),
        'multiple' => false,
    )];
}

What I can do, is to wrap in a try-catch block, the line where it sets the wrong value. And it would indeed submit the form and proceed to the next assertion. The issue here is that the form was considered submitted and valid, it forced an appropriate value for the color field (the first choice of the enum set).
This is not what I get when I try this in my browser (cf. the intro).

// ...
/** @var SomeRepository $repo */
$repo = self::getContainer()->get(SomeRepository::class);
$countEntries = $repo->count([]); // Gives 0.
// ...
try {
    $form->setValues([
        'some[name]' => 'Someokvalue',
        'some[color]' => 'SomeNOTOKValue',
    ]);
} catch (\InvalidArgumentException $e) {}

$client->submit($form); // Now it submits the form.
$this->assertResponseRedirects(); // Ok.
$this->assertEquals($countEntries, $repo->count([])); // Failed asserting that 1 matches expected 0. !!

How can I mimic the browser behaviour in my test case and make asserts on it ?

Answer we found from sources

It seems that you can disable validation on the DomCrawler\Form component. Based on the official documentation here.

So doing this, now works as expected :

$form = $crawler->filter('[type=submit]')->form()->disableValidation();
$form->setValues([
    'some[name]' => 'Someokvalue',
    'some[color]' => 'SomeNOTOKValue',
];
$client->submit($form);

$this->assertEquals($entriesBefore, $repo->count([]); // Now passes.

Answered By – Christophe

This Answer collected from stackoverflow, is licensed under cc by-sa 2.5 , cc by-sa 3.0 and cc by-sa 4.0

Posted in PHP

Who we are?

We are team of software engineers in multiple domains like Programming and coding, Fundamentals of computer science, Design and architecture, Algorithms and data structures, Information analysis, Debugging software and Testing software. We are working on Systems developer and application developer. We are curious, methodical, rational, analytical, and logical. Some of us are also conventional, meaning we're conscientious and conservative.

Answer collected from stackoverflow and other sources, is licensed under cc by-sa 2.5 , cc by-sa 3.0 and cc by-sa 4.0