I'm rewriting some Selenium tests according to the page object design pattern taking advantage of Seleniums' annotations. My problem is that I have some html select
elements whose option
elements are loaded dynamically. These are not available at the same time the select
s are.
The original code looks like:
public void fillinForm() {
// Fill-in some fields ...
// Select dynamic loaded option
String optionXpath = "//*[@id='field']/option[text()='Software engineering']";
waitForElement(driver, By.xpath(optionXpath), SHORT_TIMEOUT_S);
driver.findElement(By.xpath(optionXpath)).click();
// Fill-in more fields, etc ...
}
// Selenium wait
public static void waitForElement(WebDriver driver, By by, int timeout) {
// implementation
}
The new code turns into something like:
public void setUp() {
page = PageFactory.initElements(driver, Page.class);
}
public void fillinForm() {
page.setField("Software engineering");
}
public class Page {
private webElement field;
public Page setField(String byText) {
field.click();
String optionXpath = String.format("./option[text()='%s']", byText);
field.findElement(By.xpath(optionXpath)).click();
return this;
}
}
If I want to implement the wait in the new code, I have to use an xpath for the option
that includes the xpath for the select
, thus losing the advantage of using annotations to simplify the code:
public void fillinForm() {
page.setField("Software engineering");
}
public class Page {
private webElement field;
public Page setField(String byText) {
field.click();
// Note that I'm now explicitly writing "field", exactly what I wanted
// to save using annotations and the PageFactory
String optionXpath = String.format("//select[@id='%s']/option[text()='%s']",
"field", byText);
field.findElement(By.xpath(optionXpath)).click();
return this;
}
}
Is there any annotation I can use to wait until the options are loaded, or am I using this wrong?
1 Answer 1
After spending some more time with WebDriverWait, I came out with something nicer:
Client code:
/** Page Object. */
public class Page {
private WebElement mySelect;
public Page setMySelect(String optionText) {
String optXpath = String.format("./option[text()='%s']", optionText);
mySelect.click();
waitForOption(driver,mySelect, By.xpath(optXpath), 10)
.click();
}
}
Utility library:
public class Util {
/**
* Waits until the option targeted by <tt>byOption</tt> is available.
*
* @param select parent element of the option to wait for
* @param byOption selector (relative to the <tt>select</tt>). It will be
* searched calling <tt>select.findElement(byOption)</tt>
* @return option element
*/
public static WebElement waitForOption(
WebDriver driver, WebElement select, By byOption, int seconds) {
Wait<WebDriver> wait = new WebDriverWait(driver, seconds);
return wait.until(new OptionAvailable(select, byOption));
}
public static class OptionAvailable
implements ExpectedCondition<WebElement> {
private WebElement select;
private By byOption;
public OptionAvailable(WebElement select, By byOption) {
this.select = select;
this.byOption = byOption;
}
@Override
public WebElement apply(WebDriver input) {
return select.findElement(byOption);
}
}
}
Note that with this approach (a By
for the option), we can support the option as text or as value.
-
I'm testing it now, and it seems that it doesn't work :-( The two consecutive clicks (in select and in option) are failing somehow, and unfortunately it is not easy to debug, as the debugger interferes with the normal flow.Alberto– Alberto2011年07月27日 17:47:19 +00:00Commented Jul 27, 2011 at 17:47
-
Indeed, it works removing the
mySelect.click()
. I'm a bit confused now, as I was "double"-clicking due to Selenium's issue 2112. I have to check if without this "double" click it still works in my SUSE Linux Enterprise Server 11 box with Firefox 3.6.18Alberto– Alberto2011年07月27日 18:52:01 +00:00Commented Jul 27, 2011 at 18:52
Explore related questions
See similar questions with these tags.