laravel / dusk

Laravel Dusk provides simple end-to-end testing and browser automation.
https://laravel.com/docs/dusk
MIT License
1.87k stars 319 forks source link

Unexpected behaviour when working with multiple checkboxes #1064

Closed ziadoz closed 11 months ago

ziadoz commented 11 months ago

Dusk Version

7.11.2

Laravel Version

10.28.0

PHP Version

8.1.17

PHPUnit Version

10.4.1

Database Driver & Version

No response

Description

The check(), uncheck(), assertChecked() and assertNotChecked() methods in Dusk only apply to the first matching element, rather than all matching elements, which causes odds results when working with multiple checkboxes (see reproduction steps). In contrast, the click() method operates on all matching elements, which is the behaviour I would expect.

There are workarounds, such as binding a macro that does something like below, however I feel like multiple checkboxes are common enough that handling them in Dusk by default would be nice:

foreach ($browser->elements('input[name="multi[]"]') as $element) {
    if (! $element->isSelected()) {
        $element->click();
    }
}

I did consider opening a pull request to make the checkbox methods work like click(), however I wasn't sure if it would be accepted. So I figured a bug report might be more useful instead.

Steps To Reproduce

With this HTML:

<label><input type="checkbox" name="multi[]" value="foo"> Foo</label>
<label><input type="checkbox" name="multi[]" value="bar"> Bar</label>

I would expect the check() and uncheck() methods to check/uncheck all of the matching checkboxes, however only the first checkbox is touched:

$browser->check('multi[]'); // Only checks the "foo" input.
$browser->uncheck('multi[]'); // Only unchecks the "foo" input.

Similarly assertChecked() and assertNotChecked() only assert on the first checkbox too:

$browser->assertChecked('multi[]'); // Only asserts on the "foo" input.
$browser->assertNotChecked('multi[]'); // Only asserts on the "foo" input.

Specifying the value works, however this isn't practical when you have many checkboxes, or don't know what the values are upfront:

$browser->check('multi[]', 'foo'); // Works as expected
$browser->uncheck('multi[]', 'bar'); // Works as expected

$browser->assertChecked('multi[]', 'foo'); // Works as expected
$browser->assertNotChecked('multi[]', 'bar'); // Works as expected
crynobone commented 11 months ago

I believe the current expected behaviour is the correct usage. You should be able to add custom macros if you want to add additional macros.