All Downloads are FREE. Search and download functionalities are using the official Maven repository.

net.sourceforge.jwebunit.htmlunit.HtmlUnitTestingEngineImpl Maven / Gradle / Ivy

/******************************************************************************
 * JWebUnit project (http://jwebunit.sourceforge.net)                         *
 * Distributed open-source, see full license under LICENCE.txt                *
 ******************************************************************************/
package net.sourceforge.jwebunit.htmlunit;

import com.gargoylesoftware.htmlunit.AlertHandler;
import com.gargoylesoftware.htmlunit.BrowserVersion;
import com.gargoylesoftware.htmlunit.ConfirmHandler;
import com.gargoylesoftware.htmlunit.DefaultCredentialsProvider;
import com.gargoylesoftware.htmlunit.ElementNotFoundException;
import com.gargoylesoftware.htmlunit.FailingHttpStatusCodeException;
import com.gargoylesoftware.htmlunit.ImmediateRefreshHandler;
import com.gargoylesoftware.htmlunit.JavaScriptPage;
import com.gargoylesoftware.htmlunit.Page;
import com.gargoylesoftware.htmlunit.PromptHandler;
import com.gargoylesoftware.htmlunit.TextPage;
import com.gargoylesoftware.htmlunit.UnexpectedPage;
import com.gargoylesoftware.htmlunit.WebClient;
import com.gargoylesoftware.htmlunit.WebResponse;
import com.gargoylesoftware.htmlunit.WebWindow;
import com.gargoylesoftware.htmlunit.WebWindowEvent;
import com.gargoylesoftware.htmlunit.WebWindowListener;
import com.gargoylesoftware.htmlunit.WebWindowNotFoundException;
import com.gargoylesoftware.htmlunit.html.ClickableElement;
import com.gargoylesoftware.htmlunit.html.DomNode;
import com.gargoylesoftware.htmlunit.html.FrameWindow;
import com.gargoylesoftware.htmlunit.html.HtmlAnchor;
import com.gargoylesoftware.htmlunit.html.HtmlButton;
import com.gargoylesoftware.htmlunit.html.HtmlButtonInput;
import com.gargoylesoftware.htmlunit.html.HtmlCheckBoxInput;
import com.gargoylesoftware.htmlunit.html.HtmlElement;
import com.gargoylesoftware.htmlunit.html.HtmlFileInput;
import com.gargoylesoftware.htmlunit.html.HtmlForm;
import com.gargoylesoftware.htmlunit.html.HtmlHiddenInput;
import com.gargoylesoftware.htmlunit.html.HtmlImageInput;
import com.gargoylesoftware.htmlunit.html.HtmlInput;
import com.gargoylesoftware.htmlunit.html.HtmlOption;
import com.gargoylesoftware.htmlunit.html.HtmlPage;
import com.gargoylesoftware.htmlunit.html.HtmlPasswordInput;
import com.gargoylesoftware.htmlunit.html.HtmlRadioButtonInput;
import com.gargoylesoftware.htmlunit.html.HtmlResetInput;
import com.gargoylesoftware.htmlunit.html.HtmlSelect;
import com.gargoylesoftware.htmlunit.html.HtmlSubmitInput;
import com.gargoylesoftware.htmlunit.html.HtmlTable;
import com.gargoylesoftware.htmlunit.html.HtmlTableCell;
import com.gargoylesoftware.htmlunit.html.HtmlTableRow;
import com.gargoylesoftware.htmlunit.html.HtmlTextInput;
import com.gargoylesoftware.htmlunit.html.HtmlTableRow.CellIterator;
import com.gargoylesoftware.htmlunit.html.HtmlTextArea;
import com.gargoylesoftware.htmlunit.xml.XmlPage;

import java.io.IOException;
import java.io.InputStream;
import java.net.InetAddress;
import java.net.URL;
import java.net.UnknownHostException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Calendar;
import java.util.Date;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Set;

import net.sourceforge.jwebunit.api.ITestingEngine;
import net.sourceforge.jwebunit.exception.ExpectedJavascriptAlertException;
import net.sourceforge.jwebunit.exception.ExpectedJavascriptConfirmException;
import net.sourceforge.jwebunit.exception.ExpectedJavascriptPromptException;
import net.sourceforge.jwebunit.exception.TestingEngineResponseException;
import net.sourceforge.jwebunit.exception.UnableToSetFormException;
import net.sourceforge.jwebunit.exception.UnexpectedJavascriptAlertException;
import net.sourceforge.jwebunit.exception.UnexpectedJavascriptConfirmException;
import net.sourceforge.jwebunit.exception.UnexpectedJavascriptPromptException;
import net.sourceforge.jwebunit.html.Cell;
import net.sourceforge.jwebunit.html.Row;
import net.sourceforge.jwebunit.html.Table;
import net.sourceforge.jwebunit.javascript.JavascriptAlert;
import net.sourceforge.jwebunit.javascript.JavascriptConfirm;
import net.sourceforge.jwebunit.javascript.JavascriptPrompt;
import net.sourceforge.jwebunit.util.TestContext;

import org.apache.commons.httpclient.Cookie;
import org.apache.commons.httpclient.NameValuePair;
import org.apache.regexp.RE;
import org.apache.regexp.RESyntaxException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * Acts as the wrapper for HtmlUnit access. A testing engine is initialized with a given URL, and maintains conversational state
 * as the dialog progresses through link navigation, form submission, etc.
 * 
 * @author Julien Henry
 * 
 */
public class HtmlUnitTestingEngineImpl implements ITestingEngine {
    /**
     * Logger for this class.
     */
    private final Logger logger = LoggerFactory.getLogger(HtmlUnitTestingEngineImpl.class);

    /**
     * Encapsulate browser abilities.
     */
    private WebClient wc;

    /**
     * The currently selected window.
     */
    private WebWindow win;

    /**
     * A ref to the test context.
     */
    private TestContext testContext;

    /**
     * The currently selected form.
     */
    private HtmlForm form;

    /**
     * Is Javascript enabled.
     */
    private boolean jsEnabled = true;

    /**
     * Javascript alerts.
     */
    private LinkedList expectedJavascriptAlerts = new LinkedList();

    /**
     * Javascript confirms.
     */
    private LinkedList expectedJavascriptConfirms = new LinkedList();

    /**
     * Javascript prompts.
     */
    private LinkedList expectedJavascriptPrompts = new LinkedList();

    // Implementation of IJWebUnitDialog

    /**
     * Begin a dialog with an initial URL and test client context.
     * 
     * @param initialURL absolute url at which to begin dialog.
     * @param context contains context information for the test client.
     * @throws TestingEngineResponseException
     */
    public void beginAt(URL initialURL, TestContext context)
            throws TestingEngineResponseException {
        this.setTestContext(context);
        initWebClient();
        try {
            wc.getPage(initialURL);
            win = wc.getCurrentWindow();
            form = null;
        } catch (FailingHttpStatusCodeException aException) {
            throw new TestingEngineResponseException(
                    aException.getStatusCode(), aException);

        } catch (IOException aException) {
            throw new RuntimeException(aException);
        }
    }

    public void closeBrowser() throws ExpectedJavascriptAlertException,
            ExpectedJavascriptConfirmException,
            ExpectedJavascriptPromptException {
        wc = null;
        if (this.expectedJavascriptAlerts.size() > 0) {
            throw new ExpectedJavascriptAlertException(
                    ((JavascriptAlert) (expectedJavascriptAlerts.get(0)))
                            .getMessage());
        }
        if (this.expectedJavascriptConfirms.size() > 0) {
            throw new ExpectedJavascriptConfirmException(
                    ((JavascriptConfirm) (expectedJavascriptConfirms.get(0)))
                            .getMessage());
        }
        if (this.expectedJavascriptPrompts.size() > 0) {
            throw new ExpectedJavascriptPromptException(
                    ((JavascriptPrompt) (expectedJavascriptPrompts.get(0)))
                            .getMessage());
        }

    }

