Overview | Package | Class | Use | Tree | Deprecated | Index | Help
PREV CLASS NEXT CLASS | FRAMES NO FRAMES
SUMMARY: NESTED | FIELD | CONSTR | METHOD | DETAIL: FIELD | CONSTR | METHOD

## org.apache.cactus.extension.jsp
Class JspTagLifecycle

    java.lang.Object
      org.apache.cactus.extension.jsp.JspTagLifecycle

public final class JspTagLifecycle
extends java.lang.Object

Convenience class that supports the testing of JSP tag by managing the tag's lifecycle as required by the JSP specification.

This class is basically a stub implementation of the tag management facilities that an actual JSP container would provide. The implementation attempts to follow the specification as closely as possible, but the tag handling functionality of real JSP implementations may vary in some details.

Although this class works quite well when used in the test methods of a `JspTestCase`, it can also safely be used outside of the Cactus testing framework, for example when following a mock objects approach.

#### Testing Simple Tags

This is how you would use this class when testing the `<c:set>`-tag of the JSTL reference implementation:

>       SetTag tag = new SetTag();
>       JspTagLifecycle lifecycle = new JspTagLifecycle(pageContext, tag);
>       tag.setVar("name");
>       tag.setValue("value");
>       lifecycle.invoke();
>       assertEquals("value", pageContext.findAttribute("name"));

The order is important:

1. Instantiation of the tag under test
2. Instantiation of the lifecycle helper, passing in the page context and the tag instance
3. Set the tag's attributes
4. Start the tag's lifecycle by calling `JspTagLifecycle.invoke()`
5. Make assertions

#### Adding Expectations to the Lifecycle

`JspTagLifecycle` features a couple of methods that let you easily add expectations about the tag's lifecycle to the test. For example, the method `expectBodySkipped()` can be used to verify that tag's body is not evaluated under the conditions set up by the test:

     IfTag tag = new IfTag();
     JspTagLifecycle lifecycle = new JspTagLifecycle(pageContext, tag);
     tag.setTest("false");
     lifecycle.expectBodySkipped();
     lifecycle.invoke();

An example of a more sophisticated expectationion is the `expectScopedVariableExposed(String, Object[])` method, which can verify that a specific scoped variable gets exposed in the body of the tag, and that the exposed variable has a specific value in each iteration step:

     ForEachTag tag = new ForEachTag();
     JspTagLifecycle lifecycle = new JspTagLifecycle(pageContext, tag);
     tag.setVar("item");
     tag.setItems("One,Two,Three");
     lifecycle.expectBodyEvaluated(3);
     lifecycle.expectScopedVariableExposed(
         "item", new Object[] {"One", "Two", "Three"});
     lifecycle.invoke();

#### Custom Expectations

In some cases, using the expectations offered by `JspTagLifecycle` does not suffice. In such cases, you need to use custom expectations. You can add custom expectations by creating a concrete subclass of the `Interceptor` class, and adding it to the list of the tag lifecycles interceptors through `addInterceptor()`:

     ForEachTag tag = new ForEachTag();
     JspTagLifecycle lifecycle = new JspTagLifecycle(pageContext, tag);
     tag.setVarStatus("status");
     tag.setBegin("0");
     tag.setEnd("2");
     lifecycle.addInterceptor(new JspTagLifecycle.Interceptor() {
         public void evalBody(int theIteration, BodyContent theBody) {
             LoopTagStatus status = (LoopTagStatus)
                 pageContext.findAttribute("status");
             assertNotNull(status);
             if (theIteration == 0) {
                 assertTrue(status.isFirst());
                 assertFalse(status.isLast());
             }
             else if (theIteration == 1) {
                 assertFalse(status.isFirst());
                 assertFalse(status.isLast());
             }
             else if (theIteration == 2) {
                 assertFalse(status.isFirst());
                 assertTrue(status.isLast());
             }
         }
     });
     lifecycle.invoke();

#### Specifying Nested Content

`JspTagLifecycle` let's you add nested tempate text as well as nested tags to the tag under test. The most important use of this feature is testing of collaboration between tags, but it also allows you to easily check whether a tag correctly handles its body content.

The following example demonstrates how to add nested template text to the tag, and how to assert that the body was written to the HTTP response on the client side:

     public void testOutTagDefaultBody() throws JspException, IOException {
         OutTag tag = new OutTag();
         JspTagLifecycle lifecycle = new JspTagLifecycle(pageContext, tag);
         tag.setValue(null);
         lifecycle.addNestedText("Default");
         lifecycle.expectBodyEvaluated();
         lifecycle.invoke();
     }
     public void endOutTagDefaultBody(WebResponse theResponse) {
         String output = theResponse.getText();
         assertEquals("Default", output);
     }

In sophisticated tag libraries, there will be many cases where tags need to collaborate with each other in some way. This is usually done by nesting such tags within eachother. `JspTagLifecycle` supports such scenarios by allowing you to add nested tags to an existing tag lifecycle. The nested tags can than be decorated with expectations themselves, as you can see in the following example:

     ChooseTag chooseTag = new ChooseTag();
     JspTagLifecycle chooseLifecycle =
         new JspTagLifecycle(pageContext, chooseTag);
     WhenTag whenTag = new WhenTag();
     JspTagLifecycle whenLifecycle =
         chooseLifecycle.addNestedTag(whenTag);
     whenTag.setTest("false");
     whenLifecycle.expectBodySkipped();
     OtherwiseTag otherwiseTag = new OtherwiseTag();
     JspTagLifecycle otherwiseLifecycle =
         chooseLifecycle.addNestedTag(otherwiseTag);
     otherwiseLifecycle.expectBodyEvaluated();
     chooseLifecycle.invoke();

