Reputation: 1240
In using C#, Selenium webdriver, I navigate to a page, which might redirect to a login screen or eventually redirect or not to the actual app page, depending on whether I have cached credentials or not. (case in point azure active dir auth).
What I am after is to find if a known element of my app page appears or the login screen of azure auth with an element id "use_another_account_link" appears. SO I want to OR the condition of ExpectedConditions without having to wait N seconds on each.
Upvotes: 3
Views: 3972
Reputation: 580
The accepted answer is undoubtedly correct from a CSS/XPath perspective, however it may not always do what is expected when used with certain Selenium ExpectedConditions. In the case where you want to wait for a login page to display, but also need to cater for the fact that this page will display either:
WebElement login = (new WebDriverWait(driver, Duration.ofSeconds(5))).until(
ExpectedConditions.visibilityOfElementLocated(
By.cssSelector("input#userid, input#pass")
));
Instead it is necessary to use ExpectedConditions.or
to determine whether either field is both present and visible:
boolean bDisplayed = (new WebDriverWait(driver, Duration.ofSeconds(5))).until(ExpectedConditions.or(
ExpectedConditions.visibilityOfElementLocated(By.cssSelector("#userid")), ExpectedConditions.visibilityOfElementLocated(By.cssSelector("#pass"))
));
and then proceed to work out which field is visible.
Upvotes: 0
Reputation: 2217
Wait until at least anyone condition returns true
wait.until(
ExpectedConditions.or(
ExpectedConditions.visibilityOfAllElementsLocatedBy(By.name("Services")),
ExpectedConditions.visibilityOfAllElementsLocatedBy(By.name("Products"))
ExpectedConditions.visibilityOfAllElementsLocatedBy(By.name("Contact Us"))
)
);
Upvotes: 0
Reputation: 42518
You could use a CSS selector with two expessions separated by a ,
to implement the OR :
WebDriverWait wait = new WebDriverWait(driver, TimeSpan.FromSeconds(10));
var element = wait.Until(ExpectedConditions.ElementExists(By.CssSelector("#id1, #id2")));
if (element.GetAttribute("id") == "id1") {
// handle element with id="id1"
} else {
// handle element with id="id2"
}
Or an XPath with two expessions separated by a |
:
var element = wait.Until(ExpectedConditions.ElementExists(By.XPath("id('id1') | id('id2')")));
if (element.GetAttribute("id") == "id1") {
// handle element with id="id1"
} else {
// handle element with id="id2"
}
Upvotes: 3
Reputation: 13999
This is a case where you have to provide your own Func<IWebElement, IWebElement>
to IWait<IWebElement>.Until()
. You can write something specific like this:
(Func<IWebElement, IWebElement>)
(return ExpectedConditions.ElementExists(By.Id("use_another_account_link"))
|| ExpectedConditions.ElementExists(By.Id("your_login_field_id")))
Or something generic like this:
public Func<IWebElement, IWebElement> Or(Func<IWebElement, IWebElement> either,
Func<IWebElement, IWebElement> or) {
return (Func<IWebElement, IWebElement>) either || or;
}
Upvotes: 0