In a functional test of a form to add members of an ArrayCollection there is this statement:
$form['client[members][1][fname]'] = 'Benny';
The field name was verified with a DOM inspector.
The console output at this line is:
InvalidArgumentException: Unreachable field "members"
G:\Documents\workspace\sym\vendor\symfony\symfony\src\Symfony\Component\DomCrawler\Form.php:459
G:\Documents\workspace\sym\vendor\symfony\symfony\src\Symfony\Component\DomCrawler\Form.php:496
G:\Documents\workspace\sym\vendor\symfony\symfony\src\Symfony\Component\DomCrawler\Form.php:319
G:\Documents\workspace\sym\src\Mana\ClientBundle\Tests\Controller\ClientControllerTest.php:57
What method should be used to test the addition of an ArrayCollection member?
//link to trigger adding household member form $link = $crawler->selectLink('Add household member')->link(); $crawler = $client->click($link); $form = $crawler->selectButton('Add client')->form(); $form['client[members][1][fname]'] = 'Benny'; $form['client[members][1][dob]'] = "3/12/1999"; $crawler = $client->submit($form); $this->assertTrue($crawler->filter('html:contains("Client View Form")')->count() > 0);
I just had the same issue and after a bit of research I found a solution which helped me.
A solution to remove a field from a Collection form type
This post is not exactly what you were looking for, this one is for removing an element and not adding new ones. But the principle is the same. What I did instead of $form->setValues() ... $form->getPhpValues()
that I've created an array, and POSTed that
In the example bellow, the configurations
field of the form is a Collection
$submitButton = $crawler->selectButton(self::BUTTON_ADD_APPLICATION);
$form = $submitButton->form();
$values = array(
'Setup' => array(
'_token' => $form['Setup[_token]']->getValue(),
'name' => 'My New Setup',
'configurations' => array(
0 => array(
'country' => 'HUN',
'value' => '3',
),
1 => array(
'country' => 'GBR',
'value' => '0',
),
),
),
);
$client->request($form->getMethod(), $form->getUri(), $values);
Hope it helps! And thanks for sstok for the original solution!
This can be done by calling slightly modified code from the submit()
method:
// Get the form.
$form = $crawler->filter('button')->form();
// Get the raw values.
$values = $form->getPhpValues();
// Add fields to the raw values.
$values['task']['tag'][0]['name'] = 'foo';
$values['task']['tag'][1]['name'] = 'bar';
// Submit the form with the existing and new values.
$crawler = $this->client->request($form->getMethod(), $form->getUri(), $values,
$form->getPhpFiles());
// The 2 tags have been added to the collection.
$this->assertEquals(2, $crawler->filter('ul.tags > li')->count());
The array with the news values in this example correspond to a form where you have a fields with these name
s:
<input type="…" name="FORM_NAME[COLLECTION_NAME][A_NUMBER][FIELD_NAME_1]" />
<input type="…" name="FORM_NAME[COLLECTION_NAME][A_NUMBER][FIELD_NAME_2]" />
With this code, the existing fields (including token) are already present in the form, that means you don't need to add all the fields.
The number (index) of the fields is irrelevant, PHP will merge the arrays and submit the data, Symfony will transform this data in the corresponding fields.
You can also remove an element from a collection:
// Get the values of the form.
$values = $form->getPhpValues();
// Remove the first tag.
unset($values['task']['tags'][0]);
// Submit the data.
$crawler = $client->request($form->getMethod(), $form->getUri(),
$values, $form->getPhpFiles());
// The tag has been removed.
$this->assertEquals(0, $crawler->filter('ul.tags > li')->count());
Source: http://symfony.com/doc/current/book/testing.html#adding-and-removing-forms-to-a-collection
If you modify the form with javascript, you cannot test it with the symfony test framework. The reason for this is that the DomCrawler provided by symfony does only fetch the static HTML and parses it, not taking into account any manipulations which would be done by a browser with a graphical user interface (mainly javascript).
If you need to test a javascript-heavy project you need to use some framework which either uses the engine of a browser (e.g. Selenium) or which can interpret the javascript and execute all changes on the DOM (e.g. Zombie.js).
A good framework to do this is Mink, which is a layer between the testing framework and the actual client doing the request and parsing the result. It provides an API to work witha very simple PHP HTML Parser (similar to the DomCrawler used by symfony), Selenium, Zombie.js and some more.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With