-
1. Re: multiple requests
ssilvert Sep 16, 2008 12:43 PM (in response to trossmy)This wiki should help you out:
http://wiki.jboss.org/wiki/JSFUnitTestingSecurePages
You'll probably just want to extend SimpleInitialRequestStrategy and insert your special login logic. That will get you past the login page each time you want to start a new JSFSession.
Let us know how it goes.
Stan -
2. Re: multiple requests
trossmy Sep 18, 2008 10:49 AM (in response to trossmy)so I tried that strategy, i could use a slightly modified FormAuthentificationStrategy, what does not work though is that the page returned by
public Page doInitialRequest(WebClientSpec wcSpec) throws IOException { HtmlPage page = (HtmlPage)super.doInitialRequest(wcSpec); setValue(page, "loginForm:name", this.userName); setValue(page, "loginForm:password", this.password); return clickSubmitComponent(page); }
is alway empty, even though the webapp does everything as expected. Am I missing something here? -
3. Re: multiple requests
ssilvert Sep 18, 2008 1:18 PM (in response to trossmy)Maybe I can help. Can you post the whole class so I can see exactly what you did?
Stan -
4. Re: multiple requests
trossmy Sep 19, 2008 4:13 AM (in response to trossmy)Hi Stan! Thanks! Well it's basically your FormauthenticationStrategy, only that I replaced the userName and password inputText id's with those that we are using. But it's not a JEE container-managed security system, maybe that is the problem?
import com.gargoylesoftware.htmlunit.Page; import com.gargoylesoftware.htmlunit.html.ClickableElement; import com.gargoylesoftware.htmlunit.html.HtmlElement; import com.gargoylesoftware.htmlunit.html.HtmlInput; import com.gargoylesoftware.htmlunit.html.HtmlPage; import java.io.IOException; import java.util.List; import org.jboss.jsfunit.framework.SimpleInitialRequestStrategy; import org.jboss.jsfunit.framework.WebClientSpec; public class FormAuthenticationStrategy extends SimpleInitialRequestStrategy { private String userName; private String password; private String submitComponent = "loginForm:loginSubmit"; /** * Create a new FormAuthenticationStrategy. * * @param userName The user name. * @param password The password. */ public FormAuthenticationStrategy(String userName, String password) { this.userName = userName; this.password = password; } /** * Set the name of the submit component. This should be the value of the * name attribute that will cause the username/password to be submitted. Note * that this is the name attribute and not the id attribute. The default * value is "Submit". * * @param submitComponent The name of the component that will submit the credentials. */ 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, "loginForm:name", this.userName); setValue(page, "loginForm: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); } }
The webapp works like this: Whenever there is a request a phaselistener checks if there is a valid user object in the session, if that is not the case it redirects to the login page. After successfull login the user then is redirected to the originally requested page. In the jsfUnit test the expected viewId is correct, but all the components are null. Im using the repository snapshot 1.0GA-SNAPSHOT -
5. Re: multiple requests
trossmy Sep 19, 2008 4:28 AM (in response to trossmy)forgot the test:
WebClientSpec wcSpec = new WebClientSpec("/myServletPath.action"); wcSpec.setInitialRequestStrategy(new FormAuthenticationStrategy("myUser", "123456")); HtmlPage page = (HtmlPage) wcSpec.doInitialRequest(); FacesContext facesContext = FacesContextBridge.getCurrentInstance(); UIViewRoot root = facesContext.getViewRoot(); boolean b = root.getViewId().equals("/myServletPath.jspx"); assertTrue(b); HtmlInput inputText = (HtmlInput) page.getElementById("myForm:myId"); assertNotNull(inputText); // this assert fails
-
6. Re: multiple requests
ssilvert Sep 19, 2008 7:44 AM (in response to trossmy)You need to pass the wcSpec to a JSFSession. You should not call wcSpec.doInitialRequest() directly.
JSFSession jsfSession = new JSFSession(wcSpec);
Stan -
7. Re: multiple requests
trossmy Sep 22, 2008 12:08 PM (in response to trossmy)ok, I found the solution, the reason the login action was not executed was that the phaselistener would always redirect a request with uiViewRoot ==null where uiViewRoot is
UIViewRoot uiViewRoot = facesContext.getViewRoot()
to the login page which somehow works allright with browsers that do have a head;-) but not with the underlying htmlunit Library where the submitted requests seem to always have a blank uiViewRoot