    public void gotoPage(URL initialURL) throws TestingEngineResponseException {
        try {
            wc.getPage(initialURL);
            win = wc.getCurrentWindow();
            form = null;
        } catch (FailingHttpStatusCodeException aException) {
            throw new TestingEngineResponseException(aException.getStatusCode());
        } catch (IOException aException) {
            throw new RuntimeException(aException);
        }
    }

    /**
     * @see net.sourceforge.jwebunit.api.IJWebUnitDialog#setScriptingEnabled(boolean)
     */
    public void setScriptingEnabled(boolean value) {
        // This variable is used to set Javascript before wc is instancied
        jsEnabled = value;
        if (wc != null) {
            wc.setJavaScriptEnabled(value);
        }
    }

    public List getCookies() {
        List result = new LinkedList();
        Set cookies = wc.getCookieManager().getCookies();
        for (Cookie cookie : cookies) {
            javax.servlet.http.Cookie c = new javax.servlet.http.Cookie(
                    cookie.getName(), cookie.getValue());
            c.setComment(cookie.getComment());
            c.setDomain(cookie.getDomain());
            Date expire = cookie.getExpiryDate();
            if (expire == null) {
                c.setMaxAge(-1);
            } else {
                Date now = Calendar.getInstance().getTime();
                // Convert milli-second to second
                Long second = new Long(
                        (expire.getTime() - now.getTime()) / 1000);
                c.setMaxAge(second.intValue());
            }
            c.setPath(cookie.getPath());
            c.setSecure(cookie.getSecure());
            c.setVersion(cookie.getVersion());
            result.add(c);
        }
        return result;
    }

    public boolean hasWindow(String windowName) {
        try {
            getWindow(windowName);
        } catch (WebWindowNotFoundException e) {
            return false;
        }
        return true;
    }

    public boolean hasWindowByTitle(String title) {
        return getWindowByTitle(title) != null;
    }

    /**
     * Make the window with the given name in the current conversation active.
     * 
     * @param windowName
     */
    public void gotoWindow(String windowName) {
        setMainWindow(getWindow(windowName));
    }

    public void gotoWindow(int windowID) {
        setMainWindow((WebWindow) wc.getWebWindows().get(windowID));
    }

    public int getWindowCount() {
        return wc.getWebWindows().size();
    }

    /**
     * Goto first window with the given title.
     * 
     * @param title
     */
    public void gotoWindowByTitle(String title) {
        WebWindow window = getWindowByTitle(title);
        if (window != null) {
            setMainWindow(window);
        }
    }

    public void closeWindow() {
        if (win != null) {
            wc.deregisterWebWindow(win);
            win = wc.getCurrentWindow();
            form = null;
        }

    }

    /**
     * {@inheritDoc}
     */
    public boolean hasFrame(String frameNameOrId) {
        return getFrame(frameNameOrId) != null;
    }

    /**
     * {@inheritDoc}
     */
    public void gotoFrame(String frameNameOrId) {
    	WebWindow frame = getFrame(frameNameOrId);
    	if (frame == null) {
    		throw new RuntimeException("No frame found in current page with name or id [" + frameNameOrId + "]");
    	}
        win = frame;
    }

    /**
     * {@inheritDoc}
     */
    public void setWorkingForm(int index) {
        setWorkingForm(getForm(index));
    }

    /**
     * {@inheritDoc}
     */
    public void setWorkingForm(String nameOrId, int index) {
        setWorkingForm(getForm(nameOrId, index));
    }

    /**
     * Return true if the current response contains a form.
     */
    public boolean hasForm() {
        return ((HtmlPage) win.getEnclosedPage()).getForms().size() > 0;
    }

    /**
     * Return true if the current response contains a specific form.
     * 
     * @param nameOrID name of id of the form to check for.
     */
    public boolean hasForm(String nameOrID) {
        return getForm(nameOrID) != null;
    }

    public boolean hasFormParameterNamed(String paramName) {
        if (hasFormSelectNamed(paramName))
            return true;
        return hasFormInputNamed(paramName);
    }

    /**
     * Return the current value of a text input element with name paramName.
     * 
     * @param paramName name of the input element. TODO: Find a way to handle multiple text input element with same
     *            name.
     */
    public String getTextFieldValue(String paramName) {
        List textFieldElements = new LinkedList();
        if (form != null) {
            textFieldElements.addAll(getForm().getHtmlElementsByAttribute(
                    "input", "type", "text"));
            textFieldElements.addAll(getForm().getHtmlElementsByAttribute(
                    "input", "type", "password"));
        } else {
            for (Iterator i = getCurrentPage().getForms().iterator(); i
                    .hasNext();) {
                HtmlForm f = (HtmlForm) i.next();
                textFieldElements.addAll(f.getHtmlElementsByAttribute("input",
                        "type", "text"));
                textFieldElements.addAll(f.getHtmlElementsByAttribute("input",
                        "type", "password"));
            }
        }
        Iterator it = textFieldElements.iterator();
        while (it.hasNext()) {
            HtmlInput input = (HtmlInput) it.next();
            if (paramName.equals(input.getNameAttribute())) {
                if (form == null) {
                    form = input.getEnclosingFormOrDie();
                }
                return input.getValueAttribute();
            }
        }
        // If no text field with the name paramName then try with textareas.
        textFieldElements.clear();
        if (form != null) {
            textFieldElements.addAll(getForm().getTextAreasByName(paramName));
        } else {
            for (Iterator i = getCurrentPage().getForms().iterator(); i
                    .hasNext();) {
                HtmlForm f = (HtmlForm) i.next();
                textFieldElements.addAll(f.getTextAreasByName(paramName));
            }
        }
        it = textFieldElements.iterator();
        while (it.hasNext()) {
            HtmlTextArea textInput = (HtmlTextArea) it.next();
            if (paramName.equals(textInput.getNameAttribute())) {
                if (form == null) {
                    form = textInput.getEnclosingFormOrDie();
                }
                return textInput.getText();
            }
        }
        throw new RuntimeException(
                "getTextFieldParameterValue failed, text field with name ["
                        + paramName + "] does not exist.");
    }

    /**
     * Return the current value of a hidden input element with name paramName.
     * 
     * @param paramName name of the input element. TODO: Find a way to handle multiple hidden input element with same
     *            name.
     */
    public String getHiddenFieldValue(String paramName) {
        List hiddenFieldElements = new LinkedList();
        if (form != null) {
            hiddenFieldElements.addAll(getForm().getHtmlElementsByAttribute(
                    "input", "type", "hidden"));
        } else {
            for (Iterator i = getCurrentPage().getForms().iterator(); i
                    .hasNext();) {
                HtmlForm f = (HtmlForm) i.next();
                hiddenFieldElements.addAll(f.getHtmlElementsByAttribute(
                        "input", "type", "hidden"));
            }
        }
        Iterator it = hiddenFieldElements.iterator();
        while (it.hasNext()) {
            HtmlHiddenInput hiddenInput = (HtmlHiddenInput) it.next();
            if (paramName.equals(hiddenInput.getNameAttribute())) {
                if (form == null) {
                    form = hiddenInput.getEnclosingFormOrDie();
                }
                return hiddenInput.getValueAttribute();
            }
        }
        throw new RuntimeException(
                "getHiddenFieldParameterValue failed, hidden field with name ["
                        + paramName + "] does not exist.");
    }

