[Webtest] submitform and posturl steps

Janno Kusman webtest@lists.canoo.com
Tue, 03 Feb 2004 11:24:37 +0200


This is a multi-part message in MIME format.
--------------050309060201080007080109
Content-Type: text/plain; charset=ISO-8859-1; format=flowed
Content-Transfer-Encoding: 7bit

Hi,

Here are my two custom steps that I have written to overcome javascript 
related issues, when submiting forms. For building see my instruction 
for exportproperty custom task (use mailing-list search). Add following 
two lines two webtestTaskdefs.properties:

submitform=com.canoo.webtest.extension.SubmitForm
posturl=com.canoo.webtest.extension.MakePost

submitform works as clickbutton task and supports formlocator, but 
submits form directly. Useful for example, if form is submited by long 
javascript functions, that doesn't work in httpUnit.



posturl was written to make my own custom POST requests. It's also 
similar to clickbutton, as you can set fields you want to post with 
setinputfield step. Example:

...
<invokeurl url="first_page"/>
<setinputfield stepid="Set the input field"
   name="field1"
   value="My simple value" />

<posturl stepid="Submit the simple form"
   url="login" />

<verifytext id="verify that login was succesful" text="Welcome"/>
....

You must use invokeurl before calling setinputfield, or you will receive 
Error, but the page doesn't need to contain actually a form.


Janno

--------------050309060201080007080109
Content-Type: text/plain;
 name="SubmitForm.java"
Content-Transfer-Encoding: 7bit
Content-Disposition: inline;
 filename="SubmitForm.java"

package com.canoo.webtest.extension;

import com.canoo.webtest.self.Block;
import com.canoo.webtest.engine.Context;
import com.canoo.webtest.engine.StepFailedException;
import com.canoo.webtest.engine.StepExecutionException;
import com.canoo.webtest.steps.Step;
import com.canoo.webtest.steps.request.Target;
import com.canoo.webtest.steps.ParameterHolder;
import com.canoo.webtest.steps.locator.*;





import com.canoo.webtest.interfaces.IFormLocator;
import org.xml.sax.SAXException;
import com.canoo.webtest.steps.locator.FormNotFoundError;
import com.canoo.webtest.steps.locator.FormLocator;
import com.meterware.httpunit.*;


import java.util.HashMap;
import java.util.Map;
import java.util.Iterator;
import java.util.List;
import java.util.Arrays;

/**
 * Step to simply submit form
 * @see MyCustomStepTest
 */
public class SubmitForm extends Target
{

        
        
        IFormLocator fFormLocator = null;
        
        public SubmitForm()
        {
            super();
        }
        
        /**
	 * Gotcha: Use the implementation and *not* the interface for FormLocator
	 * or a "strange" ant introspection exception will occur ...
	 */
	public void addForm(FormLocator locator)
	{
		fFormLocator = locator;
	}




	/**
	 * Use the locator mechanism to get to the required request by using the configured
	 * locators (if any). Configure the generated request with parameters.
	 *
	 * @throws com.canoo.webtest.engine.StepFailedException if the locator has a problem (e.g. no form found, multiple
	 * formss found, ...) or if a problem with parameters exists.
	 */
	public void doExecute(Context context) throws Exception
	{
            verifyParameters();
            super.doExecute(context);

            WebForm form = null;
            try
            {
                IFormLocator locator = getFormLocator();
                form = locator.locateForm(context);
                setParameters(context, form);
                gotoTarget(context, form);
            }
            catch(SAXException se)
            {
                se.printStackTrace();
            }
            catch (LocatorError error)
            {
                throw new StepFailedException(error.getMessage(), this);
            }
	}
        
        protected WebResponse gotoTarget(final Context context, final WebForm form) throws Exception
	{
		return protectedGoto(context, "submit form", new Block(){
			public void call() throws Exception
			{
				prepareConversation(context);

				try
				{
                                        form.submit();
                                        setIntermediateResponse(context.getWebConversation().getCurrentPage());
				}
				catch (SAXException e)
				{
					e.printStackTrace();
				}
			}
		});
	}

	

