<?xml version="1.0"?>

<!--
 * ========================================================================
 * 
 * Copyright 2001-2004 The Apache Software Foundation.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * 
 *   http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 * 
 * ========================================================================
-->

<document id="howto_jsp">

  <properties>
    <title>Testing JSP with Cactus</title>
  </properties>

  <body>

    <section title="JSP Testing in Cactus">

      <p>
        This tutorial explains how Cactus can be used to test JSP.        
      </p>
	  <p>
	  	There are different kibds of tests that you can implement with
	  	Cactus for testing JSP:
	  </p>
	  <ul>
	  	<li>
          <jump anchor="jsp_type1">type 1</jump>:
          You may simply want to verify the result of the JSP processing,
	  	  i.e. the HTML, XML or other format it returns.
	  	</li>
	  	<li>
          <jump anchor="jsp_type2">type 2</jump>:
          You may want to unit test your JSP taglibs.
	    </li>
	    <li>
          <jump anchor="jsp_type2">type 3</jump>:
	      You may want to test your JSP in isolation by being able to 
	      execute it without the java logic being present. This is often 
	      the case when the team is split into 2: one group for page 
	      development and another group for the java logic.
	    </li>
	  </ul>
	      
    </section>

    <anchor id="jsp_type1"/>
    <section title="Type 1: verifying JSP result">

      <p>
      	This is easily done by implementing a
      	<code>endXXX(WebResponse)</code> method as described in the
      	<jump href="site:howto_testcase" anchor="endxxx">TestCase tutorial</jump>.
      </p>
      <p>
      	Your test case class will also need to extend 
      	<code>ServletTestCase</code> and forward the request to your JSP
      	page, as in the following example:
      </p>

<source><![CDATA[
public class MyTest extends ServletTestCase
{
    [...]
    
    public void testXXX()
    {
        RequestDispatcher rd = theConfig.getServletContext().
            getRequestDispatcher("/path/to/test.jsp");
        rd.forward(theRequest, theResponse);
    }
    
    public void endXXX(WebResponse)
    {
        // Assert result
        [...]
    }
    
    [...]
}        
]]></source>
      
    </section>

    <anchor id="jsp_type2"/>
    <section title="Type 2: testing JSP taglibs">

      <p>
      	This is easily done by creating a test case class that extends
      	<code>JspTestCase</code>. See the 
      	<link href="site:howto_testcase_jsp">Taglib TestCase 
        tutorial</link>.
      </p>
      
    </section>

    <anchor id="jsp_type3"/>
    <section title="Type 3: testing JSP in isolation">

      <p>
        This type of testing depends mostly on your architecture. The general
        idea is that you would normally have an MVC implementation with a
        controller (usually a Servlet) that inspect the HTTP request, 
        potentially gather some other data from the Session, ServletContext or
        some storage and based on this information decides to call some 
        business code logic, and then forward the call to a given JSP page.
      </p>
      <p>
      	Thus, one solution to unit test your JSP in isolation is to succeed
      	in either bypassing the controller altogether or in telling it to use
      	some mock code logic that you would write for your tests.
      </p>
      
      <section title="Example1">

<source><![CDATA[
public class MyTestCase extends JspTestCase
{
[...]

    public void beginXXX(WebRequest webRequest)
    {
        webRequest.addParameter("cacheId", "1");
    }
	
    public void testXXX() throws Exception 
	{
        PageBean bean = new PageBean();
        bean.setName("kevin");
        request.setAttribute("pageBean", bean);
        pageContext.forward("/test.jsp");
	}
	
    public void endXXX(com.meterware.httpunit.WebResponse theResponse)
    {
        WebTable table = theResponse.getTables()[0];
        assertEquals("rows", 4, table.getRowCount());
        assertEquals("columns", 3, table.getColumnCount());
        assertEquals("links", 1, table.getTableCell(0, 2).getLinks().length);
       [...]
    }
}
]]></source>

        <p>
          In <code>testXXX()</code>, we populate a bean with values for our
          test and put this bean in the request.  Normally this would have
          been performed by the controller but we're bypassing it for the
          test. Then we call our JSP page, which looks like:
        </p>

<source><![CDATA[
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<HTML>
  <HEAD>
    <TITLE>test.jsp</TITLE>
  </HEAD>
  <BODY>
    <P><BR>
      <jsp:useBean id="pageBean" class="PageBean" scope="request"/>
    </P>
    <P>
      <%= pageBean.getName() %>
    </P><BR>
    
    Place test.jsp's content here
  </BODY>
</HTML>
]]></source>
        
      </section>
      
      <section title="Example2: Struts application">

        <p>
          See the 
          <link href="http://strutstestcase.sourceforge.net/">StrutsTestCase</link>
          project.
        </p>
        
      </section>

    </section>

  </body>
</document>
