Skip to content

Commit b2f8254

Browse files
author
syber911911
committed
[java]
feat: - Add method to deselect options containing the provided text - Add method for checking element visibility fix: - fix selectByContainsVisibleText method to check element visibility
1 parent b06461c commit b2f8254

File tree

5 files changed

+135
-3
lines changed

5 files changed

+135
-3
lines changed

common/src/web/formPage.html

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,12 @@
8080
<option value="oranges">Oranges</option>
8181
</select>
8282

83+
<select id="invisible_multi_select" multiple>
84+
<option selected="selected" value="apples" style="opacity: 0;">Apples</option>
85+
<option value="oranges">Oranges</option>
86+
<option selected="selected" value="lemons">Lemons</option>
87+
</select>
88+
8389
<select name="select-default">
8490
<option>One</option>
8591
<option>Two</option>

java/src/org/openqa/selenium/support/ui/ISelect.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -125,4 +125,6 @@ public interface ISelect {
125125
* @param text The visible text to match against
126126
*/
127127
void deselectByVisibleText(String text);
128+
129+
void deSelectByContainsVisibleText(String text);
128130
}

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

Lines changed: 47 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -17,9 +17,7 @@
1717

1818
package org.openqa.selenium.support.ui;
1919

20-
import java.util.List;
21-
import java.util.Objects;
22-
import java.util.StringTokenizer;
20+
import java.util.*;
2321
import java.util.stream.Collectors;
2422
import org.openqa.selenium.By;
2523
import org.openqa.selenium.NoSuchElementException;
@@ -68,6 +66,22 @@ public boolean isMultiple() {
6866
return isMulti;
6967
}
7068