The code above creates a constellation of tags equivalent to the following JSP fragment:

     <c:choose>
      <c:when test='false'>
       <%-- body content not significant for the test --%>
      </c:when>
      <c:otherwise>
       <%-- body content not significant for the test --%>
      </c:otherwise>
     </c:choose>

Since:
  Cactus 1.5
Version:
  $Id: JspTagLifecycle.java 238991 2004-05-22 11:34:50Z vmassol $
See Also:
  `JspTestCase`

Nested Class Summary
`static class` | `JspTagLifecycle.Interceptor` Abstract class for intercepting the tag lifecycle.

Field Summary
`protected javax.servlet.jsp.PageContext` | `pageContext` The JSP page context.

Constructor Summary
`JspTagLifecycle(javax.servlet.jsp.PageContext thePageContext, javax.servlet.jsp.tagext.Tag theTag)` Constructor.

Method Summary
`void` | `addInterceptor(JspTagLifecycle.Interceptor theInterceptor)` Adds an interceptor to the interceptor chain.
`JspTagLifecycle` | `addNestedTag(javax.servlet.jsp.tagext.Tag theNestedTag)` Adds a nested tag.
`void` | `addNestedText(java.lang.String theNestedText)` Adds template text to nest inside the tag.
`void` | `expectBodyEvaluated()` Adds the expectation that the tag body must be evaluated once in the course of the tags lifecycle.
`void` | `expectBodyEvaluated(int theNumIterations)` Adds the expectation that the tag body must be evaluated a specific number of times in the course of the tags lifecycle.
`void` | `expectBodySkipped()` Adds the expectation that the tag body must be skipped.
`void` | `expectScopedVariableExposed(java.lang.String theName, java.lang.Object[] theExpectedValues)` Adds a special expectation that verifies that a specific scoped variable is exposed in the body of the tag.
`void` | `expectScopedVariableExposed(java.lang.String theName, java.lang.Object[] theExpectedValues, int theScope)` Adds a special expectation that verifies that a specific scoped variable is exposed in the body of the tag.
`void` | `invoke()` Invokes the tag with the provided interceptor.

Methods inherited from class java.lang.Object
`clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait`

Field Detail

### pageContext

    protected javax.servlet.jsp.PageContext pageContext

  The JSP page context.

Constructor Detail

### JspTagLifecycle

    public JspTagLifecycle(javax.servlet.jsp.PageContext thePageContext,
                           javax.servlet.jsp.tagext.Tag theTag)

  Constructor.

Parameters:
  `thePageContext` - The JSP page context
  `theTag` - The JSP tag

Method Detail

### addInterceptor

    public void addInterceptor(JspTagLifecycle.Interceptor theInterceptor)

  Adds an interceptor to the interceptor chain.

  Parameters:
    `theInterceptor` - The interceptor to add

### addNestedTag

    public JspTagLifecycle addNestedTag(javax.servlet.jsp.tagext.Tag theNestedTag)

  Adds a nested tag. The tag will be invoked when the body content of the enclosing tag is evaluated.

  Parameters:
    `theNestedTag` - The tag to be nested
  Returns:
    The lifecycle wrapper for the nested tag, can be used to add expectations for the nested tag

### addNestedText

    public void addNestedText(java.lang.String theNestedText)

  Adds template text to nest inside the tag. The text will be printed to the body content when it is evaluated.

  Parameters:
    `theNestedText` - The string containing the template text

### expectBodyEvaluated

    public void expectBodyEvaluated()

  Adds the expectation that the tag body must be evaluated once in the course of the tags lifecycle.

### expectBodyEvaluated

    public void expectBodyEvaluated(int theNumIterations)

  Adds the expectation that the tag body must be evaluated a specific number of times in the course of the tags lifecycle.

  Parameters:
    `theNumIterations` - The number of times the body is expected to get evaluated

### expectBodySkipped

    public void expectBodySkipped()

  Adds the expectation that the tag body must be skipped. Essentially, this expectation verifies that the tag returns `SKIP_BODY` from `doStartTag()`.

### expectScopedVariableExposed

    public void expectScopedVariableExposed(java.lang.String theName,
                                            java.lang.Object[] theExpectedValues)

  Adds a special expectation that verifies that a specific scoped variable is exposed in the body of the tag.

  Parameters:
    `theName` - The name of the variable
    `theExpectedValues` - An ordered list containing the expected values values of the scoped variable, one for each expected iteration step

### expectScopedVariableExposed

    public void expectScopedVariableExposed(java.lang.String theName,
                                            java.lang.Object[] theExpectedValues,
                                            int theScope)

  Adds a special expectation that verifies that a specific scoped variable is exposed in the body of the tag.

  Parameters:
    `theName` - The name of the variable
    `theExpectedValues` - An ordered list containing the expected values values of the scoped variable, one for each expected iteration step
    `theScope` - The scope under which the variable is stored

### invoke

    public void invoke()
                throws javax.servlet.jsp.JspException,
                       java.io.IOException

  Invokes the tag with the provided interceptor. The tag should have been populated with its properties before calling this method. The tag is not released after the tag's lifecycle is over.

  Throws:
    `javax.servlet.jsp.JspException` - If the tag throws an exception
    `java.io.IOException` - If an error occurs when reading or writing the body content

Overview | Package | Class | Use | Tree | Deprecated | Index | Help
PREV CLASS NEXT CLASS | FRAMES NO FRAMES
SUMMARY: NESTED | FIELD | CONSTR | METHOD | DETAIL: FIELD | CONSTR | METHOD

Copyright © 2000-2004 Apache Software Foundation. All Rights Reserved.