Most applications have at least some pages that require authenticated access. So you will need your test to log in to the application before you start testing the secure page. JSFUnit provides a way to easily log in when the JSFSession is started.
We do this using the Strategy pattern. You provide an implementation of InitialRequestStrategy. For applications that use JEE container-managed security, JSFUnit has built-in strategy objects for BASIC and FORM authentication.
Here is an example using the BasicAuthenticationStrategy.
WebClientSpec wcSpec = new WebClientSpec("/mysecurepage.jsf");
wcSpec.setInitialRequestStrategy(new BasicAuthenticationStrategy("username", "password"));
JSFSession jsfSession = new JSFSession(wcSpec);
JSFClientSession client = jsfSession.getJSFClientSession();
JSFServerSession server = jsfSession.getJSFServerSession();
For form authentication, you use the FormAuthenticationStrategy. Besides user name and password, you will usually need to provide a reference to the submit button so that JSFUnit can automatically submit the form.
<form method="POST" action="j_security_check" name="loginform" id="loginform">
<tr>
<td>username</td><td><input type="text" name="j_username"/></td>
</tr>
<tr>
<td>password</td><td><input type="password" name="j_password"/></td>
</tr>
<tr><td><input type="submit" name="login_button" value="login"/></td></tr>
</form>
WebClientSpec wcSpec = new WebClientSpec("/mysecurepage.jsf");
FormAuthenticationStrategy formAuth = new FormAuthenticationStrategy("username", "password");
formAuth.setSubmitComponent("login_button");
wcSpec.setInitialRequestStrategy(formAuth);
JSFSession jsfSession = new JSFSession(wcSpec);
JSFClientSession client = jsfSession.getJSFClientSession();
JSFServerSession server = jsfSession.getJSFServerSession();
Note that the reference to the submit button, "login_button", is the value of the "name" attribute and not the "id" attribute. If you do not call formAuth.setSubmitComponent(), it will default to "Submit".
For any application that does not use container-managed BASIC or FORM authentication, you will need to write your own implementation of InitialRequestStrategy. The javadoc is here. Usually, you will just subclass SimpleInitialRequestStrategy and then use the HtmlUnit API to get you past whatever security is in place. The source code for FormAuthenticationStrategy serves as a good example:
public class FormAuthenticationStrategy extends SimpleInitialRequestStrategy
{
private String userName;
private String password;
private String submitComponent = "Submit";
public FormAuthenticationStrategy(String userName, String password)
{
this.userName = userName;
this.password = password;
}
public void setSubmitComponent(String submitComponent)
{
this.submitComponent = submitComponent;
}
/**
* Perform the initial request and provide FORM authentication
* credentials when challenged.
*
* @param wcSpec The WebClient specification.
*
* @return The requested page if authentication passed. Otherwise, return
* the error page specified in web.xml.
*/
public Page doInitialRequest(WebClientSpec wcSpec) throws IOException
{
HtmlPage page = (HtmlPage)super.doInitialRequest(wcSpec);
setValue(page, "j_username", this.userName);
setValue(page, "j_password", this.password);
return clickSubmitComponent(page);
}
protected Page clickSubmitComponent(HtmlPage page) throws IOException
{
HtmlElement htmlElement = getElement(page, this.submitComponent);
if (!(htmlElement instanceof ClickableElement))
{
throw new IllegalStateException("Component with name=" + this.submitComponent + " is not a ClickableElement.");
}
ClickableElement clickable = (ClickableElement)htmlElement;
return clickable.click();
}
protected void setValue(HtmlPage page, String elementName, String value)
{
HtmlElement element = getElement(page, elementName);
if (!(element instanceof HtmlInput))
{
throw new IllegalStateException("Component with name=" + elementName + " is not an HtmlInput element.");
}
HtmlInput inputElement = (HtmlInput)element;
inputElement.setValueAttribute(value);
}
protected HtmlElement getElement(HtmlPage page, String elementName)
{
List<HtmlElement> elements = page.getHtmlElementsByName(elementName);
if (elements.size() == 0)
{
throw new IllegalStateException("Component with name=" + elementName + " was not found on the login page.");
}
if (elements.size() > 1)
{
throw new IllegalStateException("More than one component with name=" + elementName + " was found on the login page.");
}
return elements.get(0);
}
Referenced by:
There are no comments on this article