69+
/**
70+
* @return This is done by checking the value of attributes in "visibility", "display", "opacity"
71+
* Return false if visibility is set to 'hidden', display is 'none', or opacity is 0 or 0.0.
72+
*/
73+
private boolean hasCssPropertyAndVisible(WebElement webElement) {
74+
List<String> cssValueCandidates = Arrays.asList(new String[]{"hidden", "none", "0", "0.0"});
75+
String[] cssPropertyCandidates = new String[]{"visibility", "display", "opacity"};
76+
77+
for (String property : cssPropertyCandidates) {
78+
String cssValue = webElement.getCssValue(property);
79+
if (cssValueCandidates.contains(cssValue)) return false;
80+
}
81+
82+
return true;
83+
}
84+
7185
/**
7286
* @return All options belonging to this select tag
7387
*/
@@ -173,13 +187,15 @@ public void selectByVisibleText(String text) {
173187
@Override
174188
public void selectByContainsVisibleText(String text) {
175189
assertSelectIsEnabled();
190+
assertSelectIsVisible();
176191

177192
// try to find the option via XPATH ...
178193
List<WebElement> options =
179194
element.findElements(
180195
By.xpath(".//option[normalize-space(.) = " + Quotes.escape(text) + "]"));
181196

182197
for (WebElement option : options) {
198+
if (!hasCssPropertyAndVisible(option)) throw new NoSuchElementException("Invisible option with text: " + text);
183199
setSelected(option, true);
184200
if (!isMultiple()) {
185201
return;
@@ -201,6 +217,7 @@ public void selectByContainsVisibleText(String text) {
201217
String trimmed = text.trim();
202218
for (WebElement option : candidates) {
203219
if (option.getText().contains(trimmed)) {
220+
if (!hasCssPropertyAndVisible(option)) throw new NoSuchElementException("Invisible option with text: " + text);
204221
setSelected(option, true);
205222
if (!isMultiple()) {
206223
return;
@@ -343,6 +360,27 @@ public void deselectByVisibleText(String text) {
343360
}
344361
}
345362

363+
@Override
364+
public void deSelectByContainsVisibleText(String text) {
365+
if (!isMultiple()) {
366+
throw new UnsupportedOperationException("You may only deselect options of a multi-select");
367+
}
368+
369+
String trimmed = text.trim();
370+
List<WebElement> options =
371+
element.findElements(
372+
By.xpath(".//option[contains(., " + Quotes.escape(trimmed) + ")]"));
373+
374+
if (options.isEmpty()) {
375+
throw new NoSuchElementException("Cannot locate option with text: " + text);
376+
}
377+
378+
for (WebElement option : options) {
379+
if (!hasCssPropertyAndVisible(option)) throw new NoSuchElementException("Invisible option with text: " + text);
380+
setSelected(option, false);
381+
}
382+
}
383+
346384
private List<WebElement> findOptionsByValue(String value) {
347385
List<WebElement> options =
348386
element.findElements(By.xpath(".//option[@value = " + Quotes.escape(value) + "]"));
@@ -389,6 +427,12 @@ private void assertSelectIsEnabled() {
389427
}
390428
}
391429

430+
private void assertSelectIsVisible() {
431+
if (!hasCssPropertyAndVisible(element)) {
432+
throw new UnsupportedOperationException("You may not select an option in invisible select");
433+
}
434+
}
435+
392436
@Override
393437
public boolean equals(Object o) {
394438
if (!(o instanceof Select)) {

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

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -162,6 +162,24 @@ public void shouldNotAllowInvisibleOptionsToBeSelectedByVisibleText() {
162162
.isThrownBy(() -> select.selectByVisibleText("Apples"));
163163
}
164164

165+
@Test
166+
void shouldNotAllowInvisibleSelectElementToBeSelectedByContainsVisibleText() {
167+
WebElement selectElement = driver.findElement(By.id("invisi_select"));
168+
Select select = new Select(selectElement);
169+
170+
assertThatExceptionOfType(UnsupportedOperationException.class)
171+
.isThrownBy(() -> select.selectByContainsVisibleText("Apples"));
172+
}
173+
174+
@Test
175+
void shouldNotAllowInvisibleOptionsToBeSelectedByContainsVisibleText() {
176+
WebElement selectElement = driver.findElement(By.id("invisible_multi_select"));
177+
Select select = new Select(selectElement);
178+
179+
assertThatExceptionOfType(NoSuchElementException.class)
180+
.isThrownBy(() -> select.selectByContainsVisibleText("Apples"));
181+
}
182+
165183
@Test
166184
void shouldThrowExceptionOnSelectByVisibleTextIfOptionDoesNotExist() {
167185
WebElement selectElement = driver.findElement(By.name("select_empty_multiple"));
@@ -260,6 +278,15 @@ void shouldAllowUserToDeselectOptionsByVisibleText() {
260278
assertThat(select.getAllSelectedOptions()).hasSize(1);
261279
}
262280

281+
@Test
282+
void shouldAllowUserToDeselectOptionsByContainsVisibleText() {
283+
WebElement selectElement = driver.findElement(By.name("multi"));
284+
Select select = new Select(selectElement);
285+
select.deSelectByContainsVisibleText("Egg");
286+
287+
assertThat(select.getAllSelectedOptions()).hasSize(1);
288+
}
289+
263290
@Test
264291
@Ignore(ALL)
265292
public void shouldNotAllowUserToDeselectOptionsByInvisibleText() {
@@ -270,6 +297,24 @@ public void shouldNotAllowUserToDeselectOptionsByInvisibleText() {
270297
.isThrownBy(() -> select.deselectByVisibleText("Apples"));
271298
}
272299

300+
@Test
301+
void shouldNotAllowUserDeselectOptionsByContainsText() {
302+
WebElement selectElement = driver.findElement(By.name("multi"));
303+
Select select = new Select(selectElement);
304+
305+
assertThatExceptionOfType(NoSuchElementException.class)
306+
.isThrownBy(() -> select.deSelectByContainsVisibleText("Eggs_"));
307+
}
308+
309+
@Test
310+
void shouldNotAllowUserDeselectOptionsByContainsInvisibleText() {
311+
WebElement selectElement = driver.findElement(By.id("invisible_multi_select"));
312+
Select select = new Select(selectElement);
313+
314+
assertThatExceptionOfType(NoSuchElementException.class)
315+
.isThrownBy(() -> select.deSelectByContainsVisibleText("Apples"));
316+
}
317+
273318
@Test
274319
void shouldAllowOptionsToBeDeselectedByIndex() {
275320
WebElement selectElement = driver.findElement(By.name("multi"));
@@ -316,6 +361,15 @@ void shouldThrowExceptionOnDeselectByVisibleTextIfOptionDoesNotExist() {
316361
.isThrownBy(() -> select.deselectByVisibleText("not there"));
317362
}
318363

364+
@Test
365+
void shouldThrowExceptionOnDeselectByContainsTextIfOptionDoesNotExist() {
366+
WebElement selectElement = driver.findElement(By.name("select_empty_multiple"));
367+
Select select = new Select(selectElement);
368+
369+
assertThatExceptionOfType(NoSuchElementException.class)
370+
.isThrownBy(() -> select.deSelectByContainsVisibleText("not there"));
371+
}
372+
319373
@Test
320374
void shouldThrowExceptionOnDeselectByIndexIfOptionDoesNotExist() {
321375
WebElement selectElement = driver.findElement(By.name("select_empty_multiple"));
@@ -351,4 +405,13 @@ void shouldNotAllowUserToDeselectByVisibleTextWhenSelectDoesNotSupportMultipleSe
351405
assertThatExceptionOfType(UnsupportedOperationException.class)
352406
.isThrownBy(() -> select.deselectByVisibleText("Four"));
353407
}
408+
409+
@Test
410+
void shouldNotAllowUserToDeselectByContainsTextDoesNotSupportMultipleSelections() {
411+
WebElement selectElement = driver.findElement(By.name("selectomatic"));
412+
Select select = new Select(selectElement);
413+
414+
assertThatExceptionOfType(UnsupportedOperationException.class)
415+
.isThrownBy(() -> select.deSelectByContainsVisibleText("Four"));
416+
}
354417
}

java/test/org/openqa/selenium/support/ui/SelectTest.java

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -250,6 +250,23 @@ void shouldAllowUserToDeselectOptionsByVisibleText() {
250250
verify(secondOption, never()).click();
251251
}
252252

253+
@Test
254+
void shouldAllowOptionsToDeSelectedByContainsVisibleText() {
255+
String parameterText = "b";
256+
final WebElement firstOption = mockOption("first", true);
257+
final WebElement secondOption = mockOption("second", false);
258+
259+
final WebElement element = mockSelectWebElement("multiple");
260+
when(element.findElements(By.xpath(".//option[contains(., " + Quotes.escape(parameterText) + ")]")))
261+
.thenReturn(Arrays.asList(firstOption, secondOption));
262+
263+
Select select = new Select(element);
264+
select.deSelectByContainsVisibleText(parameterText);
265+
266+
verify(firstOption).click();
267+
verify(secondOption, never()).click();
268+
}
269+
253270
@Test
254271
void shouldAllowOptionsToBeDeselectedByIndex() {
255272
final WebElement firstOption = mockOption("first", true, 2);

0 commit comments

Comments
 (0)