package com.oreilly.jent.people.servlet;

/**
 * In general, you may use the code in this book in your programs and 
 * documentation. You do not need to contact us for permission unless 
 * you're reproducing a significant portion of the code. For example, 
 * writing a program that uses several chunks of code from this book does 
 * not require permission. Selling or distributing a CD-ROM of examples 
 * from O'Reilly books does require permission. Answering a question by 
 * citing this book and quoting example code does not require permission. 
 * Incorporating a significant amount of example code from this book into 
 * your product's documentation does require permission.
 * 
 * We appreciate, but do not require, attribution. An attribution usually 
 * includes the title, author, publisher, and ISBN. For example: 
 * 
 *   "Java Enterprise in a Nutshell, Third Edition, 
 *    by Jim Farley and William Crawford 
 *    with Prakash Malani, John G. Norman, and Justin Gehtland. 
 *    Copyright 2006 O'Reilly Media, Inc., 0-596-10142-2."
 *  
 *  If you feel your use of code examples falls outside fair use or the 
 *  permission given above, feel free to contact us at 
 *  permissions@oreilly.com.
 */

import java.io.IOException;

import javax.servlet.RequestDispatcher;
import javax.servlet.ServletException;

import junit.framework.Test;

import org.apache.cactus.ServletTestCase;
import org.apache.cactus.WebRequest;
import org.apache.cactus.WebResponse;

import com.oreilly.jent.people.Person;
import com.oreilly.jent.people.PersonDAO;

public class TestPeopleFinderServlet extends ServletTestCase {
    /** Common servlet instance, which serves as our test fixture */
    private PeopleFinderServlet mPFServlet = null;
    
    /** Default constructor. */
    public TestPeopleFinderServlet() {
        super();
    }

    /** Constructor with a test name */
    public TestPeopleFinderServlet(String name) {
        super(name);
    }

    /** Constructor used to wrap another test with a Cactus test. */
    public TestPeopleFinderServlet(String name, Test t) {
        super(name, t);
    }
    
    /** Set up the test fixture.  In this case, create the servlet instace */
    protected void setUp() {
        // Create the servlet instance.  We also initialize the servlet
        // here, so that we know it's only done once.  If any tests
        // require an uninitialized servlet for some reason, then the
        // test will have to create its own servlet instance.
        mPFServlet = new PeopleFinderServlet();
        try {
            mPFServlet.init(this.config);
        }
        catch (ServletException se) {
            fail("Unexpected servlet exception while setting up test case: "
                 + se.getMessage());
        }
    }
    
    // ----------------------------------------------------------------------
    
    /** Invoked on the "client-side" (within the test runner) before
     *  running the validSearch test. */
    public void beginValidSearch(WebRequest request) {
        // Add a search parameter
        request.addParameter(PersonDAO.FIRST_NAME, "John");
    }
    
    /** Ensure that a valid response is generated from a valid search */
    public void testValidSearch() {
        // Simply invoke the servlet's doGet() method, using
        // the request constructed in the begin method
        invokeGet();
    }
    
    /** Invoked on the "client-side" (within the test runner) after the
     *  validSearch test completes and sends a response to 
     *  the test runner. */
    public void endValidSearch(WebResponse response) {
        // The servlet should return some response
        assertNotNull("No response provided by servlet",
                      response.getText());
        // Since this was a valid search, there should be no "Error"
        // text in the response HTML
        assertTrue("Response from servlet contains the \"Error:\" label: "
                   + response.getText(),
                   response.getText().indexOf("Error:") < 0);
        // A valid search result will contain a search results header.
        assertTrue("Response doesn't contain a \"Search Results\" header: "
                   + response.getText(),
                   response.getText().indexOf("Search Results") >= 0);
    }
    
    // ----------------------------------------------------------------------
    
    public void testNoSearchArguments() {
        // Invoke the doGet method on the servlet using the request
        // that was generated through the proxy.  This request should
        // include no search arguments, since we have not added any in
        // a begin method
        // Un-comment one of the lines below to either invoke the GET 
        // handler directly (invokeGet()), or with a dispatch
        // (invokeGetDispatch()).
        invokeGetDispatch();
        // invokeGet();
    }
    
    public void endNoSearchArguments(WebResponse response) {
        // Even with no search arguments, the servlet should return a response
        assertNotNull("No response returned from servlet",
                      response.getText());
        // The response should contain the key phrase "Invalid search",
        // indicating a bad search request.
        assertTrue("Response from servlet does not contain \"Invalid search\": "
                   + response.getText(),
                   response.getText().indexOf("Invalid search") >= 0);
    }
    
    // ----------------------------------------------------------------------
    
    /** Test the HTML conversion util on PeopleFinderServlet */
    public void testPeopleToHTML() {
        // Create a test person, and the equivalent HTML snippet to be
        // expected from the method
        String fname = "Andy";
        String lname = "Long";
        String eAddr = "andy.long@buffaloimports.org";
        Person samplePerson = new Person();
        samplePerson.setFirstName(fname);
        samplePerson.setLastName(lname);
        samplePerson.addEmailAddress(eAddr);
        
        StringBuffer sampleHTML = new StringBuffer();
        sampleHTML.append("<tr bgcolor=\"#EEEEEE\"><td>")
            .append(lname).append("</td><td>").append(fname)
            .append("</td><td>").append(eAddr).append("</td></tr>");
        
        // Now apply the method to our Person and validate the results
        String result = PeopleFinderServlet.personToHTML(samplePerson);
        assertEquals("HMTL generated from sample person is not as expected",
                     result, sampleHTML.toString());
    }
    
    // ----------------------------------------------------------------------
    
    /** Tear down the test fixture.  Invoke the servlet's destroy method,
     *  to ensure any servlet cleanup occurs. */
    protected void tearDown() {
        mPFServlet.destroy();
        mPFServlet = null;
    }
    
    // ----------------------------------------------------------------------
    
    // Utility methods used by the tests
     
    /** Invoke the GET method on the servlet in our fixture.  If any
     *  exceptions are generated, fail the test.*/
    private void invokeGet() {
        try {
            mPFServlet.doGet(this.request, this.response);
        }
        catch (IOException ioe) {
            fail("Unexpected IO exception: " + ioe.getMessage());
        }
        catch (ServletException se) {
            fail("Unexpected servlet exception: " + se.getMessage());
        }
    }
    
    private void invokeGetDispatch() {
        try {
            RequestDispatcher dispatcher = 
                config.getServletContext().getRequestDispatcher("/search-servlet");
            dispatcher.forward(request, response);
        }
        catch (IOException ioe) {
            fail("Unexpected IO exception: " + ioe.getMessage());
        }
        catch (ServletException se) {
            fail("Unexpected servlet exception: " + se.getMessage());
        }
    }
}
