Skip to content

[Crawler] Selecting values of a ChoiceType field multiple and expanded #7337

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
mmenozzi opened this issue Mar 12, 2013 · 6 comments
Closed

Comments

@mmenozzi
Copy link
Contributor

On DomCrawler documentation is stated that is possible to select many options form a multiple select or checkboxes: http://d.pr/i/uY29.

// select many options from a "multiple" select or checkboxes
$form['registration[interests]']->select(array('symfony', 'cookies'));

I found that this is not true if the choice field is expanded (so checkboxes are generated). As stated in #5562 and in #5502, I also tried with:

$form['registration[interests]']->setValues(array('symfony', 'cookies'));

But doesn't work. The problem is that $form['registration[interests]'] returns an array of ChoiceFormField (where every ChoiceFormField represent the single checkboxes of the options) so you can't call any method on it.

The only way to select values for a multiple and expanded choice field using DomCrawler is this:

$form['registration[interests][0]']->tick();
$form['registration[interests][3]']->tick();

Where 0 and 3 are zero-based indexes for the options symfony and cookies. This is uncomfortable because in tests we know the value of the choices and not the position in the markup of the correspondent checkbox.

fabpot added a commit to fabpot/symfony-docs that referenced this issue Jun 13, 2013
@fabpot
Copy link
Member

fabpot commented Jun 13, 2013

This is actually a documentation problemas each checkbox is totally independent as you mentioned in your report. I've opened a PR to fix the docs.

@fabpot fabpot closed this as completed Jun 13, 2013
@mmenozzi
Copy link
Contributor Author

Ok, thats good but what I wanted to report is that it should be possible to select multiple and expanded choices by value and not by zero-based index of the options. This, in my opinion, would make tests much more readable (and writable).

@raziel057
Copy link
Contributor

@mmenozzi +1. Same "problem" for me.

I also tried to write:

$form = $crawler->selectButton('Save')->form(array(
    'ptc_noventobundle_supplier[name]' => 'Test Integration',
    'ptc_noventobundle_supplier[categories]' => array(2, 1),
));

With this HTML structure:

<div class="simpleBox" id="ptc_noventobundle_supplier_categories">
<input type="checkbox" value="4" name="ptc_noventobundle_supplier[categories][]" id="ptc_noventobundle_supplier_categories_4">
<label for="ptc_noventobundle_supplier_categories_4">Catering</label>
<input type="checkbox" value="2" name="ptc_noventobundle_supplier[categories][]" id="ptc_noventobundle_supplier_categories_2">
<label for="ptc_noventobundle_supplier_categories_2">Decorator</label>
<input type="checkbox" value="1" name="ptc_noventobundle_supplier[categories][]" id="ptc_noventobundle_supplier_categories_1">
<label for="ptc_noventobundle_supplier_categories_1">Florist</label>
</div>

But I get an InvalidArgumentException: Input "ptc_noventobundle_supplier[categories][]" cannot take "2" as a value (possible values: 4).

raziel057 added a commit to raziel057/symfony-docs-fr that referenced this issue Oct 9, 2014
@raziel057
Copy link
Contributor

As a workaround, it's possible to do:

$values = $form->getPhpValues();
$values['ptc_noventobundle_supplier']['categories'] = array(2, 1);

$this->client->request($form->getMethod(), $form->getUri(), $values, $form->getPhpFiles());

@claudionunezjr
Copy link

@raziel057 that workaround wasn't working for me. My scenario is the same as above. I kept getting an error stating that I can only set the value to the first checkbox value (the one at index 0).

Instead, I finally came up with a nice helper function which I include in my WebTestCase extended class (a custom child class).

Example (sorry for the code formatting):

protected function getCheckboxByValue($form, $field_name, $field_value)
{
    return array_reduce($form->offsetGet($field_name), function ($carry, $field) use ($field_value) {
        $options = array_map(function($option_value) {
            return array(
                'value' => $option_value
            );
        }, $field->availableOptionValues());

        if ($field->containsOption($field_value, $options)) {
            return $field;
        }
    });
}

And call it like so:

$field_name = 'ptc_noventobundle_supplier[categories]';
$field_value = '2';
$field = $this->getCheckboxByValue($form, $field_name, $field_value);

$field->tick();

@intelektron
Copy link

intelektron commented Mar 30, 2017

It didn't work for me, I had to rewrite the function:

/**
 * Find checkbox
 * 
 * @param \Symfony\Component\DomCrawler\Form $form
 * @param string $name Field name without trailing '[]'
 * @param string $value
 */
protected function findCheckbox($form, $name, $value)
{
    foreach ($form->offsetGet($name) as $field) {
        $available = $field->availableOptionValues();
        if (strval($value) == reset($available)) {
            return $field;
        }
    }
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

5 participants