kandi background
kandi background
Explore Kits
kandi background
Explore Kits
kandi background
Explore Kits
kandi background
Explore Kits
Explore all Crawler open source software, libraries, packages, source code, cloud functions and APIs.

Popular New Releases in Crawler

1.8.2

v3.7.1

v0.6.0-beta.20211224

INFO-SPIDER v1.0

scrapy

1.8.2

cheerio

winston

v3.7.1

crawlab

v0.6.0-beta.20211224

InfoSpider

INFO-SPIDER v1.0

Popular Libraries in Crawler

Trending New libraries in Crawler

Top Authors in Crawler

1

21 Libraries

1554

2

11 Libraries

1206

3

11 Libraries

3217

4

8 Libraries

600

5

7 Libraries

93

6

6 Libraries

41

7

6 Libraries

105

8

6 Libraries

448

9

6 Libraries

158

10

6 Libraries

34

1

21 Libraries

1554

2

11 Libraries

1206

3

11 Libraries

3217

4

8 Libraries

600

5

7 Libraries

93

6

6 Libraries

41

7

6 Libraries

105

8

6 Libraries

448

9

6 Libraries

158

10

6 Libraries

34

Trending Kits in Crawler

No Trending Kits are available at this moment for Crawler

Trending Discussions on Crawler

    How to test form submission with wrong values using Symfony crawler component and PHPUnit?
    Setting proxies when crawling websites with Python
    Can't Successfully Run AWS Glue Job That Reads From DynamoDB
    Why does scrapy_splash CrawlSpider take the same amount of time as scrapy with Selenium?
    How can I send Dynamic website content to scrapy with the html content generated by selenium browser?
    How to set class variable through __init__ in Python?
    headless chrome on docker M1 error - unable to discover open window in chrome
    How do I pass in arguments non-interactive into a bash file that uses "read"?
    Scrapy crawls duplicate data
    AWS Glue Crawler sends all data to Glue Catalog and Athena without Glue Job

QUESTION

How to test form submission with wrong values using Symfony crawler component and PHPUnit?

Asked 2022-Apr-05 at 11:18

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 :

1public function testPayloadNotRespectingFieldLimits(): void
2{
3    $client = static::createClient();
4
5    /** @var SomeRepository $repo */
6    $repo = self::getContainer()->get(SomeRepository::class);
7    $countEntries = $repo->count([]);
8    
9    $crawler = $client->request(
10        'GET',
11        '/route/to/form/add'
12    );
13    $this->assertResponseIsSuccessful(); // Goes ok.
14
15    $form = $crawler->filter('[type=submit]')->form(); // It does retrieve my form node.
16    
17    // This is where it's not working.
18    $form->setValues([
19        'some[name]' => 'Someokvalue',
20        'some[color]' => 'SomeNOTOKValue', // It is a ChoiceType with limited values, where 'SomeNOTOKValue' does not belong. This is the line that throws an \InvalidArgumentException.
21    )];
22
23    // What I'd like to assert after this
24    $client->submit($form);
25    $this->assertResponseRedirects();
26    $this->assertEquals($countEntries, $repo->count([]));
27}
28

Here's the exception message I get :

1public function testPayloadNotRespectingFieldLimits(): void
2{
3    $client = static::createClient();
4
5    /** @var SomeRepository $repo */
6    $repo = self::getContainer()->get(SomeRepository::class);
7    $countEntries = $repo->count([]);
8    
9    $crawler = $client->request(
10        'GET',
11        '/route/to/form/add'
12    );
13    $this->assertResponseIsSuccessful(); // Goes ok.
14
15    $form = $crawler->filter('[type=submit]')->form(); // It does retrieve my form node.
16    
17    // This is where it's not working.
18    $form->setValues([
19        'some[name]' => 'Someokvalue',
20        'some[color]' => 'SomeNOTOKValue', // It is a ChoiceType with limited values, where 'SomeNOTOKValue' does not belong. This is the line that throws an \InvalidArgumentException.
21    )];
22
23    // What I'd like to assert after this
24    $client->submit($form);
25    $this->assertResponseRedirects();
26    $this->assertEquals($countEntries, $repo->count([]));
27}
28InvalidArgumentException: Input "some[color]" cannot take "SomeNOTOKValue" as a value (possible values: "red", "pink", "purple", "white").
29vendor/symfony/dom-crawler/Field/ChoiceFormField.php:140
30vendor/symfony/dom-crawler/FormFieldRegistry.php:113
31vendor/symfony/dom-crawler/Form.php:75
32

The ColorChoiceType tested here is pretty standard :

1public function testPayloadNotRespectingFieldLimits(): void
2{
3    $client = static::createClient();
4
5    /** @var SomeRepository $repo */
6    $repo = self::getContainer()->get(SomeRepository::class);
7    $countEntries = $repo->count([]);
8    
9    $crawler = $client->request(
10        'GET',
11        '/route/to/form/add'
12    );
13    $this->assertResponseIsSuccessful(); // Goes ok.
14
15    $form = $crawler->filter('[type=submit]')->form(); // It does retrieve my form node.
16    
17    // This is where it's not working.
18    $form->setValues([
19        'some[name]' => 'Someokvalue',
20        'some[color]' => 'SomeNOTOKValue', // It is a ChoiceType with limited values, where 'SomeNOTOKValue' does not belong. This is the line that throws an \InvalidArgumentException.
21    )];
22
23    // What I'd like to assert after this
24    $client->submit($form);
25    $this->assertResponseRedirects();
26    $this->assertEquals($countEntries, $repo->count([]));
27}
28InvalidArgumentException: Input "some[color]" cannot take "SomeNOTOKValue" as a value (possible values: "red", "pink", "purple", "white").
29vendor/symfony/dom-crawler/Field/ChoiceFormField.php:140
30vendor/symfony/dom-crawler/FormFieldRegistry.php:113
31vendor/symfony/dom-crawler/Form.php:75
32public function configureOptions(OptionsResolver $resolver): void
33{
34    $resolver->setDefaults([
35        'choices' => ColorEnumType::getChoices(),
36        'multiple' => false,
37    )];
38}
39

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).

