Reputation: 179
i'm using @FindBy annotations to locate elements on my page. Like this:
@FindBy(xpath = "//textarea")
public InputBox authorField;
Please, help. I want use wait (ExpectedConditions) with my annotated elements. Like this:
wait.until(visibilityOfElementLocated(authorField));
instead of:
wait.until(visibilityOfElementLocated(By.xpath("//textarea")));
Thanks for advance
Upvotes: 4
Views: 13171
Reputation: 107
As mentioned in other answers, ExpectedConditions.visibilityOf(authorField);
will do the job. Mentioning a detailed solution below for more clarity.
public class YourTestPage {
private WebDriver driver;
private WebDriverWait wait;
@FindBy(xpath = "//textarea")
private WebElement authorField;
public YourTestPage(WebDriver driver) {
this.driver = driver;
wait = new WebDriverWait(driver, 15, 50);
PageFactory.initElements(driver,this);
}
public void enterAuthorName() {
wait.until(ExpectedConditions.visibilityOf(authorField)).sendKeys("Author Name");
}
}
Upvotes: 1
Reputation: 545
I know that this question is already answered and was asked a while ago, but I figured that I'd provide a concrete example of how to write your own Expected Condition for this. By creating this Expected Condition class:
/**
* Since the proxy won't try getting the actual web element until you
* call a method on it, and since it is highly unlikely (if not impossible)
* to get a web element that doesn't have a tag name, this simply will take
* in a proxy web element and call the getTagName method on it. If it throws
* a NoSuchElementException then return null (signaling that it hasn't been
* found yet). Otherwise, return the proxy web element.
*/
public class ProxyWebElementLocated implements ExpectedCondition<WebElement> {
private WebElement proxy;
public ProxyWebElementLocated(WebElement proxy) {
this.proxy = proxy;
}
@Override
public WebElement apply(WebDriver d) {
try {
proxy.getTagName();
} catch (NoSuchElementException e) {
return null;
}
return proxy;
}
}
Then this will allow you to do:
wait.until(new ProxyWebElementLocated(authorField));
And that's all you really need. But if you want to take the abstraction one step further, you could create a class like this:
public final class MyExpectedConditions {
private MyExpectedConditions() {}
public static ExpectedCondition<WebElement> proxyWebElementLocated(WebElement proxy) {
return new ProxyWebElementLocated(proxy);
}
}
Which would then allow you to do something like this:
wait.until(MyExpectedConditions.proxyWebElementLocated(authorField));
The MyExpectedConditions
class can be a bit overkill for one Expected Condition, but if you have multiple Expected Conditions, then having it will make things much nicer.
As a final note for any that really want to go the extra mile, you can also add methods to the MyExpectedConditions
class that wrap the methods in the ExpectedConditions
class, and then you can get all your Expected Conditions stuff from one place. (I'd suggest extending ExpectedConditions
instead of doing the wrapper methods, but it has a private constructor, making it impossible to extend. This leaves wrapper methods as the only option for those that really want everything in one place.)
Upvotes: 3
Reputation: 38414
The problem is that methods taking a WebElement
usually assume the WebElement was already found (And they are right! PageFactory arranges it so that just before the element is accessed by a method, it is found.), i.e. exists on the page. When giving a By to the method, you say "I want it to be found, I just don't know when will it show up."
You can use
wait.until(visibilityOf(authorField));
in conjuction with
// right after driver is instantiated
driver.manage().timeouts().implicitlyWait(...);
That should do it just the way you'd like.
implicitlyWait()
documentation says:
Specifies the amount of time the driver should wait when searching for an element if it is not immediately present.
When searching for a single element, the driver should poll the page until the element has been found, or this timeout expires before throwing a NoSuchElementException. When searching for multiple elements, the driver should poll the page until at least one element has been found or this timeout has expired.
So, basically, it waits for an element to show up every time it is looked up. Which is good for all sorts of asynchronous requests, obviously.
Upvotes: 5
Reputation: 1559
ExpectedConditions.visibilityOf(authorField);
Look at the source code of any Expected condition. It's very easy to write your own condition that can do everything you want.
Upvotes: 5