6 Replies Latest reply on Apr 8, 2008 9:15 AM by ssilvert

    WebResponse not up to date when using client.click

    laurentn

      Hi

      I'm currently trying to develop my own api to test my web site.
      I'm wrapping a web page into a java class

      So for example i have a basic page Page that owns a JSFClientSession and a JSFServerSession

      public class Page
      {
       private JSFClientSession client;
       private JSFServerSession server;
      
       public Page(String pageName)
       {
       client = new JSFClientSession(pageName);
       server = new JSFServerSession(client);
       }
      
       public Page(Page page)
       {
       client=page.client;
       server = page.server;
       }
      
       public void clickOnLinkWithId(String id)
       {
       client.click();
       }
      
       public MySecondPage goToSecondPage()
       {
       clientOnLinkWithId("nextPage");
       return new MySecondPage(this);
       }
      
       public void setFormParameter(String id, String value)
       {
       client.setParameter(id, value);
       }
      }
      
      public class MySecondPage extends Page
      {
       public MySecondPage(Page page)
       {
       super(page);
       }
      
       public static MySecondPage getPage()
       {
       return new Page("index.jsp").goToSecondPage();
       }
      }
      

      and so, in my test case:
      public class MyTest extends ServletTest
      {
       public void testMyTest()
       {
       MySecondPage page = MySecondPage.getPage();
       page.setFormParameter("myInput", "myValue");
       }
      }
      


      Actually, my classes are a bit longer than the above code, by the exception is thrown in page.setFormParamter

      This is because, the client.getUpdatedDOM is still on the first page, and the client is not updated when we click on the link (the link is a simple outputlink)
      Only client.getWebResponse().getDOM is well updated
      and server.getCurrentViewId is good also.

      The exception is this one (with my own code)
      java.lang.NullPointerException
      at org.jboss.jsfunit.facade.JSFClientSession.setValueOnDOM(JSFClientSession.java:230)
      at org.jboss.jsfunit.facade.JSFClientSession.setParameter(JSFClientSession.java:248)
      at kiwi.jsfunit.api.Page.setFormParameter(Page.java:229)
      at jsfunit.api.administration.AdministrationEditHelpDesks.fillAndSubmit(AdministrationEditHelpDesks.java:87)
      at jsfunit.admin.hd.HelpDeskEditTest.testUploadPicture(HelpDeskEditTest.java:94)
      at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)


      I hope i'm clear enough, and any help is welcome.

      Thanks
      Laurent

        • 1. Re: WebResponse not up to date when using client.click
          ssilvert

          I'll help as much as I can.

          I see this problem:

          public static MySecondPage getPage()
           {
           return new Page("index.jsp").goToSecondPage();
           }


          The argument to the JSFClientSession constructor must be a JSF request. It should be something like "/index.jsf".

          This code below shouldn't even compile because there is no JSFClientSession.click() method:
          public void clickOnLinkWithId(String id)
           {
           client.click();
           }


          I don't understand why you created the MySecondPage class. You don't need to do anything special to go from one page to another in a JSFUnit test. For instance, if you said:

          JSFClientSession client = new JSFClientSession("/index.jsf");
          client.submit("my_button");


          Your client instance would be loaded with the resulting screen. You could continue to use that same client instance to set parameters and do a submit for the second screen. So a single JSFClientSession instance can be used to navigate through your whole application if you wish. That being said, it is more common to test navigation paths that involve only two or three screens, but you get the idea.

          This is why JSFClientSession has "Session" in its name. It represents a browser session.

          Also, because JSFServerSession requires a JSFClientSession in its constructor, JSFServerSession and JSFClientSession are always linked. You don't need to create an artificial wrapper to keep them in sync. JSFUnit will do that for you.

          Stan

          • 2. Re: WebResponse not up to date when using client.click
            laurentn

            hum ok, but let's try to formulate my issue differently.

            public void testClickAdminbis()
             throws IOException, SAXException
             {
            // i need to login to be able to navigate
             JSFClientSession c = new JSFClientSession("/faces/login.jsp");
             JSFServerSession s = new JSFServerSession(c);
            
             c.setParameter("form:login", "laurent");
             c.setParameter("form:password", "xxx");
             c.submit();
            
             String[] cookies = c.getWebConversation().getCookieNames();
            
             c.getWebConversation().putCookie(cookies[0], c.getWebConversation().getCookieValue(cookies[0]));
            
             // i click on some links in order to access my page
             c.clickLink("tabAdmin");
            
             c.clickLink("tabAdminHelpDesksOff");
            
             c.submit("emptyForm:button_create");
            
             // once on the page, i fill the form. but i'm not on the good page
             // throw NullPointerException
             // org.jboss.jsfunit.facade.JSFClientSession.setValueOnDOM(JSFClientSession.java:230)
             // org.jboss.jsfunit.facade.JSFClientSession.setParameter(JSFClientSession.java:248)
             c.setParameter("form:name", "foooo");
             }
            


            This test has the same behaviour, but i access the page directly withtout clicking on links
             public void testClickAdminTer()
             throws IOException, SAXException
             {
             JSFClientSession c = new JSFClientSession("/faces/login.jsp");
             JSFServerSession s = new JSFServerSession(c);
            
             c.setParameter("form:login", "laurent");
             c.setParameter("form:password", "xxx");
             c.submit();
            
             String[] cookies = c.getWebConversation().getCookieNames();
            
             c.getWebConversation().putCookie(cookies[0], c.getWebConversation().getCookieValue(cookies[0]));
            
            // throws javax.xml.transform.TransformerException: org.w3c.dom.DOMException: NAMESPACE_ERR: An attempt is made to create or change an object in a way which is incorrect with regard to namespaces.
             c=new JSFClientSession(c.getWebConversation(), "/faces/administrationHelpDesks.jsp");
             c.submit("emptyForm:button_
             c.setParameter("form:name", "foooo");
             }
            


            and another one, with a new webConversation
             public void testClickAdmin4()
             throws IOException, SAXException
             {
             JSFClientSession c = new JSFClientSession("/faces/login.jsp");
             JSFServerSession s = new JSFServerSession(c);
            
             c.setParameter("form:login", "laurent");
             c.setParameter("form:password", "xxx");
             c.submit();
            
             String[] cookies = c.getWebConversation().getCookieNames();
            
             c.getWebConversation().putCookie(cookies[0], c.getWebConversation().getCookieValue(cookies[0]));
             // throws javax.xml.transform.TransformerException: org.w3c.dom.DOMException: NAMESPACE_ERR: An attempt is made to create or change an object in a way which is incorrect with regard to namespaces.
             c = new JSFClientSession("/faces/administrationHelpDesks.jsp");
             c.submit("emptyForm:button_create");
             c.setParameter("form:name", "foooo");
             }
            


            And this last one, making a webRequest with the JSFClientSession
             public void testClickAdmin5()
             throws IOException, SAXException
             {
             JSFClientSession c = new JSFClientSession("/faces/login.jsp");
             JSFServerSession s = new JSFServerSession(c);
            
             c.setParameter("form:login", "laurent");
             c.setParameter("form:password", "xxx");
             c.submit();
            
             String[] cookies = c.getWebConversation().getCookieNames();
            
             c.getWebConversation().putCookie(cookies[0], c.getWebConversation().getCookieValue(cookies[0]));
             // throws javax.xml.transform.TransformerException: org.w3c.dom.DOMException: NAMESPACE_ERR: An attempt is made to create or change an object in a way which is incorrect with regard to namespaces.
             GetMethodWebRequest req = new GetMethodWebRequest(WebConversationFactory.getWARURL()+"/faces/administrationHelpDesks.jsp");
             c.doWebRequest(req);
             c.submit("emptyForm:button_create");
             c.setParameter("form:name", "foooo");
             }
            
            


            So, i'd like to know how to avoid the NullPointerException, and/or to know how can we prevent from having a NAMESPACE_ERR (and why it is thrown)

            Thanks

            • 3. Re: WebResponse not up to date when using client.click
              ssilvert

              So I assume you have path-mapped the FacesServlet? So /faces/* maps to JSF? That's fine. JSFUnit will work that way, but most people use extension mapping, I'm interested to know.

              I don't see what your JSF page looks like, but clickLink is only used for static navigation using the <h:outputLink> tag. Once you follow a static link you are no longer looking at a JSF page. So you can only use the HttpUnit API from that point. Some JSFClientSession methods will work, but you should just call c.getWebConversation() and/or c.getWebResponse() and use HttpUnit.

              I suspect that what you really want to do is to use a command link instead of an output link. That will keep you within the confines of JSF.

              See http://wiki.jboss.org/wiki/JSFClientSessionAPI.

              Stan

              • 4. Re: WebResponse not up to date when using client.click
                laurentn

                Just a note to let you know that the error
                throws javax.xml.transform.TransformerException: org.w3c.dom.DOMException: NAMESPACE_ERR

                was thrown because of an attribute in my jsf page "xml:space=preserve" that was set for and tag.

                so, i'm now able to navigate on my pages, usign this abstraction.

                But I still have some issue, but is related to javascript: some commandButton are set to disabled (<html:commandButton disabled="true" .../>)
                When I fill my JSF form with "hands", this button gets enabled.
                But using jsfUnit, the button is not.
                I think I wont test submitting forms...

                Thanks anyway for your help and your time.
                L.

                • 5. Re: WebResponse not up to date when using client.click
                  laurentn

                  Just a note to let you know that the error
                  throws javax.xml.transform.TransformerException: org.w3c.dom.DOMException: NAMESPACE_ERR

                  was thrown because of an attribute in my jsf page "xml:space=preserve" that was set for script and link tag.

                  so, i'm now able to navigate on my pages, usign this abstraction.

                  But I still have some issue, but is related to javascript: some commandButton are set to disabled (html:commandButton disabled="true" .../)
                  When I fill my JSF form with "hands", this button gets enabled.
                  But using jsfUnit, the button is not.
                  I think I wont test submitting forms...

                  Thanks anyway for your help and your time.
                  L.

                  • 6. Re: WebResponse not up to date when using client.click
                    ssilvert

                    JSFUnit doesn't execute or test client-side javascript. But I don't think you will need to enable the button in order to submit the form.

                    If you want to enable the button in your code you can still do it. Just call JSFClientSession.getUpdatedDOM() and manipulate the DOM. In other words, do in java what the client-side javascript does. There is a utility class in JSFUnit called org.jboss.jsfunit.facade.DOMUtil that has some useful routines to help you.

                    Stan