// Copyright � 2004-2005 ASERT. Released under the Canoo Webtest license.
package com.canoo.webtest.extension;
import com.canoo.webtest.engine.StepExecutionException;
import com.canoo.webtest.engine.StepFailedException;
import com.canoo.webtest.steps.Step;
import com.canoo.webtest.steps.store.BaseStoreStep;
import com.canoo.webtest.boundary.HtmlUnitBoundary;
import com.gargoylesoftware.htmlunit.ElementNotFoundException;
import com.gargoylesoftware.htmlunit.Page;
import com.gargoylesoftware.htmlunit.html.HtmlElement;
import com.gargoylesoftware.htmlunit.html.HtmlPage;
import org.apache.log4j.Logger;
/**
* StoreElementAttribute
*
* @author Paul King
* @webtest.step category="Extension"
* name="storeElementAttribute"
* description="Retrieves a particular attribute value of an element. E.g. the <em>style</em> attribute could be retrieved for an <key>HTML</key> element such as <TD style='color:green' ...>"
*/
public class StoreElementAttribute extends BaseStoreStep {
private static final Logger LOG = Logger.getLogger(StoreElementAttribute.class);
private String fHtmlId;
private String fXPath;
private String fAttributeName;
/**
* Locate all applicable html elements, check their number (size == 1) and
* store the value of the attribute.
*
* @throws com.canoo.webtest.engine.StepFailedException
* if no applicable button was found
*/
public void doExecute() throws Exception {
nullResponseCheck();
final HtmlElement element = findElement(getContext().getCurrentResponse(), getHtmlId(), getXpath(), LOG, this);
String retval = element.getAttribute(getAttributeName());
if (retval == HtmlElement.ATTRIBUTE_NOT_DEFINED) {
retval = "undefined";
} else if (retval == HtmlElement.ATTRIBUTE_VALUE_EMPTY || retval.length() == 0) {
retval = "empty";
}
storeProperty(retval);
}
/**
* Search for the element by id or xpath.<p>
*
* @param currentResp the html page in which to search
* @param id
* @param xpathStr
* @param log
* @param step
* @return the element
* @throws com.canoo.webtest.engine.StepFailedException if no element is found
*/
public static HtmlElement findElement(final Page currentResp, final String id, final String xpathStr,
final Logger log, final Step step) throws StepFailedException {
if (id != null) {
return findElementById(currentResp, id, log, step);
}
return findElementByXpath(currentResp, xpathStr, log, step);
}
static HtmlElement findElementById(final Page currentResp, final String id,
final Logger log, final Step step) throws StepFailedException {
log.debug("Looking for element with id \"" + id + "\"");
try {
if (!(currentResp instanceof HtmlPage)) {
throw new StepExecutionException("Current response is not an HTML page but of type "
+ currentResp.getWebResponse().getContentType(), step);
}
HtmlPage lastHtmlResp = (HtmlPage) currentResp;
final HtmlElement element = lastHtmlResp.getHtmlElementById(id);
log.debug("found element with id \"" + id + "\": " + element);
return element;
} catch (final ElementNotFoundException e) {
throw new StepFailedException("No element found with id \"" + id + "\".", step);
}
}
static HtmlElement findElementByXpath(final Page currentResp, final String xpathStr,
final Logger log, final Step step) throws StepFailedException {
log.debug("Looking for element with xpath \"" + xpathStr + "\"");
Object node;
node = HtmlUnitBoundary.trySelectSingleNodeByXPath(xpathStr, currentResp, step);
if (node == null) {
throw new StepFailedException("No element found with xpath \"" + xpathStr + "\".", step);
}
try {
return (HtmlElement) node;
} catch (ClassCastException cce) {
throw new StepFailedException("The xpath doesn't select an Element: '" + node.getClass() + "'");
}
}
/**
* Sets the id attribute of the element of interest.<p>
*
* @param str the new value
* @webtest.parameter required="yes/no"
* description="The id of the html element to click on."
*/
public void setHtmlId(final String str) {
fHtmlId = str;
}
public String getHtmlId() {
return fHtmlId;
}
/**
* Sets the XPath used to identify the element of interest.<p>
*
* @param path the new value
* @webtest.parameter required="yes/no"
* description="The XPath identifying the html element to click on."
*/
public void setXpath(final String path) {
fXPath = path;
}
public String getXpath() {
return fXPath;
}
/**
* Sets the name of the attribute of interest.<p>
*
* @param name Sets the name of the attribute.
* @webtest.parameter required="yes"
* description="The name of the attribute of interest, e.g. \"disabled\" or \"checked\"."
*/
public void setAttributeName(final String name) {
fAttributeName = name;
}
public String getAttributeName() {
return fAttributeName;
}
/**
* Sets the Name of the Property.<p>
*
* @param name The Property Name
* @webtest.parameter
* required="no"
* description="Deprecated. Same as property."
* @deprecated since 03.2007. Use {@link #setProperty(String)}
*/
public void setPropertyName(final String name) {
LOG.warn("'propertyName' is deprecated. Use 'property' instead");
setProperty(name);
}
/**
* Verifies the parameters.<p>
*/
protected void verifyParameters() {
super.verifyParameters();
paramCheck(getHtmlId() == null && getXpath() == null, "\"htmlId\" or \"xPath\" must be set!");
paramCheck(getHtmlId() != null && getXpath() != null, "Only one from \"htmlId\" and \"xPath\" can be set!");
nullParamCheck(getProperty(), "property");
nullParamCheck(getAttributeName(), "attributeName");
}
}