001: // Copyright © 2002-2005 Canoo Engineering AG, Switzerland.
002: package com.canoo.webtest.steps.verify;
003:
004: import com.canoo.webtest.engine.StepFailedException;
005: import com.canoo.webtest.extension.StoreElementAttribute;
006: import com.gargoylesoftware.htmlunit.html.HtmlElement;
007: import com.gargoylesoftware.htmlunit.html.HtmlPage;
008: import org.apache.log4j.Logger;
009: import org.apache.commons.lang.StringUtils;
010:
011: import java.util.ArrayList;
012: import java.util.Iterator;
013: import java.util.List;
014:
015: /**
016: * This step verifies if the specified text (CDATA) is enclosed
017: * by an HTML element (tag) of the specified type. A name can
018: * be specified in case that the element in question appears
019: * multiple times. The text can be specified as a regular expression.
020: * <p/>
021: * Example 1:<br/>
022: * HTML source:
023: * <pre>
024: * <title>The page title</title>
025: * </pre>
026: * <p/>
027: * Possible statements:
028: * <pre>
029: * <verifyElementText type="title" text="The page title"/>
030: * <verifyElementText type="title" text=".*page title.*" regex="true"/>
031: * </pre>
032: * <p/>
033: * Example 2:
034: * HTML source:
035: * <pre>
036: * <textarea name="Hugo">
037: * The very large text area named hugo.
038: * </textarea>
039: * </pre>
040: * <p/>
041: * Possible statements:
042: * <pre>
043: * <verifyElementText type="textarea" name="Hugo" text="The very large text area named hugo."/>
044: * <verifyElementText type="textarea" name="Hugo" text=".*text area.*" regex="true"/>
045: * </pre><p/>
046: *
047: * @author Unknown
048: * @author Marc Guillemot
049: * @author Paul King
050: * @webtest.step
051: * category="Core"
052: * name="verifyElementText"
053: * alias="verifyelementtext"
054: * description="This step verifies whether the <key>HTML</key> element specified by <em>htmlId</em> or <em>type</em>
055: * and optional <em>name</em> encloses <em>text</em> between its opening and closing tags."
056: */
057: public class VerifyElementText extends AbstractVerifyTextStep {
058: private static final Logger LOG = Logger
059: .getLogger(VerifyElementText.class);
060: private String fType;
061: private String fName;
062: private String fHtmlId;
063:
064: public void doExecute() {
065: final HtmlElement elt;
066: if (StringUtils.isEmpty(getHtmlId())) {
067: elt = findElementByTypeAndOptionalName();
068: } else {
069: elt = StoreElementAttribute
070: .findElement(getContext().getCurrentResponse(),
071: getHtmlId(), null, LOG, this );
072: }
073: if (!verifyText(readText(elt))) {
074: throw new StepFailedException(getFailedMessage(),
075: getText(), readText(elt), this );
076: }
077: }
078:
079: private HtmlElement findElementByTypeAndOptionalName() {
080: final List li = ((HtmlPage) getContext().getCurrentResponse())
081: .getDocumentHtmlElement().getHtmlElementsByTagName(
082: getType());
083: LOG.debug(li.size() + " elts found of type \"" + getType()
084: + "\"");
085: if (li.isEmpty()) {
086: throw new StepFailedException("No element found of type \""
087: + getType() + "\"", this );
088: }
089: if (li.size() > 1 && getName() == null) {
090: throw new StepFailedException(
091: "More than 1 element with type \"" + getType()
092: + "\" found! No name is specified.", this );
093: }
094:
095: final HtmlElement elt;
096: if (getName() != null) {
097: final List namedElements = findNodesWithAttribute(li,
098: ELEMENT_ATTRIBUTE_NAME, getName());
099:
100: if (namedElements.isEmpty()) {
101: throw new StepFailedException("No element of type \""
102: + getType() + "\" and name \"" + getName()
103: + "\" found!", this );
104: }
105: if (namedElements.size() > 1) {
106: throw new StepFailedException(
107: "More than 1 element of type \"" + getType()
108: + "\" with name \"" + getName()
109: + "\" found!", this );
110: }
111: elt = (HtmlElement) namedElements.get(0);
112: } else {
113: elt = (HtmlElement) li.get(0);
114: }
115: return elt;
116: }
117:
118: /**
119: * Gets the text representation of the element
120: * @param elt
121: * @return the text for the element
122: */
123: protected String readText(final HtmlElement elt) {
124: LOG.debug("Reading text for " + elt);
125: return elt.asText();
126: }
127:
128: protected static List findNodesWithAttribute(final List li,
129: final String attributeName, final String attributeValue) {
130: LOG.debug("Looking in list for elements with attribute \""
131: + attributeName + "\"'s value: \"" + attributeValue
132: + "\"");
133: List result = new ArrayList();
134: for (Iterator iter = li.iterator(); iter.hasNext();) {
135: final HtmlElement elt = (HtmlElement) iter.next();
136: final String strValue = elt
137: .getAttributeValue(attributeName);
138:
139: if (attributeValue.equals(strValue)) {
140: result.add(elt);
141: } else {
142: LOG.debug("Value: \"" + strValue + "\" => not ok for "
143: + elt);
144: }
145: }
146: LOG.debug(result.size() + " element(s) found");
147: return result;
148: }
149:
150: protected String getFailedMessage() {
151: StringBuffer sb = new StringBuffer();
152: sb.append("Wrong contents found in HTML element (type=\"");
153: sb.append(getType());
154: sb.append("\", name=\"");
155: sb.append(getName());
156: sb.append("\", htmlId=\"");
157: sb.append(getHtmlId());
158: sb.append("\")!");
159: return sb.toString();
160: }
161:
162: public String getName() {
163: return fName;
164: }
165:
166: /**
167: * @webtest.parameter
168: * required="no"
169: * description="The name of the element, i.e. the value of the 'name' attribute. Ignored if using 'htmlId'."
170: */
171: public void setName(String newName) {
172: fName = newName;
173: }
174:
175: public String getType() {
176: return fType;
177: }
178:
179: /**
180: * @webtest.parameter
181: * required="yes/no"
182: * description="The HTML element (tag) name. One of 'htmlId' or 'type' must be set."
183: */
184: public void setType(String newType) {
185: fType = newType;
186: }
187:
188: public String getHtmlId() {
189: return fHtmlId;
190: }
191:
192: /**
193: * @webtest.parameter
194: * required="yes/no"
195: * description="The HTML htmlId of the element. One of 'htmlId' or 'type' must be set."
196: */
197: public void setHtmlId(String htmlId) {
198: this .fHtmlId = htmlId;
199: }
200:
201: protected void verifyParameters() {
202: super .verifyParameters();
203: paramCheck(StringUtils.isEmpty(getType())
204: && StringUtils.isEmpty(getHtmlId()),
205: "One of 'htmlId' or 'type' must be set.");
206: }
207: }
|