Author: johnh
Date: Thu Aug 14 18:48:26 2008
New Revision: 686106
URL: http://svn.apache.org/viewvc?rev=686106&view=rev
Log:
Initial implementation of the classes involved in manipulating mutable gadget
HTML and CSS.
Each class can be created from a Parsed equivalent of itself, or freshly
created in-memory.
The HTML representation is a sort of DOM-lite, while CSS manipulation consists
of ordered-string
(selector) manipulation and String/String Map manipulation for declarations.
Tests are provided
for each creation mechanism and all APIs.
This implementation will likely change notably as I and others attempt to put
it to real use in
rewriters. Hopefully modifying it will be reasonably easy due to its being
abstracted away
from parsing logic.
This commit resolves SHINDIG-524, and does not affect any existing
functionality yet.
Added:
incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/parse/GadgetCssDeclaration.java
incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/parse/GadgetCssRule.java
incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/parse/GadgetHtmlAttribute.java
incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/parse/GadgetHtmlNode.java
incubator/shindig/trunk/java/gadgets/src/test/java/org/apache/shindig/gadgets/parse/
incubator/shindig/trunk/java/gadgets/src/test/java/org/apache/shindig/gadgets/parse/GadgetCssDeclarationTest.java
incubator/shindig/trunk/java/gadgets/src/test/java/org/apache/shindig/gadgets/parse/GadgetCssRuleTest.java
incubator/shindig/trunk/java/gadgets/src/test/java/org/apache/shindig/gadgets/parse/GadgetHtmlAttributeTest.java
incubator/shindig/trunk/java/gadgets/src/test/java/org/apache/shindig/gadgets/parse/GadgetHtmlNodeTest.java
Added:
incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/parse/GadgetCssDeclaration.java
URL:
http://svn.apache.org/viewvc/incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/parse/GadgetCssDeclaration.java?rev=686106&view=auto
==============================================================================
---
incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/parse/GadgetCssDeclaration.java
(added)
+++
incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/parse/GadgetCssDeclaration.java
Thu Aug 14 18:48:26 2008
@@ -0,0 +1,72 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations under the License.
+ */
+package org.apache.shindig.gadgets.parse;
+
+/**
+ * Mutable wrapper around a [EMAIL PROTECTED] ParsedCssDeclaration}.
+ * Used by rewriting to manipulate parsed gadget CSS, and
+ * to separate parsing from manipulation code.
+ */
+public class GadgetCssDeclaration {
+ private String name;
+ private String value;
+
+ /**
+ * Construct a mutable attribute out of an immutable parsed one.
+ * @param source Parsed CSS declaration
+ */
+ public GadgetCssDeclaration(ParsedCssDeclaration source) {
+ this.name = source.getName();
+ this.value = source.getValue();
+ }
+
+ /**
+ * Construct a mutable CSS declaration from a name/value pair.
+ * @param name Name of attribute
+ * @param value Value of attribute
+ */
+ public GadgetCssDeclaration(String name, String value) {
+ this.name = name;
+ this.value = value;
+ }
+
+ /**
+ * @return Name of the HTML attribute
+ */
+ public String getName() {
+ return name;
+ }
+
+ /**
+ * @return Value of the HTML attribute
+ */
+ public String getValue() {
+ return value;
+ }
+
+ /**
+ * Only provide an API for setting value. To set
+ * a new attribute a developer can simply create
+ * a new one. To replace, the developer can delete
+ * the existing one before doing so.
+ * @param value New HTML attribute value.
+ */
+ public void setValue(String value) {
+ this.value = value;
+ }
+}
Added:
incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/parse/GadgetCssRule.java
URL:
http://svn.apache.org/viewvc/incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/parse/GadgetCssRule.java?rev=686106&view=auto
==============================================================================
---
incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/parse/GadgetCssRule.java
(added)
+++
incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/parse/GadgetCssRule.java
Thu Aug 14 18:48:26 2008
@@ -0,0 +1,144 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations under the License.
+ */
+package org.apache.shindig.gadgets.parse;
+
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+/**
+ * Mutable wrapper around a [EMAIL PROTECTED] ParsedCssRule}.
+ * Used by rewriting to manipulate parsed gadget CSS, and
+ * to separate parsing from manipulation code.
+ */
+public class GadgetCssRule {
+ private final List<String> selectors;
+ private final Map<String, String> declarations;
+
+ /**
+ * Create a new [EMAIL PROTECTED] GadgetCssRule} from a [EMAIL PROTECTED]
ParsedCssRule}
+ * @param source Parsed CSS rule
+ */
+ public GadgetCssRule(ParsedCssRule source) {
+ this();
+ for (String selector : source.getSelectors()) {
+ addSelector(selector, null);
+ }
+
+ // Last decl with a given key "wins" - duplicates are therefore ignored.
+ for (ParsedCssDeclaration decl : source.getDeclarations()) {
+ setDeclaration(decl.getName(), decl.getValue());
+ }
+ }
+
+ /**
+ * Create a new, blank rule. At least one selector must be added
+ * for the rule to be valid (and serializable).
+ */
+ public GadgetCssRule() {
+ selectors = new LinkedList<String>();
+ declarations = new HashMap<String, String>();
+ }
+
+ /**
+ * Adds a new selector after the provided entry. Selector order in a given
+ * rule is significant in CSS.
+ * @param selector Selector to add (will be automatically trimmed)
+ * @param before Selector key after which to add new, null for list end
+ * @return Whether or not the selector was freshly added
+ */
+ public boolean addSelector(String selector, String before) {
+ selector = selector.trim();
+ int selIx = selectors.indexOf(selector);
+ if (selIx >= 0) {
+ return false;
+ }
+ if (before == null) {
+ return selectors.add(selector);
+ }
+ int befIx = selectors.indexOf(before);
+ if (befIx >= 0) {
+ selectors.add(befIx, selector);
+ } else {
+ selectors.add(selector);
+ }
+ return true;
+ }
+
+ /**
+ * @param selector Selector to remove
+ * @return Whether or not the selector was present and removed
+ */
+ public boolean removeSelector(String selector) {
+ return selectors.remove(selector);
+ }
+
+ /**
+ * @param selector Selector whose presence in the rule to test
+ * @return Whether or not the selector exists in the rule
+ */
+ public boolean hasSelector(String selector) {
+ return selectors.contains(selector);
+ }
+
+ /**
+ * @return Unmodifiable list of selectors
+ */
+ public List<String> getSelectors() {
+ return Collections.unmodifiableList(selectors);
+ }
+
+ /**
+ * Add a declaration by key/value. Key is trimmed.
+ * @param key Declaration key, either new or replaced
+ * @param value Declaration value, either new or replaced
+ */
+ public void setDeclaration(String key, String value) {
+ key = key.trim();
+ declarations.put(key, value);
+ }
+
+ /**
+ * @param key Key for the declaration to remove.
+ * @return Whether or not the declaration existed and was removed
+ */
+ public boolean removeDeclaration(String key) {
+ key = key.trim();
+ return declarations.remove(key) != null;
+ }
+
+ /**
+ * Get a given declaration's value by key.
+ * @param key Key for the declaration
+ * @return Declaration's value, or null if not present
+ */
+ public String getDeclarationValue(String key) {
+ key = key.trim();
+ return declarations.get(key);
+ }
+
+ /**
+ * @return Unmodifiable set of existing declaration keys.
+ */
+ public Set<String> getDeclarationKeys() {
+ return Collections.unmodifiableSet(declarations.keySet());
+ }
+}
Added:
incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/parse/GadgetHtmlAttribute.java
URL:
http://svn.apache.org/viewvc/incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/parse/GadgetHtmlAttribute.java?rev=686106&view=auto
==============================================================================
---
incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/parse/GadgetHtmlAttribute.java
(added)
+++
incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/parse/GadgetHtmlAttribute.java
Thu Aug 14 18:48:26 2008
@@ -0,0 +1,72 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations under the License.
+ */
+package org.apache.shindig.gadgets.parse;
+
+/**
+ * Mutable wrapper around a [EMAIL PROTECTED] ParsedHtmlAttribute}.
+ * Used by rewriting to manipulate a parsed gadget DOM, and
+ * to separate parsing from manipulation code.
+ */
+public class GadgetHtmlAttribute {
+ private String name;
+ private String value;
+
+ /**
+ * Construct a mutable attribute out of an immutable parsed one.
+ * @param source Parsed HTML attribute
+ */
+ public GadgetHtmlAttribute(ParsedHtmlAttribute source) {
+ this.name = source.getName();
+ this.value = source.getValue();
+ }
+
+ /**
+ * Construct a mutable attribute from a name/value pair.
+ * @param name Name of attribute
+ * @param value Value of attribute
+ */
+ public GadgetHtmlAttribute(String name, String value) {
+ this.name = name;
+ this.value = value;
+ }
+
+ /**
+ * @return Name of the HTML attribute
+ */
+ public String getName() {
+ return name;
+ }
+
+ /**
+ * @return Value of the HTML attribute
+ */
+ public String getValue() {
+ return value;
+ }
+
+ /**
+ * Only provide an API for setting value. To set
+ * a new attribute a developer can simply create
+ * a new one. To replace, the developer can delete
+ * the existing one before doing so.
+ * @param value New HTML attribute value.
+ */
+ public void setValue(String value) {
+ this.value = value;
+ }
+}
Added:
incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/parse/GadgetHtmlNode.java
URL:
http://svn.apache.org/viewvc/incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/parse/GadgetHtmlNode.java?rev=686106&view=auto
==============================================================================
---
incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/parse/GadgetHtmlNode.java
(added)
+++
incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/parse/GadgetHtmlNode.java
Thu Aug 14 18:48:26 2008
@@ -0,0 +1,287 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations under the License.
+ */
+package org.apache.shindig.gadgets.parse;
+
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+/**
+ * Mutable wrapper around a [EMAIL PROTECTED] ParsedHtmlNode}.
+ * Used by rewriting to manipulate a parsed gadget DOM, and
+ * to separate parsing from manipulation code. Essentially
+ * a lightweight DOM1-style object.
+ */
+public class GadgetHtmlNode {
+ private final NodeType type;
+ private GadgetHtmlNode parentNode;
+ private String tagName;
+ private Map<String, String> attributes;
+ private List<GadgetHtmlNode> children;
+ private String text;
+
+ private enum NodeType {
+ TAG, TEXT
+ }
+
+ /**
+ * Construct a mutable HTML node from a parsed one.
+ * @param parsed HTML node object from parser.
+ */
+ public GadgetHtmlNode(ParsedHtmlNode parsed) {
+ if (parsed.getText() == null) {
+ // Tag type
+ type = NodeType.TAG;
+ parentNode = null;
+ tagName = parsed.getTagName();
+ attributes = new HashMap<String, String>();
+ for (ParsedHtmlAttribute attrib : parsed.getAttributes()) {
+ setAttribute(attrib.getName(), attrib.getValue());
+ }
+ children = new LinkedList<GadgetHtmlNode>();
+ for (ParsedHtmlNode node: parsed.getChildren()) {
+ appendChild(new GadgetHtmlNode(node));
+ }
+ } else {
+ type = NodeType.TEXT;
+ setText(parsed.getText());
+ }
+ }
+
+ /**
+ * Construct a tag-type HTML node.
+ * @param tagName Tag name for new node, must not be null.
+ * @param attributes Name/value pairs for new attributes, or null if none.
+ */
+ public GadgetHtmlNode(String tag, String[][] attribs) {
+ type = NodeType.TAG;
+ tagName = tag;
+ attributes = new HashMap<String, String>();
+ if (attribs != null) {
+ for (String[] attrib : attribs) {
+ if (attrib == null || attrib.length != 2) {
+ throw new UnsupportedOperationException(
+ "Coding error: Invalid GadgetHtmlNode creation");
+ }
+ setAttribute(attrib[0], attrib[1]);
+ }
+ }
+ children = new LinkedList<GadgetHtmlNode>();
+ }
+
+ /**
+ * Construct a text-type HTML node.
+ * @param text Textual contents of new node.
+ */
+ public GadgetHtmlNode(String text) {
+ type = NodeType.TEXT;
+ setText(text);
+ }
+
+ /**
+ * @return True if the node is text type
+ */
+ public boolean isText() {
+ return type == NodeType.TEXT;
+ }
+
+ /**
+ * @return Tag name for the HTML node.
+ */
+ public String getTagName() {
+ validateNodeType(NodeType.TAG);
+ return tagName;
+ }
+
+ /**
+ * @param newTag New tag name to set for the node
+ * @return True if the tag name was set, false if invalid
+ */
+ public boolean setTagName(String newTag) {
+ validateNodeType(NodeType.TAG);
+ if (tagName != null) {
+ newTag = newTag.trim();
+ if (newTag.matches("[\\w\\-_:]+")) {
+ this.tagName = newTag;
+ return true;
+ }
+ }
+ return false;
+ }
+
+ /**
+ * Retrieve an attribute by key.
+ * @param key Attribute key to look up.
+ * @return Value associated with key, or null if none.
+ */
+ public String getAttributeValue(String key) {
+ validateNodeType(NodeType.TAG);
+ return attributes.get(key);
+ }
+
+ /**
+ * Remove an attribute by key.
+ * @param key Key for attribute to remove.
+ * @return Whether or not an attribute with that key was removed.
+ */
+ public boolean removeAttribute(String key) {
+ validateNodeType(NodeType.TAG);
+ boolean hasBefore = hasAttribute(key);
+ attributes.remove(key);
+ return hasBefore && !hasAttribute(key);
+ }
+
+ /**
+ * Set an attribute's key/value.
+ * @param key Attribute key.
+ * @param value Attribute value.
+ * @return Whether or not the set operation succeeded.
+ */
+ public boolean setAttribute(String key, String value) {
+ validateNodeType(NodeType.TAG);
+ String putKey = validateAttributeKey(key);
+ if (putKey == null) {
+ return false;
+ }
+ attributes.put(putKey, value);
+ return true;
+ }
+
+ /**
+ * @param key Key whose existence to test in the attribute set
+ * @return Whether or not the node has an attribute for the given key
+ */
+ public boolean hasAttribute(String key) {
+ validateNodeType(NodeType.TAG);
+ return attributes.containsKey(key);
+ }
+
+ /**
+ * @return Immutable set of attribute keys.
+ */
+ public Set<String> getAttributeKeys() {
+ validateNodeType(NodeType.TAG);
+ return Collections.unmodifiableSet(attributes.keySet());
+ }
+
+ // DOM-like node management helpers
+ /**
+ * Append a new node to this node's children.
+ * @param node New node to append.
+ */
+ public void appendChild(GadgetHtmlNode node) {
+ insertBefore(node, null);
+ }
+
+ /**
+ * Insert a new node before another given node. If the relative
+ * node is not found or null, insert the new node at the end of
+ * this node's children.
+ * @param node New node to insert.
+ * @param before Node before which to insert [EMAIL PROTECTED] node}.
+ */
+ public void insertBefore(GadgetHtmlNode node, GadgetHtmlNode before) {
+ validateNodeType(NodeType.TAG);
+ node.setParentNode(this);
+ if (before == null) {
+ children.add(node);
+ return;
+ }
+ int befIx = children.indexOf(before);
+ if (befIx >= 0) {
+ children.add(befIx, node);
+ } else {
+ children.add(node);
+ }
+ }
+
+ /**
+ * Remove the given node from the tree.
+ * @param node Node to remove.
+ * @return Whether or not the node was removed.
+ */
+ public boolean removeChild(GadgetHtmlNode node) {
+ validateNodeType(NodeType.TAG);
+
+ // For good measure, dissociate from parent
+ node.setParentNode(null);
+ return children.remove(node);
+ }
+
+ /**
+ * Returns this nodes parent, or null if none exists.
+ * @return
+ */
+ public GadgetHtmlNode getParentNode() {
+ return parentNode;
+ }
+
+ // Internal helper: sets parent for tree-node management
+ private void setParentNode(GadgetHtmlNode parent) {
+ parentNode = parent;
+ }
+
+ /**
+ * Returns an unmodifiable list of current child nodes.
+ * @return
+ */
+ public List<GadgetHtmlNode> getChildren() {
+ validateNodeType(NodeType.TAG);
+ return Collections.unmodifiableList(children);
+ }
+
+ /**
+ * @return Text for this node if text-type.
+ */
+ public String getText() {
+ validateNodeType(NodeType.TEXT);
+ return text;
+ }
+
+ /**
+ * Set new text value for the node.
+ * @param text New text value for the node.
+ */
+ public void setText(String text) {
+ validateNodeType(NodeType.TEXT);
+ this.text = text;
+ }
+
+ // Helper that cleans up and validates an attribute key
+ private String validateAttributeKey(String key) {
+ if (key == null) {
+ return null;
+ }
+ key = key.trim();
+ if (!key.matches("[\\w\\d_\\-:]+")) {
+ return null;
+ }
+ return key;
+ }
+
+ // Helper that enforces correct API usage by type
+ private void validateNodeType(NodeType expected) {
+ if (type != expected) {
+ throw new UnsupportedOperationException("Code error: " +
+ "Attempted " + expected + " operation on node of type " + type);
+ }
+ }
+}
Added:
incubator/shindig/trunk/java/gadgets/src/test/java/org/apache/shindig/gadgets/parse/GadgetCssDeclarationTest.java
URL:
http://svn.apache.org/viewvc/incubator/shindig/trunk/java/gadgets/src/test/java/org/apache/shindig/gadgets/parse/GadgetCssDeclarationTest.java?rev=686106&view=auto
==============================================================================
---
incubator/shindig/trunk/java/gadgets/src/test/java/org/apache/shindig/gadgets/parse/GadgetCssDeclarationTest.java
(added)
+++
incubator/shindig/trunk/java/gadgets/src/test/java/org/apache/shindig/gadgets/parse/GadgetCssDeclarationTest.java
Thu Aug 14 18:48:26 2008
@@ -0,0 +1,52 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations under the License.
+ */
+package org.apache.shindig.gadgets.parse;
+
+import static org.easymock.EasyMock.expect;
+import static org.easymock.classextension.EasyMock.replay;
+import org.easymock.classextension.EasyMock;
+
+import junit.framework.TestCase;
+
+public class GadgetCssDeclarationTest extends TestCase {
+ static ParsedCssDeclaration makeParsedDecl(String name, String value) {
+ ParsedCssDeclaration parsed =
+ EasyMock.createNiceMock(ParsedCssDeclaration.class);
+ expect(parsed.getName()).andReturn(name).anyTimes();
+ expect(parsed.getValue()).andReturn(value).anyTimes();
+ replay(parsed);
+ return parsed;
+ }
+
+ public void testDeclarationCreatedFromParsed() {
+ ParsedCssDeclaration parsed = makeParsedDecl("foo", "bar");
+ GadgetCssDeclaration decl = new GadgetCssDeclaration(parsed);
+ assertEquals("foo", decl.getName());
+ assertEquals("bar", decl.getValue());
+ decl.setValue("baz");
+ assertEquals("baz", decl.getValue());
+ }
+
+ public void testDeclarationCreatedFromRaw() {
+ GadgetHtmlAttribute attrib = new GadgetHtmlAttribute("foo", "bar");
+ assertEquals("foo", attrib.getName());
+ assertEquals("bar", attrib.getValue());
+ attrib.setValue("baz");
+ assertEquals("baz", attrib.getValue());
+ }
+}
Added:
incubator/shindig/trunk/java/gadgets/src/test/java/org/apache/shindig/gadgets/parse/GadgetCssRuleTest.java
URL:
http://svn.apache.org/viewvc/incubator/shindig/trunk/java/gadgets/src/test/java/org/apache/shindig/gadgets/parse/GadgetCssRuleTest.java?rev=686106&view=auto
==============================================================================
---
incubator/shindig/trunk/java/gadgets/src/test/java/org/apache/shindig/gadgets/parse/GadgetCssRuleTest.java
(added)
+++
incubator/shindig/trunk/java/gadgets/src/test/java/org/apache/shindig/gadgets/parse/GadgetCssRuleTest.java
Thu Aug 14 18:48:26 2008
@@ -0,0 +1,139 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations under the License.
+ */
+package org.apache.shindig.gadgets.parse;
+
+import static org.easymock.EasyMock.expect;
+import static org.easymock.classextension.EasyMock.replay;
+import org.easymock.classextension.EasyMock;
+
+import junit.framework.TestCase;
+
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Set;
+
+public class GadgetCssRuleTest extends TestCase {
+ private String[] selectors = { "#id1", " .class1 " };
+ private String[][] decls =
+ { { "color", "blue" }, { " font-size ", "10 em" } };
+
+ private ParsedCssRule makeParsedRule(String[] selectors, String[][] decls) {
+ ParsedCssRule parsedMock = EasyMock.createNiceMock(ParsedCssRule.class);
+
+ List<String> selectorList = new LinkedList<String>();
+ for (String sel : selectors) {
+ selectorList.add(sel);
+ }
+ expect(parsedMock.getSelectors()).andReturn(selectorList).anyTimes();
+
+ List<ParsedCssDeclaration> declList =
+ new LinkedList<ParsedCssDeclaration>();
+ for (String[] decl : decls) {
+ declList.add(
+ GadgetCssDeclarationTest.makeParsedDecl(decl[0], decl[1]));
+ }
+ expect(parsedMock.getDeclarations()).andReturn(declList).anyTimes();
+
+ replay(parsedMock);
+ return parsedMock;
+ }
+
+ public void testCreatedFromParsed() {
+ ParsedCssRule parsed = makeParsedRule(selectors, decls);
+ GadgetCssRule rule = new GadgetCssRule(parsed);
+ helperValidateCssRule(rule);
+ }
+
+ public void testCreatedManually() {
+ GadgetCssRule rule = new GadgetCssRule();
+ assertNotNull(rule.getSelectors());
+ assertEquals(0, rule.getSelectors().size());
+ assertNotNull(rule.getDeclarationKeys());
+ assertEquals(0, rule.getDeclarationKeys().size());
+ for (String sel : selectors) {
+ assertTrue(rule.addSelector(sel, null));
+ }
+ for (String[] decl : decls) {
+ rule.setDeclaration(decl[0], decl[1]);
+ }
+ helperValidateCssRule(rule);
+ }
+
+ private void helperValidateCssRule(GadgetCssRule rule) {
+ assertTrue(rule.hasSelector("#id1"));
+ assertTrue(rule.hasSelector(".class1"));
+ assertFalse(rule.hasSelector(" .class1 "));
+ assertFalse(rule.hasSelector("body"));
+
+ List<String> seleList = rule.getSelectors();
+ assertNotNull(seleList);
+ assertEquals(2, seleList.size());
+ assertEquals("#id1", seleList.get(0));
+ assertEquals(".class1", seleList.get(1));
+
+ assertTrue(rule.removeSelector(".class1"));
+ assertTrue(rule.hasSelector("#id1"));
+ assertFalse(rule.hasSelector(".class1"));
+ assertFalse(rule.removeSelector("nonexistent"));
+
+ assertTrue(rule.addSelector(" .new ", null));
+ assertTrue(rule.hasSelector("#id1"));
+ assertTrue(rule.hasSelector(".new"));
+ assertFalse(rule.hasSelector(".class1"));
+ assertFalse(rule.addSelector(".new", null));
+
+ List<String> addSeleList = rule.getSelectors();
+ assertNotNull(addSeleList);
+ assertEquals(2, addSeleList.size());
+ assertEquals("#id1", addSeleList.get(0));
+ assertEquals(".new", addSeleList.get(1));
+
+ assertTrue(rule.addSelector(".middle", ".new"));
+ List<String> injectSeleList = rule.getSelectors();
+ assertNotNull(injectSeleList);
+ assertEquals(3, injectSeleList.size());
+ assertEquals("#id1", injectSeleList.get(0));
+ assertEquals(".middle", injectSeleList.get(1));
+ assertEquals(".new", injectSeleList.get(2));
+ assertFalse(rule.addSelector(".middle", ".new"));
+
+ Set<String> declKeys = rule.getDeclarationKeys();
+ assertEquals(2, declKeys.size());
+ assertTrue(declKeys.contains("color"));
+ assertEquals("blue", rule.getDeclarationValue("color"));
+ assertTrue(declKeys.contains("font-size"));
+ assertEquals("10 em", rule.getDeclarationValue("font-size"));
+
+ assertTrue(rule.removeDeclaration("font-size"));
+ Set<String> removeDeclKeys = rule.getDeclarationKeys();
+ assertEquals(1, removeDeclKeys.size());
+ assertTrue(removeDeclKeys.contains("color"));
+ assertEquals("blue", rule.getDeclarationValue("color"));
+ assertFalse(removeDeclKeys.contains("font-size"));
+ assertFalse(rule.removeDeclaration("font-size"));
+
+ rule.setDeclaration("color", "green");
+ assertEquals("green", rule.getDeclarationValue("color"));
+ assertEquals(1, rule.getDeclarationKeys().size());
+
+ rule.setDeclaration("font", "verdana");
+ assertEquals(2, rule.getDeclarationKeys().size());
+ assertEquals("green", rule.getDeclarationValue("color"));
+ assertEquals("verdana", rule.getDeclarationValue("font"));
+ }
+}
Added:
incubator/shindig/trunk/java/gadgets/src/test/java/org/apache/shindig/gadgets/parse/GadgetHtmlAttributeTest.java
URL:
http://svn.apache.org/viewvc/incubator/shindig/trunk/java/gadgets/src/test/java/org/apache/shindig/gadgets/parse/GadgetHtmlAttributeTest.java?rev=686106&view=auto
==============================================================================
---
incubator/shindig/trunk/java/gadgets/src/test/java/org/apache/shindig/gadgets/parse/GadgetHtmlAttributeTest.java
(added)
+++
incubator/shindig/trunk/java/gadgets/src/test/java/org/apache/shindig/gadgets/parse/GadgetHtmlAttributeTest.java
Thu Aug 14 18:48:26 2008
@@ -0,0 +1,52 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations under the License.
+ */
+package org.apache.shindig.gadgets.parse;
+
+import static org.easymock.EasyMock.expect;
+import static org.easymock.classextension.EasyMock.replay;
+
+import org.easymock.classextension.EasyMock;
+
+import junit.framework.TestCase;
+
+public class GadgetHtmlAttributeTest extends TestCase {
+ static ParsedHtmlAttribute makeParsedAttribute(String name, String value) {
+ ParsedHtmlAttribute parsed =
EasyMock.createNiceMock(ParsedHtmlAttribute.class);
+ expect(parsed.getName()).andReturn(name).anyTimes();
+ expect(parsed.getValue()).andReturn(value).anyTimes();
+ replay(parsed);
+ return parsed;
+ }
+
+ public void testAttributeCreatedFromParsed() {
+ ParsedHtmlAttribute parsed = makeParsedAttribute("foo", "bar");
+ GadgetHtmlAttribute attrib = new GadgetHtmlAttribute(parsed);
+ assertEquals("foo", attrib.getName());
+ assertEquals("bar", attrib.getValue());
+ attrib.setValue("baz");
+ assertEquals("baz", attrib.getValue());
+ }
+
+ public void testAttributeCreatedFromRaw() {
+ GadgetHtmlAttribute attrib = new GadgetHtmlAttribute("foo", "bar");
+ assertEquals("foo", attrib.getName());
+ assertEquals("bar", attrib.getValue());
+ attrib.setValue("baz");
+ assertEquals("baz", attrib.getValue());
+ }
+}
Added:
incubator/shindig/trunk/java/gadgets/src/test/java/org/apache/shindig/gadgets/parse/GadgetHtmlNodeTest.java
URL:
http://svn.apache.org/viewvc/incubator/shindig/trunk/java/gadgets/src/test/java/org/apache/shindig/gadgets/parse/GadgetHtmlNodeTest.java?rev=686106&view=auto
==============================================================================
---
incubator/shindig/trunk/java/gadgets/src/test/java/org/apache/shindig/gadgets/parse/GadgetHtmlNodeTest.java
(added)
+++
incubator/shindig/trunk/java/gadgets/src/test/java/org/apache/shindig/gadgets/parse/GadgetHtmlNodeTest.java
Thu Aug 14 18:48:26 2008
@@ -0,0 +1,421 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations under the License.
+ */
+package org.apache.shindig.gadgets.parse;
+
+import static org.easymock.EasyMock.expect;
+import static org.easymock.classextension.EasyMock.replay;
+
+import org.easymock.classextension.EasyMock;
+
+import junit.framework.TestCase;
+
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Set;
+
+public class GadgetHtmlNodeTest extends TestCase {
+ private ParsedHtmlNode makeTagNodeFromParsed(
+ String tag, String[][] attribs, ParsedHtmlNode[] children) {
+ ParsedHtmlNode parsed = EasyMock.createNiceMock(ParsedHtmlNode.class);
+ expect(parsed.getTagName()).andReturn(tag).anyTimes();
+ List<ParsedHtmlAttribute> attributes = new
LinkedList<ParsedHtmlAttribute>();
+ if (attribs != null) {
+ for (String[] attrib : attribs) {
+ attributes.add(
+ GadgetHtmlAttributeTest.makeParsedAttribute(attrib[0], attrib[1]));
+ }
+ }
+ expect(parsed.getAttributes()).andReturn(attributes).anyTimes();
+ List<ParsedHtmlNode> childNodes = new LinkedList<ParsedHtmlNode>();
+ if (children != null) {
+ for (ParsedHtmlNode child : children) {
+ childNodes.add(child);
+ }
+ }
+ expect(parsed.getChildren()).andReturn(childNodes).anyTimes();
+ expect(parsed.getText()).andReturn(null).anyTimes();
+ replay(parsed);
+ return parsed;
+ }
+
+ private GadgetHtmlNode makeTagNodeFromNew(
+ String tag, String[][] attribs, GadgetHtmlNode[] children) {
+ GadgetHtmlNode node = new GadgetHtmlNode(tag, attribs);
+ if (children != null) {
+ for (GadgetHtmlNode child : children) {
+ node.appendChild(child);
+ }
+ }
+ return node;
+ }
+
+ private ParsedHtmlNode makeTextNodeFromParsed(String text) {
+ ParsedHtmlNode parsed = EasyMock.createNiceMock(ParsedHtmlNode.class);
+ expect(parsed.getText()).andReturn(text).anyTimes();
+ expect(parsed.getTagName()).andReturn(null).anyTimes();
+ expect(parsed.getAttributes()).andReturn(null).anyTimes();
+ expect(parsed.getChildren()).andReturn(null).anyTimes();
+ replay(parsed);
+ return parsed;
+ }
+
+ private GadgetHtmlNode makeTextNodeFromNew(String text) {
+ return new GadgetHtmlNode(text);
+ }
+
+ // Test: tag tree
+ private static String[][] tagTreeAttribs = { { "id", "foo" }, { "name",
"bar" } };
+ public void testTagTreeCreatedFromParsedGetters() {
+ ParsedHtmlNode[] parsedKids = {
+ makeTextNodeFromParsed("content"),
+ makeTagNodeFromParsed("span", null, null)
+ };
+ ParsedHtmlNode parsed = makeTagNodeFromParsed("div", tagTreeAttribs,
parsedKids);
+ GadgetHtmlNode node = new GadgetHtmlNode(parsed);
+ validateTagTreeGetters(node);
+ }
+
+ public void testTagTreeCreatedByNewGetters() {
+ GadgetHtmlNode[] children = {
+ makeTextNodeFromNew("content"),
+ makeTagNodeFromNew("span", null, null)
+ };
+ GadgetHtmlNode node = makeTagNodeFromNew("div", tagTreeAttribs, children);
+ validateTagTreeGetters(node);
+ }
+
+ private void validateTagTreeGetters(GadgetHtmlNode node) {
+ assertFalse(node.isText());
+ assertEquals("div", node.getTagName());
+ assertNull(node.getParentNode());
+
+ Set<String> attribKeys = node.getAttributeKeys();
+ assertEquals(2, attribKeys.size());
+ assertTrue(attribKeys.contains("id"));
+ assertTrue(attribKeys.contains("name"));
+ assertTrue(node.hasAttribute("id"));
+ assertEquals("foo", node.getAttributeValue("id"));
+ assertTrue(node.hasAttribute("name"));
+ assertEquals("bar", node.getAttributeValue("name"));
+
+ List<GadgetHtmlNode> children = node.getChildren();
+ assertEquals(2, children.size());
+
+ GadgetHtmlNode textChild = children.get(0);
+ assertTrue(textChild.isText());
+ assertEquals("content", textChild.getText());
+ assertSame(node, textChild.getParentNode());
+
+ GadgetHtmlNode tagChild = children.get(1);
+ assertFalse(tagChild.isText());
+ assertEquals("span", tagChild.getTagName());
+ assertNotNull(tagChild.getAttributeKeys());
+ assertEquals(0, tagChild.getAttributeKeys().size());
+ assertNotNull(tagChild.getChildren());
+ assertEquals(0, tagChild.getChildren().size());
+ assertSame(node, tagChild.getParentNode());
+ }
+
+ // Test: basic getters
+ private static String textGetterContent = "content";
+ public void testTextCreatedFromParsedGetters() {
+ ParsedHtmlNode parsed = makeTextNodeFromParsed(textGetterContent);
+ GadgetHtmlNode node = new GadgetHtmlNode(parsed);
+ validateTextGetters(node);
+ }
+
+ public void testTextCreatedByNewGetters() {
+ validateTextGetters(makeTextNodeFromNew(textGetterContent));
+ }
+
+ private void validateTextGetters(GadgetHtmlNode node) {
+ assertTrue(node.isText());
+ assertEquals("content", node.getText());
+ assertNull(node.getParentNode());
+ }
+
+ // Test: tag name setter
+ public void testTagCreatedFromParsedTagSetter() {
+ ParsedHtmlNode parsed = makeTagNodeFromParsed("div", null, null);
+ GadgetHtmlNode node = new GadgetHtmlNode(parsed);
+ validateTagNameSetter(node);
+ }
+
+ public void testTagCreatedFromNewTagSetter() {
+ validateTagNameSetter(makeTagNodeFromNew("div", null, null));
+ }
+
+ private void validateTagNameSetter(GadgetHtmlNode node) {
+ assertFalse(node.isText());
+ assertEquals("div", node.getTagName());
+ node.setTagName("span");
+ assertEquals("span", node.getTagName());
+ }
+
+ // Test: tag attribute manipulation
+ private static String[][] tagManipAttribs = { { "id", "foo" } };
+ public void testTagCreatedFromParsedAttributeManipulation() {
+ ParsedHtmlNode parsed =
+ makeTagNodeFromParsed("div", tagManipAttribs, null);
+ GadgetHtmlNode node = new GadgetHtmlNode(parsed);
+ validateTagAttributeManipulation(node);
+ }
+
+ public void testTagCreatedFromNewAttributeManipulation() {
+ validateTagAttributeManipulation(
+ makeTagNodeFromNew("div", tagManipAttribs, null));
+ }
+
+ private void validateTagAttributeManipulation(GadgetHtmlNode node) {
+ assertFalse(node.isText());
+
+ Set<String> origKeys = node.getAttributeKeys();
+ assertNotNull(origKeys);
+ assertEquals(1, origKeys.size());
+ assertTrue(origKeys.contains("id"));
+ assertTrue(node.hasAttribute("id"));
+ assertEquals("foo", node.getAttributeValue("id"));
+
+ // Set existing key
+ node.setAttribute("id", "bar");
+ Set<String> barKeys = node.getAttributeKeys();
+ assertNotNull(barKeys);
+ assertEquals(1, barKeys.size());
+ assertTrue(barKeys.contains("id"));
+ assertTrue(node.hasAttribute("id"));
+ assertEquals("bar", node.getAttributeValue("id"));
+
+ // Set existing key to null: null's perfectly valid
+ // Also set with whitespace padding to test that bit
+ assertTrue(node.setAttribute("id", null));
+ Set<String> nullKeys = node.getAttributeKeys();
+ assertNotNull(nullKeys);
+ assertEquals(1, nullKeys.size());
+ assertTrue(nullKeys.contains("id"));
+ assertTrue(node.hasAttribute("id"));
+ assertEquals(null, node.getAttributeValue("id"));
+
+ // Remove id key
+ assertTrue(node.removeAttribute("id"));
+ assertFalse(node.removeAttribute("id"));
+ Set<String> noKeys = node.getAttributeKeys();
+ assertNotNull(noKeys);
+ assertEquals(0, noKeys.size());
+ assertFalse(node.hasAttribute("id"));
+
+ // Add some new key
+ assertTrue(node.setAttribute("name", "value"));
+ Set<String> newKeys = node.getAttributeKeys();
+ assertNotNull(newKeys);
+ assertEquals(1, newKeys.size());
+ assertTrue(node.hasAttribute("name"));
+ assertEquals("value", node.getAttributeValue("name"));
+ assertTrue(node.removeAttribute("name"));
+ assertFalse(node.removeAttribute("name"));
+ }
+
+ // Test: tag node manipulation
+ // We don't do created-from-new testing since html node creation types are
+ // already mixed here.
+ public void testTagCreatedFromParsedNodeManipulation() {
+ ParsedHtmlNode[] kidNodes = { makeTextNodeFromParsed("content") };
+ ParsedHtmlNode parsed = makeTagNodeFromParsed("div", null, kidNodes);
+ GadgetHtmlNode parentNode = new GadgetHtmlNode(parsed);
+
+ // Sanity check on created child
+ List<GadgetHtmlNode> initialChildren = parentNode.getChildren();
+ assertNotNull(initialChildren);
+ assertEquals(1, initialChildren.size());
+ GadgetHtmlNode textNode = initialChildren.get(0);
+ assertTrue(textNode.isText());
+ assertSame(parentNode, textNode.getParentNode());
+
+ // appendChild
+ GadgetHtmlNode afterNode = new
GadgetHtmlNode(makeTagNodeFromParsed("after", null, null));
+ parentNode.appendChild(afterNode);
+ List<GadgetHtmlNode> appendKids = parentNode.getChildren();
+ assertNotNull(appendKids);
+ assertEquals(2, appendKids.size());
+ assertSame(textNode, appendKids.get(0));
+ assertSame(afterNode, appendKids.get(1));
+ assertSame(parentNode, textNode.getParentNode());
+ assertSame(parentNode, afterNode.getParentNode());
+
+ // insertBefore
+ GadgetHtmlNode beforeNode = new
GadgetHtmlNode(makeTagNodeFromParsed("before", null, null));
+ parentNode.insertBefore(beforeNode, textNode);
+ List<GadgetHtmlNode> insertKids = parentNode.getChildren();
+ assertNotNull(insertKids);
+ assertEquals(3, insertKids.size());
+ assertSame(beforeNode, insertKids.get(0));
+ assertSame(textNode, insertKids.get(1));
+ assertSame(afterNode, insertKids.get(2));
+ assertSame(parentNode, beforeNode.getParentNode());
+ assertSame(parentNode, textNode.getParentNode());
+ assertSame(parentNode, afterNode.getParentNode());
+
+ // remove before and text, leaving only after
+ assertTrue(parentNode.removeChild(beforeNode));
+ assertFalse(parentNode.removeChild(beforeNode));
+ assertTrue(parentNode.removeChild(textNode));
+ assertFalse(parentNode.removeChild(textNode));
+ assertNull(beforeNode.getParentNode());
+ assertNull(textNode.getParentNode());
+ List<GadgetHtmlNode> remainingKids = parentNode.getChildren();
+ assertNotNull(remainingKids);
+ assertEquals(1, remainingKids.size());
+ assertSame(parentNode, afterNode.getParentNode());
+ assertSame(afterNode, remainingKids.get(0));
+ }
+
+ // Test: text setter
+ public void testTextCreatedFromParsedTextSetter() {
+ ParsedHtmlNode parsed = makeTextNodeFromParsed("content");
+ GadgetHtmlNode node = new GadgetHtmlNode(parsed);
+ validateTextSetter(node);
+ }
+
+ public void tesetTextCreatedFromNewTextSetter() {
+ validateTextSetter(makeTextNodeFromNew("content"));
+ }
+
+ private void validateTextSetter(GadgetHtmlNode node) {
+ assertTrue(node.isText());
+ assertEquals("content", node.getText());
+ node.setText("new content");
+ assertEquals("new content", node.getText());
+ }
+
+ // Test: text-node API limitation
+ public void testTagsFromParsedCantUseTextApis() {
+ validateTagsCantUseTextApis(
+ new GadgetHtmlNode(makeTagNodeFromParsed("tag", null, null)));
+ }
+
+ public void testTagsFromNewCantUseTextApis() {
+ validateTagsCantUseTextApis(makeTagNodeFromNew("tag", null, null));
+ }
+
+ private void validateTagsCantUseTextApis(GadgetHtmlNode tagNode) {
+ assertFalse(tagNode.isText());
+
+ try {
+ tagNode.getText();
+ fail("Tag nodes shouldn't be able to use getText()");
+ } catch (UnsupportedOperationException e) {
+ // Expected condition
+ }
+
+ try {
+ tagNode.setText("foo");
+ fail("Tag nodes shouldn't be able to use setText()");
+ } catch (UnsupportedOperationException e) {
+ // Expected condition
+ }
+ }
+
+ // Test: tag-node API limitation
+ public void testTextFromParsedCantUseTagsApis() {
+ validateTextCantUseTagsApis(new
GadgetHtmlNode(makeTextNodeFromParsed("content")));
+ }
+
+ public void testTextFromNewCantUseTagsApis() {
+ validateTextCantUseTagsApis(makeTextNodeFromNew("content"));
+ }
+
+ private void validateTextCantUseTagsApis(GadgetHtmlNode textNode) {
+ assertTrue(textNode.isText());
+
+ try {
+ textNode.appendChild(null);
+ fail("Text nodes shouldn't be able to use appendChild()");
+ } catch (UnsupportedOperationException e) {
+ // Expected condition
+ }
+
+ try {
+ textNode.getAttributeKeys();
+ fail("Text nodes shouldn't be able to use getAttributeKeys()");
+ } catch (UnsupportedOperationException e) {
+ // Expected condition
+ }
+
+ try {
+ textNode.getAttributeValue("foo");
+ fail("Text nodes shouldn't be able to use getAttributeValue()");
+ } catch (UnsupportedOperationException e) {
+ // Expected condition
+ }
+
+ try {
+ textNode.getChildren();
+ fail("Text nodes shouldn't be able to use getChildren()");
+ } catch (UnsupportedOperationException e) {
+ // Expected condition
+ }
+
+ try {
+ textNode.getTagName();
+ fail("Text nodes shouldn't be able to use getTagName()");
+ } catch (UnsupportedOperationException e) {
+ // Expected condition
+ }
+
+ try {
+ textNode.hasAttribute("foo");
+ fail("Text nodes shouldn't be able to use hasAttribute()");
+ } catch (UnsupportedOperationException e) {
+ // Expected condition
+ }
+
+ try {
+ textNode.insertBefore(null, null);
+ fail("Text nodes shouldn't be able to use insertBefore()");
+ } catch (UnsupportedOperationException e) {
+ // Expected condition
+ }
+
+ try {
+ textNode.removeAttribute("foo");
+ fail("Text nodes shouldn't be able to use removeAttribute()");
+ } catch (UnsupportedOperationException e) {
+ // Expected condition
+ }
+
+ try {
+ textNode.removeChild(null);
+ fail("Text nodes shouldn't be able to use removeChild()");
+ } catch (UnsupportedOperationException e) {
+ // Expected condition
+ }
+
+ try {
+ textNode.setAttribute("id", "foo");
+ fail("Text nodes shouldn't be able to use setAttribute()");
+ } catch (UnsupportedOperationException e) {
+ // Expected condition
+ }
+
+ try {
+ textNode.setTagName("div");
+ fail("Text nodes shouldn't be able to use setTagName()");
+ } catch (UnsupportedOperationException e) {
+ // Expected condition
+ }
+ }
+}