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());

Источник: http://symfony.com/doc/current/book/testing.html

Если вы измените форму с помощью 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",
        ]);
Другие вопросы по тегам