Skip to content

Commit 790ac29

Browse files
committed
Allow to deselect option of <select> by partial text
1 parent 02b1d20 commit 790ac29

File tree

2 files changed

+77
-25
lines changed

2 files changed

+77
-25
lines changed

lib/WebDriverSelect.php

Lines changed: 45 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -40,9 +40,7 @@ public function __construct(WebDriverElement $element)
4040
}
4141

4242
/**
43-
* @return bool Whether this select element support selecting multiple
44-
* options. This is done by checking the value of the 'multiple'
45-
* attribute.
43+
* @return bool Whether this select element support selecting multiple options.
4644
*/
4745
public function isMultiple()
4846
{
@@ -89,26 +87,6 @@ public function getFirstSelectedOption()
8987
throw new NoSuchElementException('No options are selected');
9088
}
9189

92-
/**
93-
* Deselect all options in multiple select tag.
94-
*
95-
* @throws UnsupportedOperationException
96-
*/
97-
public function deselectAll()
98-
{
99-
if (!$this->isMultiple()) {
100-
throw new UnsupportedOperationException(
101-
'You may only deselect all options of a multi-select'
102-
);
103-
}
104-
105-
foreach ($this->getOptions() as $option) {
106-
if ($option->isSelected()) {
107-
$option->click();
108-
}
109-
}
110-
}
111-
11290
/**
11391
* Select the option at the given index.
11492
*
@@ -252,6 +230,24 @@ public function selectByVisiblePartialText($text)
252230
}
253231
}
254232

233+
/**
234+
* Deselect all options in multiple select tag.
235+
*
236+
* @throws UnsupportedOperationException If the SELECT does not support multiple selections
237+
*/
238+
public function deselectAll()
239+
{
240+
if (!$this->isMultiple()) {
241+
throw new UnsupportedOperationException('You may only deselect all options of a multi-select');
242+
}
243+
244+
foreach ($this->getOptions() as $option) {
245+
if ($option->isSelected()) {
246+
$option->click();
247+
}
248+
}
249+
}
250+
255251
/**
256252
* Deselect the option at the given index.
257253
*
@@ -268,7 +264,7 @@ public function deselectByIndex($index)
268264

269265
/**
270266
* Deselect all options that have value attribute matching the argument. That
271-
* is, when given "foo" this would select an option like:
267+
* is, when given "foo" this would deselect an option like:
272268
*
273269
* <option value="foo">Bar</option>;
274270
*
@@ -287,7 +283,7 @@ public function deselectByValue($value)
287283

288284
/**
289285
* Deselect all options that display text matching the argument. That is, when
290-
* given "Bar" this would select an option like:
286+
* given "Bar" this would deselect an option like:
291287
*
292288
* <option value="foo">Bar</option>;
293289
*
@@ -304,6 +300,30 @@ public function deselectByVisibleText($text)
304300
}
305301
}
306302

303+
/**
304+
* Deselect all options that display text matching the argument. That is, when
305+
* given "Bar" this would deselect an option like:
306+
*
307+
* <option value="foo">Foo Bar Baz</option>;
308+
*
309+
* @param string $text The visible text to match against.
310+
* @throws UnsupportedOperationException If the SELECT does not support multiple selections
311+
*/
312+
public function deselectByVisiblePartialText($text)
313+
{
314+
if (!$this->isMultiple()) {
315+
throw new UnsupportedOperationException('You may only deselect options of a multi-select');
316+
}
317+
318+
$xpath = './/option[contains(normalize-space(.), ' . $this->escapeQuotes($text) . ')]';
319+
$options = $this->element->findElements(WebDriverBy::xpath($xpath));
320+
foreach ($options as $option) {
321+
if ($option->isSelected()) {
322+
$option->click();
323+
}
324+
}
325+
}
326+
307327
/**
308328
* Convert strings with both quotes and ticks into:
309329
* foo'"bar -> concat("foo'", '"', "bar")

tests/functional/WebDriverSelectTest.php

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -353,6 +353,38 @@ public function testShouldDeselectOptionByVisibleText()
353353
$this->assertContainsOptionsWithValues(['second'], $select->getAllSelectedOptions());
354354
}
355355

356+
public function testShouldDeselectOptionByVisiblePartialText()
357+
{
358+
$select = $this->getWebDriverSelectForMultipleSelect();
359+
$select->selectByValue('fourth'); // text 'Fourth with spaces inside'
360+
$select->selectByValue('fifth'); // text ' Fifth surrounded by spaces '
361+
$select->selectByValue('second'); // text 'This is second option'
362+
$select->selectByValue('third'); // text 'This is not second option'
363+
$select->selectByValue('first'); // text 'First'
364+
$this->assertCount(5, $select->getAllSelectedOptions());
365+
366+
$select->deselectByVisiblePartialText('second'); // should deselect two options
367+
$this->assertContainsOptionsWithValues(['first', 'fourth', 'fifth'], $select->getAllSelectedOptions());
368+
369+
$select->deselectByVisiblePartialText('Fourth with spaces');
370+
$select->deselectByVisiblePartialText('Fourth with spaces'); // should be deselected even if deselected again
371+
$this->assertContainsOptionsWithValues(['first', 'fifth'], $select->getAllSelectedOptions());
372+
373+
$select->deselectByVisiblePartialText('Fifth surrounded');
374+
$this->assertContainsOptionsWithValues(['first'], $select->getAllSelectedOptions());
375+
}
376+
377+
public function testShouldThrowExceptionIfDeselectingSimpleSelectByVisiblePartialText()
378+
{
379+
$select = $this->getWebDriverSelectForSimpleSelect();
380+
381+
$this->setExpectedException(
382+
UnsupportedOperationException::class,
383+
'You may only deselect options of a multi-select'
384+
);
385+
$select->deselectByVisiblePartialText('First');
386+
}
387+
356388
/**
357389
* @return WebDriverSelect
358390
*/

0 commit comments

Comments
 (0)