After reviewing the selenium docs, I am wondering if I am attempting to implement explicit waits incorrectly.
In the docs, it always shows identifying a new element, then assigning the defined wait to said element
WebDriver driver = new ChromeDriver();
driver.get("https://google.com/ncr");
driver.findElement(By.name("q")).sendKeys("cheese" + Keys.ENTER);
// Initialize and wait till element(link) became clickable - timeout in 10 seconds
WebElement firstResult = new WebDriverWait(driver, Duration.ofSeconds(10))
.until(ExpectedConditions.elementToBeClickable(By.xpath("//a/h3")));
// Print the first result
System.out.println(firstResult.getText());
In this example, a new element firstResult is created, then the defined wait assigned to it.
Is this required? Should always be done this way?
This is why I ask.
I am using the PageFactory model and have my elements defined via the FindBy annotation, as shown here.
// Input field for slice ID
@FindBy(how = How.XPATH, using = "//input[@name='id']")
private WebElement inputSliceId;
Then, in that same class, I have defined some convenience methods to use them.
So now, in my convenience methods, should I do things like this?
inputSliceId = new WebDriverWait(driver, Duration.ofSeconds(10))...
inputSliceId.sendKeys(...
What I have been doing, which is what I'm questioning now, is putting wait statements that are not being assigned directly to the element in question.
For example, I've been doing things like this.
buttonSubmit.click();
WebDriverWait wait = new WebDriverWait(driver, 5);
wait.until(ExpectedConditions.visibilityOfElementLocated(By.xpath("//div[@role='alertdialog']")));
wait.until(ExpectedConditions.invisibilityOfElementLocated(By.xpath("//div[@role='alertdialog']")));
Why? (could totally be wrong here)
Upon clicking the button, I need to wait for a pop-up to display Once it does, I am then waiting for it to disappear, before proceeding
Here's the main question Are these two wait lines not really doing anything because I am not assigning them to an element? Or are they still causing the web driver to hold until the conditions specified by the wait occur?
No, You can't assigned wait statement as above to your web element. If you want to wait for your element using Page factory model for a below element then you have to create
public void isLoaded() throws Error { // Initial loading, called when creating the page object to make sure that the page is loaded to a state where it is ready to interact with us, in our case it means that button is present in DOM and visible.
public class BaseClass
{
private void waitForVisibility(WebElement element) throws Error{
new WebDriverWait(driver, 60)
.until(ExpectedConditions.visibilityOf(element));
}
}
And then in your page object model class you can extend this BaseClass.
public class page extends BaseClass
{
@FindBy(how = How.XPATH, using = "//input[@name='id']")
private WebElement inputSliceId;
waitForVisibility(inputSliceId);
}
I have defined wait in the BaseClass to achieve re-usability of waitForVisibility code across all page object classes.
Also after button clicking if you want to wait for a pop up to be appear then you can include code like below:
@FindBy(xpath = "//div[@role='alertdialog']")
private WebElementFacade alertPopup;
buttonSubmit.click();
waitForVisibility(alertPopup);