	/**
	 * good style to verify mandatory parameters before execution
	 * @throws StepExecutionException if a mandatory attribute is not set
	 */
	protected void verifyParameters()
	{
	}

	/**
	 * override to add actual attribute values to the reporting
	 */
	public Map getParameterDictionary()
	{
		return super.getParameterDictionary();
	}

	/**
	 * Hook for property expansion in our parameters
	 */
	public void expandProperties()
	{
		super.expandProperties();
	}
        
        protected IFormLocator getFormLocator()
        {
            if(fFormLocator == null)
            {
                return new FormLocator()
                {
                    public WebForm locateForm(Context context) throws FormNotFoundError
                    {
                        try
                        {
                            WebForm forms[] = context.getLastResponse().getForms();
                            if(forms.length == 1)
                            {
                                return forms[0];
                            }
                            else
                            {
                                throw new FormNotFoundError("UnSpecified");
                            }
                        }
                        catch(SAXException sa)
                        {
                            sa.printStackTrace();
                            throw new FormNotFoundError("UnSpecified");
                        }
                    }
                };
            }
            else
            {
                return fFormLocator;
            }
        }
        
        	/**
	 * Add all parameters collected in the nextParameters HashMap to the request and remove
	 * all parameters from the request that are listed in the resetNextParameters list.
	 * Set also the click position if coordinates are configured.
	 *
	 * @param context The current test context
	 * @param form The form to add/remove parameters from
	 *
	 * @throws com.canoo.webtest.engine.StepFailedException if a parameter to remove is not present in the request,
	 * if a parameter is not available in the form
	 * or if click positions are configured and target button is no image button
	 */
	protected void setParameters(Context context, WebForm form) throws StepFailedException
	{
		for (Iterator i = context.getNextParameters().entrySet().iterator(); i.hasNext();)
		{
			ParameterHolder parameter = (ParameterHolder) ((Map.Entry) i.next()).getValue();
			try
			{
				addParameter(form, parameter);
			}
			catch (IllegalRequestParameterException irpe)
			{
				handleIllegalRequestParameterException(parameter.getName(), form, irpe.getMessage());
			}
		}

		for (Iterator i = context.getNextResetParameters().iterator(); i.hasNext();)
		{

			String resetParameterName = (String) i.next();
			if (form.getParameterValues(resetParameterName).length > 0)
			{
				form.removeParameter(resetParameterName);
			}
			else
			{
				throw new StepFailedException("Could not remove parameter from request: " + resetParameterName, this);
			}
		}
	}

	protected void handleIllegalRequestParameterException(String parameterName, WebForm form, String message)
	{
		String formInfo = "<unknown>";
		if (form != null)
		{
			formInfo = "[";
			try
			{
				formInfo += form.getName() + ", " ;
				formInfo += form.getMethod() + ", ";
				formInfo += form.getAction() + ", ";
				formInfo += form.getFragmentIdentifier() + ", ";
				formInfo += form.getID() + ", ";
				formInfo += form.getTarget() + ", ";
				formInfo += form.getTitle() + ", ";
				formInfo += form.getRequest().toString();
			}
			catch (IllegalRequestParameterException e)
			{}
			formInfo += "]";
		}
		throw new StepFailedException(
		    "Illegal parameter " + parameterName +
		    " in form " + formInfo +
		    " with message <" + message +
		    "> ", this);
	}

