Skip to content

Commit 58bbb1d

Browse files
committed
fix "or" condition
We need to re-try in case of `NoSuchElementException`, not only `StaleElementReferenceException`. `NoSuchElementException` may be thrown by a page object because its @findby fields are lazy-initialized. Fixes #17091
1 parent 1c6caf0 commit 58bbb1d

2 files changed

Lines changed: 32 additions & 13 deletions

File tree

‎java/src/org/openqa/selenium/support/ui/ExpectedConditions.java‎

Lines changed: 28 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -399,7 +399,7 @@ public static ExpectedCondition<Boolean> textToBePresentInElement(
399399

400400
return new ExpectedCondition<>() {
401401
private @Nullable String elementText;
402-
private @Nullable StaleElementReferenceException error;
402+
private @Nullable WebDriverException error;
403403

404404
@Override
405405
public Boolean apply(WebDriver driver) {
@@ -408,7 +408,7 @@ public Boolean apply(WebDriver driver) {
408408
try {
409409
elementText = element.getText();
410410
return elementText.contains(text);
411-
} catch (StaleElementReferenceException e) {
411+
} catch (StaleElementReferenceException | NoSuchElementException e) {
412412
error = e;
413413
return false;
414414
}
@@ -481,7 +481,7 @@ public static ExpectedCondition<Boolean> textToBePresentInElementValue(
481481

482482
return new ExpectedCondition<>() {
483483
private @Nullable String actualValue;
484-
private @Nullable StaleElementReferenceException error;
484+
private @Nullable WebDriverException error;
485485

486486
@Override
487487
public Boolean apply(WebDriver driver) {
@@ -490,7 +490,7 @@ public Boolean apply(WebDriver driver) {
490490
try {
491491
actualValue = element.getAttribute("value");
492492
return actualValue != null && actualValue.contains(expectedValue);
493-
} catch (StaleElementReferenceException e) {
493+
} catch (StaleElementReferenceException | NoSuchElementException e) {
494494
error = e;
495495
return false;
496496
}
@@ -825,7 +825,7 @@ public Boolean apply(WebDriver ignored) {
825825
// Calling any method forces a staleness check
826826
element.isEnabled();
827827
return false;
828-
} catch (StaleElementReferenceException expected) {
828+
} catch (StaleElementReferenceException | NoSuchElementException expected) {
829829
return true;
830830
}
831831
}
@@ -855,7 +855,7 @@ public String toString() {
855855
public @Nullable T apply(WebDriver driver) {
856856
try {
857857
return condition.apply(driver);
858-
} catch (StaleElementReferenceException e) {
858+
} catch (StaleElementReferenceException | NoSuchElementException e) {
859859
return null;
860860
}
861861
}
@@ -1677,15 +1677,21 @@ private static boolean isInvisible(final WebElement element) {
16771677
*/
16781678
public static ExpectedCondition<Boolean> or(final ExpectedCondition<?>... conditions) {
16791679
return new ExpectedCondition<>() {
1680+
@Nullable final Object[] results = new Object[conditions.length];
1681+
16801682
@Override
16811683
public Boolean apply(WebDriver driver) {
1682-
for (ExpectedCondition<?> condition : conditions) {
1684+
for (int i = 0; i != conditions.length; ++i) {
1685+
ExpectedCondition<?> condition = conditions[i];
1686+
results[i] = null;
16831687
try {
16841688
Object result = condition.apply(driver);
16851689
if (Boolean.TRUE.equals(result) || result != null && !(result instanceof Boolean)) {
16861690
return true;
16871691
}
1688-
} catch (StaleElementReferenceException ignore) {
1692+
results[i] = result;
1693+
} catch (RuntimeException e) {
1694+
results[i] = e;
16891695
}
16901696
}
16911697
return false;
@@ -1696,10 +1702,23 @@ public String toString() {
16961702
StringBuilder message =
16971703
new StringBuilder("at least one condition to be valid:").append(lineSeparator());
16981704
for (int i = 0; i < conditions.length; i++) {
1699-
message.append(i + 1).append(". ").append(conditions[i]).append(lineSeparator());
1705+
message
1706+
.append(i + 1)
1707+
.append(". ")
1708+
.append(conditions[i])
1709+
.append(resultAsString(results[i]))
1710+
.append(lineSeparator());
17001711
}
17011712
return message.toString();
17021713
}
1714+
1715+
private Object resultAsString(@Nullable Object result) {
1716+
return Boolean.FALSE.equals(result)
1717+
? ""
1718+
: result instanceof WebDriverException
1719+
? " (caused by: " + shortDescription((WebDriverException) result) + ")"
1720+
: " (actual: " + result + ")";
1721+
}
17031722
};
17041723
}
17051724

‎java/test/org/openqa/selenium/support/ui/ExpectedConditionsTest.java‎

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -966,8 +966,7 @@ void whenOneThrows() {
966966
.thenReturn("16pt")
967967
.thenReturn("17pt")
968968
.thenReturn("18pt");
969-
when(mockElement.getText())
970-
.thenThrow(new StaleElementReferenceException("Element disappeared"));
969+
when(mockElement.getText()).thenThrow(new NoSuchElementException("Element disappeared"));
971970

972971
assertThat(
973972
wait.until(
@@ -981,7 +980,7 @@ void whenOneThrows() {
981980
void whenAllThrow() {
982981
String attributeName = "test";
983982
when(mockElement.getAttribute(attributeName))
984-
.thenThrow(new StaleElementReferenceException("Disappeared 1"));
983+
.thenThrow(new NoSuchElementException("Disappeared 1"));
985984
when(mockElement.getCssValue(attributeName))
986985
.thenThrow(new StaleElementReferenceException("Disappeared 2"));
987986
when(mockElement.getText()).thenThrow(new StaleElementReferenceException("Disappeared 3"));
@@ -999,7 +998,8 @@ void whenAllThrow() {
999998
+ "1. element to have text \"test\", but..."
1000999
+ " org.openqa.selenium.StaleElementReferenceException: Disappeared 3."
10011000
+ lineSeparator()
1002-
+ "2. attribute or CSS value \"test\"=\"test\". Current value: \"null\".")
1001+
+ "2. attribute or CSS value \"test\"=\"test\". Current value: \"null\". (caused"
1002+
+ " by: org.openqa.selenium.NoSuchElementException: Disappeared 1)")
10031003
.hasMessageContaining("tried for 1.1 seconds with 250 milliseconds interval");
10041004
}
10051005
}

0 commit comments

Comments
 (0)