Skip to content

Commit 5883af1

Browse files
glibaslukeis
authored andcommitted
[Java] Fix deselecting options in <select>
1. Fix inconsistency between java doc and implementation: deselectByVisibleText, deselectByIndex and deselectByValue did not throw NoSuchElementException, while they should have to. 2. Remove check !isMultiple() while selecting/deselecting by index, since no need as index is unique. 3. Add appropriate tests to SelectElementTest 4. Include SelectElementTest in LargeTests suite, since it was not a part of any. Add exception when deselecting non-multiselect Signed-off-by: Luke Inman-Semerau <[email protected]>
1 parent 4f828d2 commit 5883af1

File tree

3 files changed

+100
-28
lines changed

3 files changed

+100
-28
lines changed

java/client/src/org/openqa/selenium/support/ui/Select.java

Lines changed: 55 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -116,7 +116,7 @@ public void selectByVisibleText(String text) {
116116

117117
boolean matched = false;
118118
for (WebElement option : options) {
119-
setSelected(option);
119+
setSelected(option, true);
120120
if (!isMultiple()) {
121121
return;
122122
}
@@ -137,7 +137,7 @@ public void selectByVisibleText(String text) {
137137
}
138138
for (WebElement option : candidates) {
139139
if (text.equals(option.getText())) {
140-
setSelected(option);
140+
setSelected(option, true);
141141
if (!isMultiple()) {
142142
return;
143143
}
@@ -173,19 +173,13 @@ private String getLongestSubstringWithoutSpace(String s) {
173173
public void selectByIndex(int index) {
174174
String match = String.valueOf(index);
175175

176-
boolean matched = false;
177176
for (WebElement option : getOptions()) {
178177
if (match.equals(option.getAttribute("index"))) {
179-
setSelected(option);
180-
if (!isMultiple()) {
181-
return;
182-
}
183-
matched = true;
178+
setSelected(option, true);
179+
return;
184180
}
185181
}
186-
if (!matched) {
187-
throw new NoSuchElementException("Cannot locate option with index: " + index);
188-
}
182+
throw new NoSuchElementException("Cannot locate option with index: " + index);
189183
}
190184

191185
/**
@@ -203,7 +197,7 @@ public void selectByValue(String value) {
203197

204198
boolean matched = false;
205199
for (WebElement option : options) {
206-
setSelected(option);
200+
setSelected(option, true);
207201
if (!isMultiple()) {
208202
return;
209203
}
@@ -227,9 +221,7 @@ public void deselectAll() {
227221
}
228222

229223
for (WebElement option : getOptions()) {
230-
if (option.isSelected()) {
231-
option.click();
232-
}
224+
setSelected(option, false);
233225
}
234226
}
235227

@@ -241,15 +233,23 @@ public void deselectAll() {
241233
*
242234
* @param value The value to match against
243235
* @throws NoSuchElementException If no matching option elements are found
236+
* @throws UnsupportedOperationException If the SELECT does not support multiple selections
244237
*/
245238
public void deselectByValue(String value) {
239+
if (!isMultiple()) {
240+
throw new UnsupportedOperationException(
241+
"You may only deselect options of a multi-select");
242+
}
243+
246244
List<WebElement> options = element.findElements(By.xpath(
247245
".//option[@value = " + Quotes.escape(value) + "]"));
248-
246+
boolean matched = false;
249247
for (WebElement option : options) {
250-
if (option.isSelected()) {
251-
option.click();
252-
}
248+
setSelected(option, false);
249+
matched = true;
250+
}
251+
if (!matched) {
252+
throw new NoSuchElementException("Cannot locate option with value: " + value);
253253
}
254254
}
255255

@@ -259,15 +259,23 @@ public void deselectByValue(String value) {
259259
*
260260
* @param index The option at this index will be deselected
261261
* @throws NoSuchElementException If no matching option elements are found
262+
* @throws UnsupportedOperationException If the SELECT does not support multiple selections
262263
*/
263264
public void deselectByIndex(int index) {
265+
if (!isMultiple()) {
266+
throw new UnsupportedOperationException(
267+
"You may only deselect options of a multi-select");
268+
}
269+
264270
String match = String.valueOf(index);
265-
271+
266272
for (WebElement option : getOptions()) {
267-
if (match.equals(option.getAttribute("index")) && option.isSelected()) {
268-
option.click();
273+
if (match.equals(option.getAttribute("index"))) {
274+
setSelected(option, false);
275+
return;
269276
}
270277
}
278+
throw new NoSuchElementException("Cannot locate option with index: " + index);
271279
}
272280

273281
/**
@@ -278,20 +286,40 @@ public void deselectByIndex(int index) {
278286
*
279287
* @param text The visible text to match against
280288
* @throws NoSuchElementException If no matching option elements are found
289+
* @throws UnsupportedOperationException If the SELECT does not support multiple selections
281290
*/
282291
public void deselectByVisibleText(String text) {
292+
if (!isMultiple()) {
293+
throw new UnsupportedOperationException(
294+
"You may only deselect options of a multi-select");
295+
}
296+
283297
List<WebElement> options = element.findElements(By.xpath(
284298
".//option[normalize-space(.) = " + Quotes.escape(text) + "]"));
285299

300+
boolean matched = false;
286301
for (WebElement option : options) {
287-
if (option.isSelected()) {
288-
option.click();
289-
}
302+
setSelected(option, false);
303+
matched = true;
304+
}
305+
306+
if (!matched) {
307+
throw new NoSuchElementException("Cannot locate element with text: " + text);
290308
}
291309
}
292310

293-
private void setSelected(WebElement option) {
294-
if (!option.isSelected()) {
311+
/**
312+
* Select or deselect specified option
313+
*
314+
* @param option
315+
* The option which state needs to be changed
316+
* @param select
317+
* Indicates whether the option needs to be selected (true) or
318+
* deselected (false)
319+
*/
320+
private void setSelected(WebElement option, boolean select) {
321+
boolean isSelected=option.isSelected();
322+
if ((!isSelected && select) || (isSelected && !select)) {
295323
option.click();
296324
}
297325
}

java/client/test/org/openqa/selenium/support/LargeTests.java

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,13 +20,15 @@
2020
import org.junit.runner.RunWith;
2121
import org.junit.runners.Suite;
2222
import org.openqa.selenium.support.pagefactory.UsingPageFactoryTest;
23+
import org.openqa.selenium.support.ui.SelectElementTest;
2324
import org.openqa.selenium.support.ui.SelectLargeTest;
2425
import org.openqa.selenium.testing.JUnit4TestBase;
2526

2627
@RunWith(Suite.class)
2728
@Suite.SuiteClasses({
2829
SelectLargeTest.class,
29-
UsingPageFactoryTest.class
30+
UsingPageFactoryTest.class,
31+
SelectElementTest.class
3032
})
3133
public class LargeTests {
3234

java/client/test/org/openqa/selenium/support/ui/SelectElementTest.java

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -270,4 +270,46 @@ public void shouldAllowOptionsToBeSelectedFromTheSelectElementThatIsNarrowerThan
270270

271271
assertEquals(1,returnedOptions.size());
272272
}
273+
274+
@Test(expected = NoSuchElementException.class)
275+
public void shouldThrowExceptionOnDeselectByReturnedValueIfOptionDoesNotExist() {
276+
WebElement selectElement = driver.findElement(By.name("select_empty_multiple"));
277+
Select select = new Select(selectElement);
278+
select.deselectByValue("not there");
279+
}
280+
281+
@Test(expected = NoSuchElementException.class)
282+
public void shouldThrowExceptionOnDeselectByVisibleTextIfOptionDoesNotExist() {
283+
WebElement selectElement = driver.findElement(By.name("select_empty_multiple"));
284+
Select select = new Select(selectElement);
285+
select.deselectByVisibleText("not there");
286+
}
287+
288+
@Test(expected = NoSuchElementException.class)
289+
public void shouldThrowExceptionOnDeselectByIndexIfOptionDoesNotExist() {
290+
WebElement selectElement = driver.findElement(By.name("select_empty_multiple"));
291+
Select select = new Select(selectElement);
292+
select.deselectByIndex(10);
293+
}
294+
295+
@Test(expected = UnsupportedOperationException.class)
296+
public void shouldNotAllowUserToDeselectByIndexWhenSelectDoesNotSupportMultipleSelections() {
297+
WebElement selectElement = driver.findElement(By.name("selectomatic"));
298+
Select select = new Select(selectElement);
299+
select.deselectByIndex(0);
300+
}
301+
302+
@Test(expected = UnsupportedOperationException.class)
303+
public void shouldNotAllowUserToDeselectByValueWhenSelectDoesNotSupportMultipleSelections() {
304+
WebElement selectElement = driver.findElement(By.name("selectomatic"));
305+
Select select = new Select(selectElement);
306+
select.deselectByValue("two");
307+
}
308+
309+
@Test(expected = UnsupportedOperationException.class)
310+
public void shouldNotAllowUserToDeselectByVisibleTextWhenSelectDoesNotSupportMultipleSelections() {
311+
WebElement selectElement = driver.findElement(By.name("selectomatic"));
312+
Select select = new Select(selectElement);
313+
select.deselectByVisibleText("Four");
314+
}
273315
}

0 commit comments

Comments
 (0)