001: /*
002: * Copyright (c) 2002-2008 Gargoyle Software Inc. All rights reserved.
003: *
004: * Redistribution and use in source and binary forms, with or without
005: * modification, are permitted provided that the following conditions are met:
006: *
007: * 1. Redistributions of source code must retain the above copyright notice,
008: * this list of conditions and the following disclaimer.
009: * 2. Redistributions in binary form must reproduce the above copyright notice,
010: * this list of conditions and the following disclaimer in the documentation
011: * and/or other materials provided with the distribution.
012: * 3. The end-user documentation included with the redistribution, if any, must
013: * include the following acknowledgment:
014: *
015: * "This product includes software developed by Gargoyle Software Inc.
016: * (http://www.GargoyleSoftware.com/)."
017: *
018: * Alternately, this acknowledgment may appear in the software itself, if
019: * and wherever such third-party acknowledgments normally appear.
020: * 4. The name "Gargoyle Software" must not be used to endorse or promote
021: * products derived from this software without prior written permission.
022: * For written permission, please contact info@GargoyleSoftware.com.
023: * 5. Products derived from this software may not be called "HtmlUnit", nor may
024: * "HtmlUnit" appear in their name, without prior written permission of
025: * Gargoyle Software Inc.
026: *
027: * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,
028: * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
029: * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL GARGOYLE
030: * SOFTWARE INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
031: * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
032: * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
033: * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
034: * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
035: * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
036: * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
037: */
038: package com.gargoylesoftware.htmlunit.html;
039:
040: import org.mozilla.javascript.ScriptableObject;
041:
042: import com.gargoylesoftware.htmlunit.WebTestCase;
043: import com.gargoylesoftware.htmlunit.javascript.host.HTMLElement;
044:
045: /**
046: * Tests for {@link HtmlTableRow}.
047: *
048: * @version $Revision: 2132 $
049: * @author <a href="mailto:gallaherm@pragmatics.com">Mike Gallaher</a>
050: * @author Mike Bowler
051: * @author Ahmed Ashour
052: * @author Marc Guillemot
053: */
054: public class HtmlTableRowTest extends WebTestCase {
055:
056: /**
057: * Create an instance.
058: * @param name The name of the test
059: */
060: public HtmlTableRowTest(final String name) {
061: super (name);
062: }
063:
064: private static final String htmlContent = "<html><head><title>foo</title></head><body>\n"
065: + "<table id='table'><tr id='row'>\n"
066: + "<td id='cell' width='20'><input type='text' id='foo'/></td>\n"
067: + "</tr></table>\n" + "</body></html>";
068:
069: private HtmlPage page_;
070: private HtmlTable table_;
071: private HtmlTableBody tbody_;
072: private HtmlTableRow row_;
073: private HtmlTableCell cell_;
074: private HtmlTableRow rowClone_;
075: private HtmlTableCell cellClone_;
076:
077: /**
078: * {@inheritDoc}
079: */
080: public void setUp() throws Exception {
081: page_ = loadPage(htmlContent);
082:
083: table_ = (HtmlTable) page_.getHtmlElementById("table");
084: tbody_ = (HtmlTableBody) table_.getFirstDomChild();
085: row_ = table_.getRow(0);
086: cell_ = row_.getCell(0);
087:
088: rowClone_ = (HtmlTableRow) row_.cloneDomNode(true);
089: cellClone_ = rowClone_.getCell(0);
090: }
091:
092: /**
093: * Ensure that cloneNode leaves the original node unchanged.
094: */
095: public void testClonePreservesOriginal() {
096: assertSame(tbody_, row_.getParentDomNode());
097: assertSame(row_, cell_.getParentDomNode());
098: assertSame(cell_, row_.getCell(0));
099: assertEquals("row", row_.getId());
100: assertEquals("cell", cell_.getId());
101: }
102:
103: /**
104: * Ensure that the clones are not the originals.
105: * @throws Exception if the test fails.
106: */
107: public void testClonesAreDistinct() throws Exception {
108: assertNotSame(row_, rowClone_);
109: assertNotSame(cell_, cellClone_);
110: }
111:
112: /**
113: * Ensure that the clones have the same page as the originals.
114: */
115: public void testCloneHasSamePage() {
116: assertSame(cell_.getPage(), cellClone_.getPage());
117: assertSame(row_.getPage(), rowClone_.getPage());
118: }
119:
120: /**
121: * Ensure that the cloned row has no parent.
122: * @throws Exception if the test fails.
123: */
124: public void testClonedRowHasNullParent() throws Exception {
125: assertNull(rowClone_.getParentDomNode());
126: }
127:
128: /**
129: * Ensure that the cloned row's children are not those of the original.
130: * @throws Exception if the test fails.
131: */
132: public void testClonedRowHasDifferentChildren() throws Exception {
133: assertEquals(row_.getCells().size(), rowClone_.getCells()
134: .size());
135: assertNotSame(row_.getFirstDomChild(), rowClone_
136: .getFirstDomChild());
137: }
138:
139: /**
140: * Ensure that the cloned cell's children are not those of the original.
141: */
142: public void testClonedCellHasDifferentChildren() {
143: assertNotSame(cell_.getParentDomNode(), cellClone_
144: .getParentDomNode());
145: assertNotNull(cell_.getFirstDomChild());
146: assertNotSame(cell_.getFirstDomChild(), cellClone_
147: .getFirstDomChild());
148: }
149:
150: /**
151: * Ensure that the cloned cell has the cloned row as its parent.
152: * @throws Exception if the test fails.
153: */
154: public void testClonedCellHasClonedRowAsParent() throws Exception {
155: assertSame(rowClone_, cellClone_.getParentDomNode());
156: }
157:
158: /**
159: * Ensure the cloned cell's attribute value is the same as the original.
160: */
161: public void testCloneAttributesCopiedFromOriginal() {
162: assertEquals("20", cell_.getAttributeValue("width"));
163: assertEquals("20", cellClone_.getAttributeValue("width"));
164: }
165:
166: /**
167: * Ensure that changing the clone's attribute leaves the original's
168: * attribute unchanged.
169: */
170: public void testCloneAttributeIsIndependentOfOriginal() {
171: cellClone_.setAttributeValue("a", "one");
172: assertFalse("one".equals(cell_.getAttributeValue("a")));
173: }
174:
175: /**
176: * Ensure that changing the original's attribute leaves the clone's
177: * attribute unchanged.
178: */
179: public void testOriginalAttributeIsIndependentOfClone() {
180: cell_.setAttributeValue("a", "one");
181: assertFalse("one".equals(cellClone_.getAttributeValue("a")));
182: }
183:
184: /**
185: * Ensure that changing the clone's nodeValue leaves the original's
186: * unchanged.
187: */
188: public void testCloneValueIsIndependentOfOriginal() {
189: cellClone_.setNodeValue("one");
190: assertFalse("one".equals(cell_.getNodeValue()));
191: }
192:
193: /**
194: * Ensure that changing the clone's id leaves the original's unchanged.
195: */
196: public void testCloneIdIsIndependentOfOriginal() {
197: cellClone_.setNodeValue("one");
198: assertFalse("one".equals(cell_.getNodeValue()));
199: }
200:
201: // these next few test our assumptions about how scripts affect the DOM
202:
203: /**
204: * Ensure that the JavaScript object returned by the script fragment really
205: * refers to the same DOM node we think it should.
206: */
207: public void testScriptCanGetOriginalCell() {
208: final String cmd = "document.getElementById('cell')";
209: final Object object = page_.executeJavaScript(cmd)
210: .getJavaScriptResult();
211:
212: final HtmlElement cellElement = ((HTMLElement) object)
213: .getHtmlElementOrDie();
214: assertSame(cell_, cellElement);
215: }
216:
217: /**
218: * Ensure that the JavaScript object returned by the script fragment is the
219: * same one the DOM node thinks it's wrapped by.
220: */
221: public void testCellScriptObjectIsReturnedByScript() {
222: final String cmd = "document.getElementById('cell')";
223: final HTMLElement jselement = (HTMLElement) page_
224: .executeJavaScript(cmd).getJavaScriptResult();
225:
226: assertSame(jselement, cell_.getScriptObject());
227: }
228:
229: /**
230: * Ensure that setting a property via script sets the property on the
231: * ScriptableObject that we think it should.
232: */
233: public void testScriptCanSetJsPropertyOnCell() {
234: final String cmd = "document.getElementById('cell').a='original';document.getElementById('cell')";
235: final Object object = page_.executeJavaScript(cmd)
236: .getJavaScriptResult();
237:
238: final HTMLElement jselement = ((HTMLElement) object);
239: assertEquals("original", ScriptableObject.getProperty(
240: jselement, "a"));
241:
242: assertSame(jselement, cell_.getScriptObject());
243: }
244:
245: /**
246: * Ensure that a script can set the disabled property on a DOM node.
247: */
248: public void testCloneScriptCanSetDisabledOnCell() {
249: final String cmd = "document.getElementById('cell').disabled='true'";
250: page_.executeJavaScript(cmd);
251: assertEquals("disabled", cell_.getAttributeValue("disabled"));
252: }
253:
254: /**
255: * Ensure that a script can set an attribute on the DOM node.
256: */
257: public void testCloneScriptCanSetAttributeOnCell() {
258: final String cmd = "document.getElementById('cell').setAttribute('a','original')";
259: page_.executeJavaScript(cmd);
260: assertEquals("original", cell_.getAttributeValue("a"));
261: }
262:
263: // these next few check that scripts manipulate the clone independently
264:
265: /**
266: * Ensure that a script setting an attribute on the original does not affect
267: * that same attribute on the clone.
268: */
269: public void testCloneScriptSetAttributeIndependentOfOriginal() {
270: final String cmd = "document.getElementById('cell').setAttribute('a','original')";
271: page_.executeJavaScript(cmd);
272:
273: assertEquals("original", cell_.getAttributeValue("a"));
274: assertFalse("original"
275: .equals(cellClone_.getAttributeValue("a")));
276: }
277:
278: /**
279: * Ensure that a script setting disabled on the original does not affect
280: * that same attribute on the clone.
281: */
282: public void testCloneScriptSetDisabledIndependentOfOriginal() {
283: final String cmd = "document.getElementById('cell').disabled = 'true'";
284: page_.executeJavaScript(cmd);
285:
286: assertEquals("disabled", cell_.getAttributeValue("disabled"));
287: assertFalse("disabled".equals(cellClone_
288: .getAttributeValue("disabled")));
289: }
290:
291: /**
292: * Ensure that a script referencing an element causes only that DOM element
293: * to get a ScriptObject assigned, and does not cause one to be assigned to
294: * the clone.
295: */
296: public void testCloneHasDifferentScriptableObject() {
297: final String cmd = "document.getElementById('cell')"; // force it to have a
298: // scriptable object
299: page_.executeJavaScript(cmd);
300:
301: assertNotSame(cell_.getScriptObject(), cellClone_
302: .getScriptObject());
303: }
304:
305: /**
306: * Ensure that setting the value on a child of a table cell doesn't affect
307: * the cloned child.
308: */
309: public void testScriptDomOperations() {
310: final String cmd = "document.getElementById('foo').value = 'Input!';document.getElementById('foo')";
311: page_.executeJavaScript(cmd);
312:
313: final HtmlElement input = (HtmlElement) cell_
314: .getFirstDomChild();
315: assertEquals("Input!", input.getAttributeValue("value"));
316:
317: final HtmlElement inputClone = (HtmlElement) cellClone_
318: .getFirstDomChild();
319: assertFalse("Input!".equals(inputClone
320: .getAttributeValue("value")));
321: }
322: }
|