Symfony2: тест на ArrayCollection дает "Недоступное поле"
В функциональном тесте формы для добавления членов ArrayCollection есть следующее утверждение:
$ form ['client [members] [1] [fname]'] = 'Benny';
Имя поля было проверено инспектором DOM.
Вывод консоли в этой строке:
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
Какой метод следует использовать для проверки добавления члена ArrayCollection?
Отредактируйте как требуется (примечание, следите за перенаправлениями):
//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);
4 ответа
У меня была та же проблема, и после небольшого исследования я нашел решение, которое мне помогло. Решение по удалению поля из типа формы Коллекция. Это сообщение не совсем то, что вы искали, это удаление элемента, а не добавление новых. Но принцип тот же. Что я сделал вместо $form->setValues() ... $form->getPhpValues()
что я создал массив, и поместил это
В приведенном ниже примере configurations
поле формы является 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);
Надеюсь, поможет! И спасибо за сток за оригинальное решение!
Это можно сделать, вызвав слегка измененный код из submit()
метод:
// 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());
Массив со значениями новостей в этом примере соответствует форме, где у вас есть поля с этими 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]" />
С этим кодом существующие поля (включая токен) уже присутствуют в форме, это означает, что вам не нужно добавлять все поля.
Количество (индекс) полей не имеет значения, PHP объединит массивы и отправит данные, Symfony преобразует эти данные в соответствующие поля.
Вы также можете удалить элемент из коллекции:
// 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());
Если вы измените форму с помощью javascript, вы не сможете протестировать ее с помощью инфраструктуры тестирования Symfony. Причина этого заключается в том, что DomCrawler, предоставляемый Symfony, только извлекает статический HTML и анализирует его, не принимая во внимание любые манипуляции, которые могут быть выполнены браузером с графическим пользовательским интерфейсом (главным образом, JavaScript).
Если вам нужно протестировать тяжелый javascript-проект, вам нужно использовать некую инфраструктуру, которая либо использует движок браузера (например, Selenium), либо может интерпретировать javascript и выполнять все изменения в DOM (например, Zombie.js).
Хорошей платформой для этого является Mink, который представляет собой слой между платформой тестирования и реальным клиентом, выполняющим запрос и анализирующим результат. Он предоставляет API для работы с очень простым PHP HTML Parser (похожим на DomCrawler, используемый symfony), Selenium, Zombie.js и некоторыми другими.
У меня была аналогичная проблема, и в моем случае я понял, что это потому, что я использовал неправильный сканер, я использовал тот, который был на предыдущей странице, с немного другой формой. Так что я думаю, что это хорошее место, чтобы дать решение, которое сработало в моем случае.
Получив новый сканер на нужной веб-странице, он работает.
$crawler = $client->getCrawler();
//processing the form
// ...
и чтобы избежать ошибок, я использую синтаксис
$crawler = $client->submitForm('Add client', [
'client[members][1][fname]' => 'Benny',
'client[members][1][dob]' => "3/12/1999",
]);