Using Selenium WebDriver to select JSF/PrimeFaces selectOneMenu options

I'm using JBehave with Selenium WebDriver to test my PrimeFaces (JSF2) application. Selecting an option from a SelectOne option list isn't standard though because of the HTML markup generated by the JSF component.


The facelets code to place the selectOneMenu uses the ID 'state':

<p:selectOneMenu id="state" value="#{myBean.state}">
<f:selectItem itemLabel="- Select One -" itemValue=""/>
<f:selectItems value="#{optionsBean.states}" var="item"
itemLabel="#{item.name}"
itemValue="#{item}"/>
</p:selectOneMenu>

This generates HTML div blocks with id's prefixed with this components id:

<div id="myForm:state" class="ui-selectonemenu ui-widget ui-state-default ui-corner-all ui-helper-clearfix" style="width: 147px;">
<div class="ui-helper-hidden">
<select id="myForm:state_input" name="myForm:state_input">
<option value="">- Select One -</option>
<option value="Enabled">Enabled</option>
<option value="Disabled">Disabled</option>
</select>
</div>
<div class="ui-helper-hidden-accessible">
<input id="myForm:state_focus" name="myForm:state_focus" type="text">
</div>
<label id="myForm:state_label" class="ui-selectonemenu-label ui-inputfield ui-corner-all" style="width: 137px;">- Select One -</label>
<div class="ui-selectonemenu-trigger ui-state-default ui-corner-right">
<span class="ui-icon ui-icon-triangle-1-s"></span>
</div>
</div>

To select an option, I use a method which manipulates the appropriate divs - this can be used as illustrated below:

/*
The facelets code uses the id "state"
<p:selectOneMenu id="state" value="#{myBean.state}">
...
</p:selectOneMenu>
*/
// sample invocation to select element
selectOne("myForm:state", "Disabled");
// select given option
public void selectOne(String idPrefix, String value) {
if (StringUtils.isNotBlank(value)) {
getDriver().findElement(By.id(idPrefix + "_label")).click();
getDriver().findElement(By.xpath("//div[@id='" + idPrefix + "_panel']/div/ul/li[text()='" + value + "']")).click();
}
}
view raw gistfile1.java hosted with ❤ by GitHub

To reuse this type of utility method, I put it in a base Page Object class:

import net.thucydides.core.pages.PageObject;
import org.apache.commons.lang3.StringUtils;
import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;
public abstract class AbstractPage extends PageObject {
public AbstractPage(WebDriver driver) {
super(driver);
}
public void waitForAjax() {
waitForRenderedElements(By.className("ajaxLoadingImg"));
waitForRenderedElementsToDisappear(By.className("ajaxLoadingImg"));
}
public void clickLinkWithText(String linkText) {
getDriver().findElement(By.linkText(linkText)).click();
}
public void selectOne(String idPrefix, String value) {
if (StringUtils.isNotBlank(value)) {
getDriver().findElement(By.id(idPrefix + "_label")).click();
getDriver().findElement(By.xpath("//div[@id='" + idPrefix + "_panel']/div/ul/li[text()='" + value + "']")).click();
}
}
}


Popular posts from this blog

AspectJWeaver with JDK 7 - error - only supported at Java 5 compliance level or above

Intellij tip - Joining multiple lines into one

JUnit parameterized test with Spring autowiring AND transactions