    /**
     * Set a form text, password input element or textarea to the provided value.
     * 
     * @param fieldName name of the input element or textarea
     * @param text parameter value to submit for the element.
     */
    public void setTextField(String fieldName, String text) {
        List textFieldElements = new LinkedList();
        if (form != null) {
            textFieldElements.addAll(getForm().getHtmlElementsByAttribute(
                    "input", "name", fieldName));
            textFieldElements.addAll(getForm().getTextAreasByName(fieldName));
        } else {
            for (Iterator i = getCurrentPage().getForms().iterator(); i
                    .hasNext();) {
                HtmlForm f = (HtmlForm) i.next();
                textFieldElements.addAll(f.getHtmlElementsByAttribute("input",
                        "name", fieldName));
                textFieldElements.addAll(f.getTextAreasByName(fieldName));
            }
        }
        for (Iterator i = textFieldElements.iterator(); i.hasNext();) {
            HtmlElement e = (HtmlElement) i.next();
            if (e instanceof HtmlTextInput) {
                ((HtmlTextInput) e).setValueAttribute(text);
                if (form == null) {
                    form = e.getEnclosingFormOrDie();
                }
                return;
            }
            if (e instanceof HtmlPasswordInput) {
                ((HtmlPasswordInput) e).setValueAttribute(text);
                if (form == null) {
                    form = e.getEnclosingFormOrDie();
                }
                return;
            }
            if (e instanceof HtmlFileInput) {
                ((HtmlFileInput) e).setValueAttribute(text);
                if (form == null) {
                    form = e.getEnclosingFormOrDie();
                }
                return;
            }
            if (e instanceof HtmlTextArea) {
                ((HtmlTextArea) e).setText(text);
                if (form == null) {
                    form = e.getEnclosingFormOrDie();
                }
                return;
            }
        }
        throw new RuntimeException("No text field with name [" + fieldName
                + "] was found.");
    }
    
    /**
     * Set a form hidden element to the provided value.
     * 
     * @param fieldName name of the hidden input element
     * @param paramValue parameter value to submit for the element.
     */
    public void setHiddenField(String fieldName, String text) {
        List hiddenFieldElements = new LinkedList();
        if (form != null) {
            hiddenFieldElements.addAll(getForm().getInputsByName(fieldName));
        } else {
            for (Iterator i = getCurrentPage().getForms().iterator(); i
                    .hasNext();) {
                HtmlForm f = (HtmlForm) i.next();
                hiddenFieldElements.addAll(f.getInputsByName(fieldName));
            }
        }
        for (Iterator i = hiddenFieldElements.iterator(); i.hasNext();) {
            HtmlElement e = (HtmlElement) i.next();
            if (e instanceof HtmlHiddenInput) {
                ((HtmlHiddenInput) e).setValueAttribute(text);
                if (form == null) {
                    form = e.getEnclosingFormOrDie();
                }
                return;
            }
        }
        throw new RuntimeException("No hidden field with name [" + fieldName
                + "] was found.");
    }

    /**
     * Return a string array of select box option values.
     * 
     * @param selectName name of the select box.
     */
    public String[] getSelectOptionValues(String selectName) {
        HtmlSelect sel = getForm().getSelectByName(selectName);
        ArrayList result = new ArrayList();
        for (HtmlOption opt : sel.getOptions()) {
            result.add(opt.getValueAttribute());
        }
        return result.toArray(new String[result.size()]);
    }

    /**
     * Return a string array of the Nth select box option values.
     * 
     * @param selectName name of the select box.
     * @param index the 0-based index when more than one
     * select with the same name is expected.
     */
    public String[] getSelectOptionValues(String selectName, int index) {
        List sels = getForm().getSelectsByName(selectName);
        if ( sels == null || sels.size() < index+1)
        	throw new RuntimeException("Did not find select with name [" + selectName 
        	                           + "] at index " + index);
        	
        HtmlSelect sel = sels.get(index);
        ArrayList result = new ArrayList();
        for (HtmlOption opt : sel.getOptions()) {
            result.add(opt.getValueAttribute());
        }
        return (String[]) result.toArray(new String[0]);
    }
    
    private String[] getSelectedOptions(HtmlSelect sel) {
        String[] result = new String[sel.getSelectedOptions().size()];
        int i = 0;
        for (HtmlOption opt : sel.getSelectedOptions())
            result[i++] = opt.getValueAttribute();
        return result;
    }

    
    public String[] getSelectedOptions(String selectName) {
        HtmlSelect sel = getForm().getSelectByName(selectName);
        return getSelectedOptions(sel);
    }

    public String[] getSelectedOptions(String selectName, int index) {
        List sels = getForm().getSelectsByName(selectName);
        if ( sels == null || sels.size() < index+1)
        	throw new RuntimeException("Did not find select with name [" + selectName 
        	                           + "] at index " + index);
        HtmlSelect sel = sels.get(index);
        return getSelectedOptions(sel);
    }

    
    private String getSelectOptionValueForLabel(HtmlSelect sel, String label) {
        for (HtmlOption opt : sel.getOptions()) {
            if (opt.asText().equals(label))
                return opt.getValueAttribute();
        }
        throw new RuntimeException("Unable to find option " + label + " for "
                + sel.getNameAttribute());
    }

    public String getSelectOptionValueForLabel(String selectName, String label) {
        HtmlSelect sel = getForm().getSelectByName(selectName);
        return getSelectOptionValueForLabel(sel, label);
    }
    
    public String getSelectOptionValueForLabel(String selectName, int index, String label) {
        List sels = getForm().getSelectsByName(selectName);
        if ( sels == null || sels.size() < index+1)
        	throw new RuntimeException("Did not find select with name [" + selectName 
        	                           + "] at index " + index);
        HtmlSelect sel = (HtmlSelect)sels.get(index);
        return getSelectOptionValueForLabel(sel, label);
    }

    private String getSelectOptionLabelForValue(HtmlSelect sel, String value) {
        for (HtmlOption opt : sel.getOptions()) {
            if (opt.getValueAttribute().equals(value))
                return opt.asText();
        }
        throw new RuntimeException("Unable to find option " + value + " for "
                + sel.getNameAttribute());
    }
    
    public String getSelectOptionLabelForValue(String selectName, String value) {
        HtmlSelect sel = getForm().getSelectByName(selectName);
        return getSelectOptionLabelForValue(sel, value);
    }
    
    public String getSelectOptionLabelForValue(String selectName, int index, String value) {
        List sels = getForm().getSelectsByName(selectName);
        if ( sels == null || sels.size() < index+1)
        	throw new RuntimeException("Did not find select with name [" + selectName 
        	                           + "] at index " + index);
        	
        HtmlSelect sel = (HtmlSelect)sels.get(index);
        return getSelectOptionLabelForValue(sel, value);
    }

    
    
    public URL getPageURL() {
        return win.getEnclosedPage().getWebResponse().getUrl();
    }
    
    public String getPageSource() {
        return win.getEnclosedPage().getWebResponse()
                .getContentAsString();
    }

    public String getPageTitle() {
        return getCurrentPageTitle();
    }

    public String getPageText() {
        Page page = win.getEnclosedPage();
        if (page instanceof HtmlPage)
            return ((HtmlPage) page).asText();
        if (page instanceof TextPage)
            return ((TextPage) page).getContent();
        if (page instanceof JavaScriptPage)
            return ((JavaScriptPage) page).getContent();
        if (page instanceof XmlPage)
            return ((XmlPage) page).getContent();
        if (page instanceof UnexpectedPage)
            return ((UnexpectedPage) page).getWebResponse()
                    .getContentAsString();
        throw new RuntimeException(
                "Unexpected error in getPageText(). This method need to be updated.");
    }

    public String getServerResponse() {
        StringBuffer result = new StringBuffer();
        WebResponse wr = wc.getCurrentWindow().getEnclosedPage()
                .getWebResponse();
        result.append(wr.getStatusCode()).append(" ").append(
                wr.getStatusMessage()).append("\n");
        result.append("Location: ").append(wr.getUrl()).append("\n");
        for (NameValuePair h : wr.getResponseHeaders()) {
            result.append(h.getName()).append(": ").append(h.getValue())
                    .append("\n");
        }
        result.append("\n");
        result.append(wr.getContentAsString());
        return result.toString();
    }