	/**
	 * Add a new multivalue parameter to the request. Add the new values to the existing ones if the parameter
	 * exists already in the request.
	 *
	 * @param form The WebForm to which the parameter shall be added
	 * @param parameterHolder The parameterHolder representing the parameter
	 */
	private void addParameter(WebForm form, ParameterHolder parameterHolder)
	{
		List parameterValues = parameterHolder.getValueList();
		if (parameterHolder.isPreserveExistingValue())
		{
			String[] existingParameters = form.getParameterValues(parameterHolder.getName());
			parameterValues.addAll(Arrays.asList(existingParameters));
		}
		form.setParameter(parameterHolder.getName(),
		    (String[]) parameterValues.toArray(new String[parameterValues.size()]));
	}
        



}

--------------050309060201080007080109
Content-Type: text/plain;
 name="MakePost.java"
Content-Transfer-Encoding: 8bit
Content-Disposition: inline;
 filename="MakePost.java"

/*
 * MakePost.java
 *
 * Created on kolmapäev, 28. Jaanuar 2004. a, 12:17
 */

package com.canoo.webtest.extension;


import com.meterware.httpunit.*;

import com.canoo.webtest.engine.Context;
import com.canoo.webtest.engine.StepExecutionException;
import com.canoo.webtest.steps.Step;
import com.canoo.webtest.self.Block;
import com.canoo.webtest.engine.Context;
import com.canoo.webtest.engine.StepFailedException;
import com.canoo.webtest.engine.StepExecutionException;
import com.canoo.webtest.steps.Step;
import com.canoo.webtest.steps.request.Target;
import com.canoo.webtest.steps.ParameterHolder;

import org.xml.sax.SAXException;

import java.util.HashMap;
import java.util.Map;
import java.util.Iterator;
import java.util.List;
import java.util.Arrays;
/**
 * Class for making custom http POST requests
 * @author  janno
 */
public class MakePost extends Target
{
        private String fRelativeUrl;
        
        public MakePost()
        {
                super();
        }
        
        public MakePost(String stepId, String relativeUrl)
        {
                super(stepId);
                fRelativeUrl = relativeUrl;
        }
    
        /**
	 * Use the locator mechanism to get to the required request by using the configured
	 * locators (if any). Configure the generated request with parameters.
	 *
	 * @throws com.canoo.webtest.engine.StepFailedException if the locator has a problem (e.g. no form found, multiple
	 * formss found, ...) or if a problem with parameters exists.
	 */
	public void doExecute(Context context) throws Exception
	{
            verifyParameters();
            super.doExecute(context);

            gotoTarget(context);
	}
        
        protected WebResponse gotoTarget(final Context context) throws Exception
	{
		return protectedGoto(context, "make post request", new Block(){
			public void call() throws Exception
			{
				prepareConversation(context);

				try
				{
                                        String targetUrl = context.getTestSpecification().getConfig().getUrlForPage(fRelativeUrl);
                                        WebRequest req = new PostMethodWebRequest(targetUrl);
                                        setRequestParameters(context, req);
                                        setIntermediateResponse(context.getWebConversation().getResponse(req));
				}
				catch (SAXException e)
				{
					e.printStackTrace();
				}
			}
		});
	}
        
        protected void setRequestParameters(final Context context, WebRequest request)
        {
                for (Iterator i = context.getNextParameters().entrySet().iterator(); i.hasNext();)
		{
			ParameterHolder parameter = (ParameterHolder) ((Map.Entry) i.next()).getValue();
                        List parameterValues = parameter.getValueList();
                        request.setParameter(parameter.getName(), 
                            (String[]) parameterValues.toArray(new String[parameterValues.size()]));
		}

        }

        protected void verifyParameters()
	{
                if (fRelativeUrl == null)
                {
                        throw new StepExecutionException("Required parameter url not set!");
                }
	}

	public void expandProperties()
	{
		super.expandProperties();
		fRelativeUrl = expandDynamicProperties(fRelativeUrl);
	}

	public void setUrl(String newRelativeUrl)
	{
		fRelativeUrl = newRelativeUrl;
	}

	public Map getParameterDictionary()
	{
		Map map = super.getParameterDictionary();
		map.put("url", fRelativeUrl);
		return map;
	}    
}

--------------050309060201080007080109--