1public function testPayloadNotRespectingFieldLimits(): void
2{
3    $client = static::createClient();
4
5    /** @var SomeRepository $repo */
6    $repo = self::getContainer()->get(SomeRepository::class);
7    $countEntries = $repo->count([]);
8    
9    $crawler = $client->request(
10        'GET',
11        '/route/to/form/add'
12    );
13    $this->assertResponseIsSuccessful(); // Goes ok.
14
15    $form = $crawler->filter('[type=submit]')->form(); // It does retrieve my form node.
16    
17    // This is where it's not working.
18    $form->setValues([
19        'some[name]' => 'Someokvalue',
20        'some[color]' => 'SomeNOTOKValue', // It is a ChoiceType with limited values, where 'SomeNOTOKValue' does not belong. This is the line that throws an \InvalidArgumentException.
21    )];
22
23    // What I'd like to assert after this
24    $client->submit($form);
25    $this->assertResponseRedirects();
26    $this->assertEquals($countEntries, $repo->count([]));
27}
28InvalidArgumentException: Input "some[color]" cannot take "SomeNOTOKValue" as a value (possible values: "red", "pink", "purple", "white").
29vendor/symfony/dom-crawler/Field/ChoiceFormField.php:140
30vendor/symfony/dom-crawler/FormFieldRegistry.php:113
31vendor/symfony/dom-crawler/Form.php:75
32public function configureOptions(OptionsResolver $resolver): void
33{
34    $resolver->setDefaults([
35        'choices' => ColorEnumType::getChoices(),
36        'multiple' => false,
37    )];
38}
39// ...
40/** @var SomeRepository $repo */
41$repo = self::getContainer()->get(SomeRepository::class);
42$countEntries = $repo->count([]); // Gives 0.
43// ...
44try {
45    $form->setValues([
46        'some[name]' => 'Someokvalue',
47        'some[color]' => 'SomeNOTOKValue',
48    ]);
49} catch (\InvalidArgumentException $e) {}
50
51$client->submit($form); // Now it submits the form.
52$this->assertResponseRedirects(); // Ok.
53$this->assertEquals($countEntries, $repo->count([])); // Failed asserting that 1 matches expected 0. !!
54

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

ANSWER

Answered 2022-Apr-05 at 11:17

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 :

copy icondownload icon

1public function testPayloadNotRespectingFieldLimits(): void
2{
3    $client = static::createClient();
4
5    /** @var SomeRepository $repo */
6    $repo = self::getContainer()->get(SomeRepository::class);
7    $countEntries = $repo->count([]);
8    
9    $crawler = $client->request(
10        'GET',
11        '/route/to/form/add'
12    );
13    $this->assertResponseIsSuccessful(); // Goes ok.
14
15    $form = $crawler->filter('[type=submit]')->form(); // It does retrieve my form node.
16    
17    // This is where it's not working.
18    $form->setValues([
19        'some[name]' => 'Someokvalue',
20        'some[color]' => 'SomeNOTOKValue', // It is a ChoiceType with limited values, where 'SomeNOTOKValue' does not belong. This is the line that throws an \InvalidArgumentException.
21    )];
22
23    // What I'd like to assert after this
24    $client->submit($form);
25    $this->assertResponseRedirects();
26    $this->assertEquals($countEntries, $repo->count([]));
27}
28InvalidArgumentException: Input "some[color]" cannot take "SomeNOTOKValue" as a value (possible values: "red", "pink", "purple", "white").
29vendor/symfony/dom-crawler/Field/ChoiceFormField.php:140
30vendor/symfony/dom-crawler/FormFieldRegistry.php:113
31vendor/symfony/dom-crawler/Form.php:75
32public function configureOptions(OptionsResolver $resolver): void
33{
34    $resolver->setDefaults([
35        'choices' => ColorEnumType::getChoices(),
36        'multiple' => false,
37    )];
38}
39// ...
40/** @var SomeRepository $repo */
41$repo = self::getContainer()->get(SomeRepository::class);
42$countEntries = $repo->count([]); // Gives 0.
43// ...
44try {
45    $form->setValues([
46        'some[name]' => 'Someokvalue',
47        'some[color]' => 'SomeNOTOKValue',
48    ]);
49} catch (\InvalidArgumentException $e) {}
50
51$client->submit($form); // Now it submits the form.
52$this->assertResponseRedirects(); // Ok.
53$this->assertEquals($countEntries, $repo->count([])); // Failed asserting that 1 matches expected 0. !!
54$form = $crawler->filter('[type=submit]')->form()->disableValidation();
55$form->setValues([
56    'some[name]' => 'Someokvalue',
57    'some[color]' => 'SomeNOTOKValue',
58];
59$client->submit($form);
60
61$this->assertEquals($entriesBefore, $repo->count([]); // Now passes.
62

Source https://stackoverflow.com/questions/71565750