    public InputStream getInputStream() {
        try {
            return wc.getCurrentWindow().getEnclosedPage().getWebResponse()
                    .getContentAsStream();
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }

    public InputStream getInputStream(URL resourceUrl)
            throws TestingEngineResponseException {
        WebWindow imageWindow = null;
        try {
            // as far as I can tell, there is no such thing as an iframe/object kind of "window" in htmlunit, so I'm
            // opening a fake new window here
            imageWindow = wc.openWindow(resourceUrl, "for_stream");
            Page page = imageWindow.getEnclosedPage();
            return page.getWebResponse().getContentAsStream();
        } catch (FailingHttpStatusCodeException aException) {
            throw new TestingEngineResponseException(
                    aException.getStatusCode(), aException);

        } catch (IOException aException) {
            throw new RuntimeException(aException);
        } finally {
            if (imageWindow != null) {
                wc.deregisterWebWindow(imageWindow);
            }
        }
    }

    private void initWebClient() {
        
        BrowserVersion bv = new BrowserVersion(BrowserVersion.INTERNET_EXPLORER,
                "4.0", testContext.getUserAgent(), "1.2", 6);
        if (getTestContext().getProxyHost()!=null && getTestContext().getProxyPort()>0) {
            //Proxy
            wc = new WebClient(bv, getTestContext().getProxyHost(), getTestContext().getProxyPort());
        }
        else {
            wc = new WebClient(bv);
        }
        wc.setJavaScriptEnabled(jsEnabled);
        wc.setThrowExceptionOnScriptError(true);
        wc.setRedirectEnabled(true);
        wc.setRefreshHandler(new ImmediateRefreshHandler());
        DefaultCredentialsProvider creds = new DefaultCredentialsProvider();
        if (getTestContext().hasAuthorization()) {
            creds.addCredentials(getTestContext().getUser(), getTestContext()
                    .getPassword());
        }
        if (getTestContext().hasNTLMAuthorization()) {
            InetAddress netAddress;
            String address;
            try {
                netAddress = InetAddress.getLocalHost();
                address = netAddress.getHostName();
            } catch (UnknownHostException e) {
                address = "";
            }
            creds.addNTLMCredentials(getTestContext().getUser(),
                    getTestContext().getPassword(), "", -1, address,
                    getTestContext().getDomain());
        }
        if (getTestContext().hasProxyAuthorization()) {
            creds.addProxyCredentials(getTestContext().getProxyUser(),
                    getTestContext().getPassword(), getTestContext()
                            .getProxyHost(), getTestContext().getProxyPort());
        }
        wc.setCredentialsProvider(creds);
        wc.addWebWindowListener(new WebWindowListener() {
            public void webWindowClosed(WebWindowEvent event) {
                if (event.getOldPage().equals(win.getEnclosedPage())) {
                    win = wc.getCurrentWindow();
                    form = null;
                }
                String win = event.getWebWindow().getName();
                Page oldPage = event.getOldPage();
                String oldPageTitle = "no_html";
                if (oldPage instanceof HtmlPage) {
                    oldPageTitle = ((HtmlPage) oldPage).getTitleText();
                }
                logger.debug("Window {} closed : {}", win, oldPageTitle);
            }

            public void webWindowContentChanged(WebWindowEvent event) {
                form = null;
                String winName = event.getWebWindow().getName();
                Page oldPage = event.getOldPage();
                Page newPage = event.getNewPage();
                String oldPageTitle = "no_html";
                if (oldPage instanceof HtmlPage)
                    oldPageTitle = ((HtmlPage) oldPage).getTitleText();
                String newPageTitle = "no_html";
                if (newPage instanceof HtmlPage)
                    newPageTitle = ((HtmlPage) newPage).getTitleText();
                logger.debug("Window \"{}\" changed : \"{}\" became \"{}", new Object[] {winName, oldPageTitle, newPageTitle});
            }

            public void webWindowOpened(WebWindowEvent event) {
                String win = event.getWebWindow().getName();
                Page newPage = event.getNewPage();
                if (newPage != null && newPage instanceof HtmlPage) {
                    logger.debug("Window {} opened : {}", win, ((HtmlPage) newPage).getTitleText());
                } else {
                    logger.info("Window {} opened", win);
                }
            }
        });
        // Add Javascript Alert Handler
        wc.setAlertHandler(new AlertHandler() {
            public void handleAlert(Page page, String msg) {
                if (expectedJavascriptAlerts.size() < 1) {
                    throw new UnexpectedJavascriptAlertException(msg);
                } else {
                    JavascriptAlert expected = (JavascriptAlert) expectedJavascriptAlerts
                            .removeFirst();
                    if (!msg.equals(expected.getMessage())) {
                        throw new UnexpectedJavascriptAlertException(msg);
                    }
                }
            }
        });
        // Add Javascript Confirm Handler
        wc.setConfirmHandler(new ConfirmHandler() {
            public boolean handleConfirm(Page page, String msg) {
                if (expectedJavascriptConfirms.size() < 1) {
                    throw new UnexpectedJavascriptConfirmException(msg);
                } else {
                    JavascriptConfirm expected = (JavascriptConfirm) expectedJavascriptConfirms
                            .removeFirst();
                    if (!msg.equals(expected.getMessage())) {
                        throw new UnexpectedJavascriptConfirmException(msg);
                    } else {
                        return expected.getAction();
                    }
                }
            }
        });
        // Add Javascript Prompt Handler
        wc.setPromptHandler(new PromptHandler() {
            public String handlePrompt(Page page, String msg) {
                if (expectedJavascriptPrompts.size() < 1) {
                    throw new UnexpectedJavascriptPromptException(msg);
                } else {
                    JavascriptPrompt expected = (JavascriptPrompt) expectedJavascriptPrompts
                            .removeFirst();
                    if (!msg.equals(expected.getMessage())) {
                        throw new UnexpectedJavascriptPromptException(msg);
                    } else {
                        return expected.getInput();
                    }
                }
            }
        });
        // Deal with cookies
        for (javax.servlet.http.Cookie c : getTestContext().getCookies()) {
            // If Path==null, cookie is not send to the server.
            wc.getCookieManager().addCookie(
                    new Cookie(c.getDomain() != null ? c.getDomain() : "", c
                            .getName(), c.getValue(), c.getPath() != null ? c                                          
                            .getPath() : "", c.getMaxAge(), c.getSecure()));
        }
        // Deal with custom request header
        Map requestHeaders = getTestContext().getRequestHeaders();

        for (String nextRequestHeaderName : requestHeaders.keySet()) {
            String nextRequestHeaderValue = (String) requestHeaders
                    .get(nextRequestHeaderName);

            wc.addRequestHeader(nextRequestHeaderName, nextRequestHeaderValue);
        }
    }

    /**
     * Return the window with the given name in the current conversation.
     * 
     * @param windowName
     */
    private WebWindow getWindow(String windowName) {
        return wc.getWebWindowByName(windowName);
    }

    private HtmlElement getElement(String anID) {
        try {
            return ((HtmlPage) win.getEnclosedPage()).getHtmlElementById(anID);
        } catch (ElementNotFoundException e) {
            return null;
        }
    }

    private HtmlElement getElementByXPath(String xpath) {
        return getElementByXPath(getCurrentPage(), xpath);
    }

    private HtmlElement getElementByXPath(DomNode parent, String xpath) {
        return (HtmlElement) parent.getFirstByXPath(xpath);
    }

    /**
     * Return the first open window with the given title.
     */
    private WebWindow getWindowByTitle(String title) {
        for (WebWindow window : wc.getWebWindows()) {
            if (window.getEnclosedPage() instanceof HtmlPage
                    && ((HtmlPage) window.getEnclosedPage()).getTitleText()
                            .equals(title)) {
                return window;
            }
        }
        return null;
    }

    /**
     * Return the page title of the current response page, encoded as specified by the current
     * {@link net.sourceforge.jwebunit.util.TestContext}.
     */
    public String getCurrentPageTitle() {
        if (win.getEnclosedPage() instanceof HtmlPage) {
            return ((HtmlPage) win.getEnclosedPage()).getTitleText();
        }
        return "";
    }

    /**
     * 

* Return the current form active for the dialog. *

*

* The active form can also be explicitly set by {@link #setWorkingForm}. *

*

* If this method is called without the form having been implicitly or explicitly set, it will attempt to return the * default first form on the page. *

* * @exception UnableToSetFormException This runtime assertion failure will be raised if there is no form on the * response. * @return HtmlForm object representing the current active form from the response. */ private HtmlForm getForm() { if (form == null) { if (hasForm()) { setWorkingForm(getForm(0)); return getForm(0); } else { throw new RuntimeException("No form in current page"); } } else { return form; } } private HtmlForm getForm(int formIndex) { return (HtmlForm) ((HtmlPage) win.getEnclosedPage()).getForms().get( formIndex); } private HtmlForm getForm(String nameOrID) { try { return (HtmlForm) ((HtmlPage) win.getEnclosedPage()) .getHtmlElementById(nameOrID); } catch (ElementNotFoundException e) { } try { return ((HtmlPage) win.getEnclosedPage()).getFormByName(nameOrID); } catch (ElementNotFoundException e) { } return null; } private HtmlForm getForm(String nameOrID, int index) { List forms = new ArrayList(); for (HtmlForm form : getCurrentPage().getForms()) { if (nameOrID.equals(form.getIdAttribute()) || nameOrID.equals(form.getNameAttribute())) { forms.add(form); } } if (forms.size()>index) { return forms.get(index); } else { return null; } } private HtmlForm getFormWithInput(String inputName) { // Search in Working form if available if (form != null) { if (!form.getHtmlElementsByAttribute("input", "name", inputName).isEmpty()) { return form; } if (!form.getTextAreasByName(inputName).isEmpty()) { return form; } } else { if (hasForm()) { for (HtmlForm form : getForms()) { List inputElements = new LinkedList(); inputElements.addAll(form.getHtmlElementsByAttribute("input", "name", inputName)); if (inputElements.isEmpty()) { inputElements.addAll(form.getTextAreasByName(inputName)); } if (!inputElements.isEmpty()) { setWorkingForm(form); return form; } } } } return null; } private HtmlForm getFormWithSelect(String selectName) { // Search in Working form if available if (form != null) { try { if (form.getSelectByName(selectName) != null) { return form; } } catch (ElementNotFoundException e) { // Nothing } } else { if (hasForm()) { for (int i = 0; i < getForms().size(); i++) { HtmlForm form = (HtmlForm) getForms().get(i); try { if (form.getSelectByName(selectName) != null) { setWorkingForm(form); return form; } } catch (ElementNotFoundException e) { // Nothing } } } } return null; } private List getForms() { HtmlPage page = (HtmlPage) win.getEnclosedPage(); return page.getForms(); } private HtmlPage getCurrentPage() { Page page = win.getEnclosedPage(); if (page instanceof HtmlPage) return (HtmlPage) page; throw new RuntimeException("Non HTML content"); } private void setWorkingForm(HtmlForm newForm) { if (newForm == null) throw new UnableToSetFormException("Attempted to set form to null."); form = newForm; } /** * Return true if a form parameter (input element) is present on the current response. * * @param inputName name of the input element to check for */ public boolean hasFormInputNamed(String inputName) { return (getFormWithInput(inputName) != null); } /** * Return true if a form parameter (input element) is present on the current response. * * @param selectName name of the input element to check for */ public boolean hasFormSelectNamed(String selectName) { return (getFormWithSelect(selectName) != null); } /** * Return the HtmlUnit submit button with a given name. * * @param buttonName name of button. * @return the button */ public ClickableElement getSubmitButton(String buttonName) { List btns = new LinkedList(); if (form != null) { btns.addAll(getForm().getInputsByName(buttonName)); } else { for (HtmlForm f : getCurrentPage().getForms()) { btns.addAll(f.getInputsByName(buttonName)); } } for (HtmlElement o : btns) { if (o instanceof HtmlSubmitInput) { HtmlSubmitInput btn = (HtmlSubmitInput) o; if (form == null) { form = btn.getEnclosingFormOrDie(); } return btn; } if (o instanceof HtmlImageInput) { HtmlImageInput btn = (HtmlImageInput) o; if (form == null) { form = btn.getEnclosingFormOrDie(); } return btn; } if (o instanceof HtmlButton) { HtmlButton btn = (HtmlButton) o; if (btn.getTypeAttribute().equals("submit")) { if (form == null) { form = btn.getEnclosingFormOrDie(); } return btn; } } } return null; } public HtmlResetInput getResetButton(String buttonName) { List btns = new LinkedList(); if (form != null) { btns.addAll(getForm().getInputsByName(buttonName)); } else { for (HtmlForm f : getCurrentPage().getForms()) { btns.addAll(f.getInputsByName(buttonName)); } } for (HtmlElement o : btns) { if (o instanceof HtmlResetInput) { HtmlResetInput btn = (HtmlResetInput) o; if (form == null) { form = btn.getEnclosingFormOrDie(); } return btn; } if (o instanceof HtmlButton) { HtmlResetInput btn = (HtmlResetInput) o; if (btn.getTypeAttribute().equals("reset")) { if (form == null) { form = btn.getEnclosingFormOrDie(); } return btn; } } } return null; } /** * Return the HtmlUnit submit button with a given name and value. * * @param buttonName button name. * @param buttonValue button value. * @return HtmlSubmitInput, HtmlImageInput or HtmlButton */ public ClickableElement getSubmitButton(String buttonName, String buttonValue) { List btns = new LinkedList(); if (form != null) { btns.addAll(getForm().getInputsByName(buttonName)); } else { for (HtmlForm f : getCurrentPage().getForms()) { btns.addAll(f.getInputsByName(buttonName)); } } for (HtmlElement o : btns) { if (o instanceof HtmlSubmitInput) { HtmlSubmitInput btn = (HtmlSubmitInput) o; if (btn.getValueAttribute().equals(buttonValue)) { if (form == null) { form = btn.getEnclosingFormOrDie(); } return btn; } } if (o instanceof HtmlImageInput) { HtmlImageInput btn = (HtmlImageInput) o; if (btn.getValueAttribute().equals(buttonValue)) { if (form == null) { form = btn.getEnclosingFormOrDie(); } return btn; } } if (o instanceof HtmlButton) { HtmlButton btn = (HtmlButton) o; if (btn.getValueAttribute().equals(buttonValue) && btn.getTypeAttribute().equals("submit")) { if (form == null) { form = btn.getEnclosingFormOrDie(); } return btn; } } } return null; } /** * {@inheritDoc} */ public boolean hasSubmitButton() { final HtmlForm htmlForm = getForm(); List l = htmlForm.getByXPath("//input[@type='submit' or @type='image']"); List l2 = htmlForm.getByXPath("//button[@type='submit']"); return (l.size() > 0 || l2.size() > 0); } /** * {@inheritDoc} */ public boolean hasSubmitButton(String buttonName) { return getSubmitButton(buttonName) != null; } /** * {@inheritDoc} */ public boolean hasSubmitButton(String buttonName, String buttonValue) { try { return getSubmitButton(buttonName, buttonValue) != null; } catch (UnableToSetFormException e) { return false; } } public boolean hasResetButton() { HtmlForm form = getForm(); List l = form.getByXPath("//input[@type='reset']"); List l2 = form.getByXPath("//button[@type='reset']"); return (l.size() > 0 || l2.size() > 0); } public boolean hasResetButton(String buttonName) { return getResetButton(buttonName) != null; } /** * Return the HtmlUnit Button with a given id. * * @param buttonId */ private ClickableElement getButton(String buttonId) { HtmlElement btn = null; try { btn = getCurrentPage().getHtmlElementById(buttonId); if (btn instanceof HtmlButton || btn instanceof HtmlButtonInput || btn instanceof HtmlSubmitInput || btn instanceof HtmlResetInput) return (ClickableElement) btn; } catch (ElementNotFoundException e) { return null; } return null; } /** * Checks whether a button containing the specified text as its label exists. * For HTML input tags of type submit, reset, or button, this checks the * value attribute. For HTML button tags, this checks the element's * content by converting it to text. * @param text the text of the button (between <button></button>) * or the value of the "value" attribute. * @return true when the button with text could be found. */ public boolean hasButtonWithText(String text) { return getButtonWithText(text) != null ? true : false; } /** * Returns the first button that contains the specified text as its label. * For HTML input tags of type submit, reset, or button, this checks the * value attribute. For HTML button tags, this checks the element's * content by converting it to text. * @param buttonValueText the text of the button (between <button></button>) * or the value of the "value" attribute. * @return the ClickableElement with the specified text or null if * no such button is found. */ public ClickableElement getButtonWithText(String buttonValueText) { List l = ((HtmlPage) win.getEnclosedPage()).getDocumentElement() .getHtmlElementsByTagNames( Arrays.asList(new String[] { "button", "input" })); for (HtmlElement e : l) { if ( e instanceof HtmlButton ) { if (((HtmlButton) e).asText().equals(buttonValueText)) return (ClickableElement) e; } else if ( e instanceof HtmlButtonInput || e instanceof HtmlSubmitInput || e instanceof HtmlResetInput ) { if ( buttonValueText.equals(e.getAttributeValue("value")) ) return (ClickableElement)e; } } return null; } /** * Returns if the button identified by buttonId is present. * * @param buttonId the id of the button * @return true when the button was found. */ public boolean hasButton(String buttonId) { try { return getButton(buttonId) != null; } catch (UnableToSetFormException e) { return false; } } public boolean isCheckboxSelected(String checkBoxName) { HtmlCheckBoxInput cb = getCheckbox(checkBoxName); return cb.isChecked(); } public boolean isCheckboxSelected(String checkBoxName, String checkBoxValue) { HtmlCheckBoxInput cb = getCheckbox(checkBoxName, checkBoxValue); return cb.isChecked(); } /** * Return true if given text is present in a specified table of the response. * * @param tableSummaryOrId table summary or id to inspect for expected text. * @param text expected text to check for. */ public boolean isTextInTable(String tableSummaryOrId, String text) { HtmlTable table = getHtmlTable(tableSummaryOrId); if (table == null) { throw new RuntimeException("No table with summary or id [" + tableSummaryOrId + "] found in response."); } for (int row = 0; row < table.getRowCount(); row++) { for (int col = 0; table.getCellAt(row, col) != null; col++) { HtmlTableCell cell = table.getCellAt(row, col); if (cell != null) { String cellHtml = cell.asText(); if (cellHtml.indexOf(text) != -1) return true; } } } return false; } public Table getTable(String tableSummaryOrId) { HtmlTable table = getHtmlTable(tableSummaryOrId); Table result = new Table(); for (int i = 0; i < table.getRowCount(); i++) { Row newRow = new Row(); HtmlTableRow htmlRow = table.getRow(i); CellIterator cellIt = htmlRow.getCellIterator(); while (cellIt.hasNext()) { HtmlTableCell htmlCell = cellIt.nextCell(); newRow.appendCell(new Cell(htmlCell.asText(), htmlCell .getColumnSpan(), htmlCell.getRowSpan())); } result.appendRow(newRow); } return result; } /** * Return the HttpUnit WebTable object representing a specified table in the current response. Null is returned if a * parsing exception occurs looking for the table or no table with the id or summary could be found. * * @param tableSummaryOrId summary or id of the table to return. */ public HtmlTable getHtmlTable(String tableSummaryOrId) { try { return (HtmlTable) ((HtmlPage) win.getEnclosedPage()) .getHtmlElementById(tableSummaryOrId); } catch (ElementNotFoundException e) { } try { return (HtmlTable) ((HtmlPage) win.getEnclosedPage()) .getDocumentElement().getOneHtmlElementByAttribute("table", "summary", tableSummaryOrId); } catch (ElementNotFoundException e) { } return null; } public boolean hasTable(String tableSummaryOrId) { HtmlTable table = getHtmlTable(tableSummaryOrId); return (table != null); } /** * Submit the current form with the default submit button. See {@link #getForm}for an explanation of how the * current form is established. */ public void submit() { try { Object[] inpt = getForm().getHtmlElementsByTagName("input") .toArray(); for (int i = 0; i < inpt.length; i++) { if (inpt[i] instanceof HtmlSubmitInput) { ((HtmlSubmitInput) inpt[i]).click(); return; } if (inpt[i] instanceof HtmlImageInput) { ((HtmlImageInput) inpt[i]).click(); return; } if (inpt[i] instanceof HtmlButton && ((HtmlButton) inpt[i]).getTypeAttribute().equals( "submit")) { ((HtmlButton) inpt[i]).click(); return; } } } catch (IOException e) { throw new RuntimeException( "HtmlUnit Error submitting form using default submit button, " + "check that form has single submit button, otherwise use submit(name): \n", e); } throw new RuntimeException("No submit button found in current form."); } /** * Submit the current form with the specified submit button. See {@link #getForm}for an explanation of how the * current form is established. * * @param buttonName name of the button to use for submission. */ public void submit(String buttonName) { List l = new LinkedList(); l.addAll(getForm().getInputsByName(buttonName)); l.addAll(getForm().getButtonsByName(buttonName)); try { for (ClickableElement o : l) { if (o instanceof HtmlSubmitInput) { HtmlSubmitInput inpt = (HtmlSubmitInput) o; inpt.click(); return; } if (o instanceof HtmlImageInput) { HtmlImageInput inpt = (HtmlImageInput) o; inpt.click(); return; } if (o instanceof HtmlButton) { HtmlButton inpt = (HtmlButton) o; if (inpt.getTypeAttribute().equals("submit")) { inpt.click(); return; } } } } catch (IOException e) { throw new RuntimeException( "HtmlUnit Error submitting form using default submit button", e); } throw new RuntimeException("No submit button found in current form."); } /** * Submit the current form with the specifed submit button (by name and value). See {@link #getForm}for an * explanation of how the current form is established. * * @param buttonName name of the button to use for submission. * @param buttonValue value/label of the button to use for submission */ public void submit(String buttonName, String buttonValue) { List l = new LinkedList(); l.addAll(getForm().getInputsByName(buttonName)); l.addAll(getForm().getButtonsByName(buttonName)); try { for (int i = 0; i < l.size(); i++) { Object o = l.get(i); if (o instanceof HtmlSubmitInput) { HtmlSubmitInput inpt = (HtmlSubmitInput) o; if (inpt.getValueAttribute().equals(buttonValue)) { inpt.click(); return; } } if (o instanceof HtmlImageInput) { HtmlImageInput inpt = (HtmlImageInput) o; if (inpt.getValueAttribute().equals(buttonValue)) { inpt.click(); return; } } if (o instanceof HtmlButton) { HtmlButton inpt = (HtmlButton) o; if (inpt.getTypeAttribute().equals("submit") && inpt.getValueAttribute().equals(buttonValue)) { inpt.click(); return; } } } } catch (IOException e) { throw new RuntimeException( "HtmlUnit Error submitting form using submit button with name [" + buttonName + "] and value [" + buttonValue + "]", e); } throw new RuntimeException( "No submit button found in current form with name [" + buttonName + "] and value [" + buttonValue + "]."); } /** * Reset the current form. See {@link #getForm}for an explanation of how the current form is established. */ public void reset() { getForm().reset(); } /** * Return true if a link is present in the current response containing the specified text (note that HttpUnit uses * contains rather than an exact match - if this is a problem consider using ids on the links to uniquely identify * them). * * @param linkText text to check for in links on the response. * @param index The 0-based index, when more than one link with the same text is expected. */ public boolean hasLinkWithText(String linkText, int index) { return getLinkWithText(linkText, index) != null; } public boolean hasLinkWithExactText(String linkText, int index) { return getLinkWithExactText(linkText, index) != null; } public boolean hasLinkWithImage(String imageFileName, int index) { return getLinkWithImage(imageFileName, index) != null; } /** * Return true if a link is present in the current response with the specified id. * * @param anId link id to check for. */ public boolean hasLink(String anId) { try { ((HtmlPage) win.getEnclosedPage()).getHtmlElementById(anId); } catch (ElementNotFoundException e) { return false; } return true; } public void clickLinkWithText(String linkText, int index) { HtmlAnchor link = getLinkWithText(linkText, index); if (link == null) throw new RuntimeException("No Link found for \"" + linkText + "\" with index " + index); try { link.click(); } catch (IOException e) { throw new RuntimeException("Click failed", e); } } public void clickLinkWithExactText(String linkText, int index) { HtmlAnchor link = getLinkWithExactText(linkText, index); if (link == null) throw new RuntimeException("No Link found for \"" + linkText + "\" with index " + index); try { link.click(); } catch (IOException e) { throw new RuntimeException("Click failed", e); } } private HtmlCheckBoxInput getCheckbox(String checkBoxName) { Object[] l = getForm().getInputsByName(checkBoxName).toArray(); for (int i = 0; i < l.length; i++) { if (l[i] instanceof HtmlCheckBoxInput) return (HtmlCheckBoxInput) l[i]; } throw new RuntimeException("No checkbox with name [" + checkBoxName + "] was found in current form."); } private HtmlCheckBoxInput getCheckbox(String checkBoxName, String value) { Object[] l = getForm().getInputsByName(checkBoxName).toArray(); for (int i = 0; i < l.length; i++) { if (l[i] instanceof HtmlCheckBoxInput) if (((HtmlCheckBoxInput) l[i]).getValueAttribute() .equals(value)) return (HtmlCheckBoxInput) l[i]; } throw new RuntimeException("No checkbox with name [" + checkBoxName + "] and value [" + value + "] was found in current form."); } /** * Select a specified checkbox. If the checkbox is already checked then the checkbox will stay checked. * * @param checkBoxName name of checkbox to be deselected. */ public void checkCheckbox(String checkBoxName) { HtmlCheckBoxInput cb = getCheckbox(checkBoxName); if (!cb.isChecked()) try { cb.click(); } catch (IOException e) { throw new RuntimeException("checkCheckbox failed", e); } } public void checkCheckbox(String checkBoxName, String value) { HtmlCheckBoxInput cb = getCheckbox(checkBoxName, value); if (!cb.isChecked()) try { cb.click(); } catch (IOException e) { e.printStackTrace(); throw new RuntimeException("checkCheckbox failed", e); } } /** * Deselect a specified checkbox. If the checkbox is already unchecked then the checkbox will stay unchecked. * * @param checkBoxName name of checkbox to be deselected. */ public void uncheckCheckbox(String checkBoxName) { HtmlCheckBoxInput cb = getCheckbox(checkBoxName); if (cb.isChecked()) try { cb.click(); } catch (IOException e) { e.printStackTrace(); throw new RuntimeException("checkCheckbox failed", e); } } public void uncheckCheckbox(String checkBoxName, String value) { HtmlCheckBoxInput cb = getCheckbox(checkBoxName, value); if (cb.isChecked()) try { cb.click(); } catch (IOException e) { e.printStackTrace(); throw new RuntimeException("uncheckCheckbox failed", e); } } private HtmlRadioButtonInput getRadioOption(String radioGroup, String radioOption) { for (HtmlForm form : getForms()) { List buttons = form.getRadioButtonsByName(radioGroup); for (HtmlRadioButtonInput button : buttons) { if (button.getValueAttribute().equals(radioOption)) { return button; } } } return null; } /** * Clicks a radio option. Asserts that the radio option exists first. * * * @param radioGroup name of the radio group. * @param radioOption value of the option to check for. */ public void clickRadioOption(String radioGroup, String radioOption) { HtmlRadioButtonInput rb = getRadioOption(radioGroup, radioOption); if (!rb.isChecked()) try { rb.click(); } catch (IOException e) { e.printStackTrace(); throw new RuntimeException("checkCheckbox failed", e); } } /** * Navigate by submitting a request based on a link with a given ID. A RuntimeException is thrown if no such link * can be found. * * @param anID id of link to be navigated. */ public void clickLink(String anID) { clickElementByXPath("//a[@id=\"" + anID + "\"]"); } private HtmlAnchor getLinkWithImage(String filename, int index) { return (HtmlAnchor) getElementByXPath("(//a[img[contains(@src,\"" + filename + "\")]])[" + index + 1 + "]"); } private HtmlAnchor getLinkWithText(String linkText, int index) { List lnks = ((HtmlPage) win.getEnclosedPage()).getAnchors(); int count = 0; for (HtmlAnchor lnk : lnks) { if ((lnk.asText().indexOf(linkText) >= 0) && (count++ == index)) return lnk; } return null; } private HtmlAnchor getLinkWithExactText(String linkText, int index) { List lnks = ((HtmlPage) win.getEnclosedPage()).getAnchors(); int count = 0; for (HtmlAnchor lnk : lnks) { if ((lnk.asText().equals(linkText)) && (count++ == index)) return lnk; } return null; } /** * Navigate by submitting a request based on a link with a given image file name. A RuntimeException is thrown if no * such link can be found. * * @param imageFileName A suffix of the image's filename; for example, to match * "images/my_icon.png", you could just pass in * "my_icon.png". */ public void clickLinkWithImage(String imageFileName, int index) { HtmlAnchor link = getLinkWithImage(imageFileName, index); if (link == null) throw new RuntimeException("No Link found with filename \"" + imageFileName + "\" and index " + index); try { link.click(); } catch (IOException e) { throw new RuntimeException("Click failed", e); } } public boolean hasElement(String anID) { return getElement(anID) != null; } public boolean hasElementByXPath(String xpath) { return getElementByXPath(xpath) != null; } public void clickElementByXPath(String xpath) { HtmlElement e = getElementByXPath(xpath); if (e == null) throw new RuntimeException("No element found with xpath \"" + xpath + "\""); try { ClickableElement c = (ClickableElement) e; c.click(); } catch (ClassCastException exp) { throw new RuntimeException("Element with xpath \"" + xpath + "\" is not clickable", exp); } catch (IOException exp) { throw new RuntimeException("Click failed", exp); } } public String getElementAttributByXPath(String xpath, String attribut) { HtmlElement e = getElementByXPath(xpath); if (e == null) return null; return e.getAttributeValue(attribut); } public String getElementTextByXPath(String xpath) { HtmlElement e = getElementByXPath(xpath); if (e == null) return null; return e.asText(); } /** * Click the indicated button (input type=button). * * @param buttonId */ public void clickButton(String buttonId) { ClickableElement btn = getButton(buttonId); try { btn.click(); } catch (Exception e) { throw new RuntimeException(e); } } /** * Clicks the first button that contains the specified text as its label. * For HTML input tags of type submit, reset, or button, this checks the * value attribute. For HTML button tags, this checks the element's * content by converting it to text. or an HTML <button> tag. */ public void clickButtonWithText(String buttonValueText) { ClickableElement b = getButtonWithText(buttonValueText); if (b != null) { try { b.click(); } catch (Exception e) { throw new RuntimeException(e); } } else { throw new RuntimeException("No button found with text: " + buttonValueText); } } /** * Return true if a radio group contains the indicated option. * * @param radioGroup name of the radio group. * @param radioOption value of the option to check for. */ public boolean hasRadioOption(String radioGroup, String radioOption) { return getRadioOption(radioGroup, radioOption) != null; } public String getSelectedRadio(String radioGroup) { List radios = getForm().getRadioButtonsByName(radioGroup); for (HtmlRadioButtonInput radio : radios) { if (radio.isChecked()) { return radio.getValueAttribute(); } } throw new RuntimeException("Unexpected state: no radio button was selected in radio group ["+radioGroup+"]. Is it possible in a real browser?"); } /** * Return true if a select box contains the indicated option. * * @param selectName name of the select box. * @param optionLabel label of the option. */ public boolean hasSelectOption(String selectName, String optionLabel) { String[] opts = getSelectOptionValues(selectName); for (int i = 0; i < opts.length; i++) { String label = getSelectOptionLabelForValue(selectName, opts[i]); if (label.equals(optionLabel)) return true; } return false; } /** * Return true if a select box contains the indicated option. * * @param selectName name of the select box. * @param optionValue value of the option. */ public boolean hasSelectOptionValue(String selectName, String optionValue) { String[] opts = getSelectOptionValues(selectName); for (int i = 0; i < opts.length; i++) { if (opts[i].equals(optionValue)) return true; } return false; } /** * Select the specified set of options in the select element * with the provided name. * @param selectName name of the select box * @param options set of options to select. */ public void selectOptions(String selectName, String[] options) { HtmlSelect sel = getForm().getSelectByName(selectName); if (!sel.isMultipleSelectEnabled() && options.length > 1) throw new RuntimeException("Multiselect not enabled"); for (String option : options) { boolean found = false; for (HtmlOption opt : sel.getOptions()) { if (opt.getValueAttribute().equals(option)) { sel.setSelectedAttribute(opt, true); found = true; break; } } if (!found) throw new RuntimeException("Option " + option + " not found"); } } /** * Return true if the Nth select box contains the indicated option. * * @param selectName name of the select box. * @param index the 0-based index of the select element when multiple * select elements are expected. * @param optionLabel label of the option. */ public boolean hasSelectOption(String selectName, int index, String optionLabel) { String[] opts = getSelectOptionValues(selectName, index); for (int i = 0; i < opts.length; i++) { String label = getSelectOptionLabelForValue(selectName, index, opts[i]); if (label.equals(optionLabel)) return true; } return false; } /** * Return true if the Nth select box contains the indicated option. * * @param selectName name of the select box. * @param index the 0-based index of the select element when multiple * select elements are expected. * @param optionValue value of the option. */ public boolean hasSelectOptionValue(String selectName, int index, String optionValue) { String[] opts = getSelectOptionValues(selectName, index); for (int i = 0; i < opts.length; i++) { if (opts[i].equals(optionValue)) return true; } return false; } /** * Select the specified set of options in the select element * with the provided name. * @param selectName name of the select box * @param index the 0-based index of the select element when multiple * select elements are expected. * @param options set of options to select. */ public void selectOptions(String selectName, int index, String[] options) { List sels = getForm().getSelectsByName(selectName); if ( sels == null || sels.size() < index+1 ) throw new RuntimeException("Did not find select with name [" + selectName + "] at index " + index); HtmlSelect sel = (HtmlSelect)sels.get(index); if (!sel.isMultipleSelectEnabled() && options.length > 1) throw new RuntimeException("Multiselect not enabled"); for (String option : options) { boolean found = false; for (HtmlOption opt : sel.getOptions()) { if (opt.getValueAttribute().equals(option)) { sel.setSelectedAttribute(opt, true); found = true; break; } } if (!found) throw new RuntimeException("Option " + option + " not found"); } } public void unselectOptions(String selectName, String[] options) { HtmlSelect sel = getForm().getSelectByName(selectName); if (!sel.isMultipleSelectEnabled() && options.length > 1) throw new RuntimeException("Multiselect not enabled"); for (String option : options) { boolean found = false; for (HtmlOption opt : sel.getOptions()) { if (opt.asText().equals(option)) { sel.setSelectedAttribute(opt, false); found = true; break; } } if (!found) throw new RuntimeException("Option " + option + " not found"); } } public void unselectOptions(String selectName, int index, String[] options) { List sels = getForm().getSelectsByName(selectName); if ( sels == null || sels.size() < index+1) throw new RuntimeException("Did not find select with name [" + selectName + "] at index " + index); HtmlSelect sel = sels.get(index); if (!sel.isMultipleSelectEnabled() && options.length > 1) throw new RuntimeException("Multiselect not enabled"); for (String option : options) { boolean found = false; for (HtmlOption opt : sel.getOptions()) { if (opt.asText().equals(option)) { sel.setSelectedAttribute(opt, false); found = true; break; } } if (!found) throw new RuntimeException("Option " + option + " not found"); } } public boolean isTextInElement(String elementID, String text) { return isTextInElement(getElement(elementID), text); } /** * Return true if a given string is contained within the specified element. * * @param element org.w3c.com.Element to inspect. * @param text text to check for. */ private boolean isTextInElement(HtmlElement element, String text) { return element.asText().indexOf(text) >= 0; } public boolean isMatchInElement(String elementID, String regexp) { return isMatchInElement(getElement(elementID), regexp); } /** * Return true if a given regexp is contained within the specified element. * * @param element org.w3c.com.Element to inspect. * @param regexp regexp to match. */ private boolean isMatchInElement(HtmlElement element, String regexp) { RE re = getRE(regexp); return re.match(element.asText()); } private RE getRE(String regexp) { try { return new RE(regexp, RE.MATCH_SINGLELINE); } catch (RESyntaxException e) { throw new RuntimeException(e); } } /** * Make the root window in the current conversation active. */ public void gotoRootWindow() { setMainWindow((WebWindow) wc.getWebWindows().get(0)); } private void setMainWindow(WebWindow win) { wc.setCurrentWindow(win); this.win = win; } /** * Return the given frame in the current conversation. * * @param frameNameOrId Frame name or ID. * @return The frame found or null. */ private WebWindow getFrame(String frameNameOrId) { // First try ID for (FrameWindow frame : getCurrentPage().getFrames()) { if (frameNameOrId.equals(frame.getFrameElement().getId())) { return frame; } } // Now try with Name for (FrameWindow frame : getCurrentPage().getFrames()) { if (frameNameOrId.equals(frame.getName())) { return frame; } } // Nothing was found. return null; } /** * @param testContext The testContext to set. */ private void setTestContext(TestContext testContext) { this.testContext = testContext; } /** * @return Returns the testContext. */ private TestContext getTestContext() { return testContext; } public void setExpectedJavaScriptAlert(JavascriptAlert[] alerts) throws ExpectedJavascriptAlertException { if (this.expectedJavascriptAlerts.size() > 0) { throw new ExpectedJavascriptAlertException( ((JavascriptAlert) (expectedJavascriptAlerts.get(0))) .getMessage()); } for (int i = 0; i < alerts.length; i++) { expectedJavascriptAlerts.add(alerts[i]); } } public void setExpectedJavaScriptConfirm(JavascriptConfirm[] confirms) throws ExpectedJavascriptConfirmException { if (this.expectedJavascriptConfirms.size() > 0) { throw new ExpectedJavascriptConfirmException( ((JavascriptConfirm) (expectedJavascriptConfirms.get(0))) .getMessage()); } for (int i = confirms.length - 1; i >= 0; i--) { expectedJavascriptConfirms.add(confirms[i]); } } public void setExpectedJavaScriptPrompt(JavascriptPrompt[] prompts) throws ExpectedJavascriptPromptException { if (this.expectedJavascriptPrompts.size() > 0) { throw new ExpectedJavascriptPromptException( ((JavascriptPrompt) (expectedJavascriptPrompts.get(0))) .getMessage()); } for (int i = prompts.length - 1; i >= 0; i--) { expectedJavascriptPrompts.add(prompts[i]); } } }