michael@0: /* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ michael@0: /* This Source Code Form is subject to the terms of the Mozilla Public michael@0: * License, v. 2.0. If a copy of the MPL was not distributed with this michael@0: * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ michael@0: michael@0: function run_test() michael@0: { michael@0: /* michael@0: * NOTE: [i] is not allowed in this test, since it's done via classinfo and michael@0: * we don't have that in xpcshell; the workaround is item(i). Suck. michael@0: */ michael@0: init(); michael@0: michael@0: test_isEqualNode_setAttribute(); michael@0: test_isEqualNode_clones(); michael@0: test_isEqualNode_variety(); michael@0: test_isEqualNode_normalization(); michael@0: test_isEqualNode_whitespace(); michael@0: test_isEqualNode_namespaces(); michael@0: test_isEqualNode_wholeDoc(); michael@0: michael@0: // XXX should Node.isEqualNode(null) throw or return false? michael@0: //test_isEqualNode_null(); michael@0: michael@0: } michael@0: michael@0: // TEST CODE michael@0: michael@0: var doc, root; // cache for use in all tests michael@0: michael@0: function init() michael@0: { michael@0: doc = ParseFile("isequalnode_data.xml"); michael@0: root = doc.documentElement; michael@0: } michael@0: michael@0: function test_isEqualNode_setAttribute() michael@0: { michael@0: // NOTE: 0, 2 are whitespace michael@0: var test1 = doc.getElementById("test_setAttribute"); michael@0: var node1 = test1.childNodes.item(1); michael@0: var node2 = test1.childNodes.item(3); michael@0: michael@0: check_eq_nodes(node1, node2); michael@0: michael@0: michael@0: el(node1).setAttribute("bar", "baz"); michael@0: check_neq_nodes(node1, node2); michael@0: michael@0: el(node2).setAttribute("bar", "baz"); michael@0: check_eq_nodes(node1, node2); michael@0: michael@0: michael@0: // the null namespace is equivalent to no namespace -- section 1.3.3 michael@0: // (XML Namespaces) of DOM 3 Core michael@0: node1.setAttributeNS(null, "quux", "17"); michael@0: check_neq_nodes(node1, node2); michael@0: michael@0: node2.setAttribute("quux", "17"); michael@0: check_eq_nodes(node1, node2); michael@0: michael@0: michael@0: node2.setAttributeNS("http://mozilla.org/", "seamonkey", "rheet"); michael@0: check_neq_nodes(node1, node2); michael@0: michael@0: node1.setAttribute("seamonkey", "rheet"); michael@0: check_neq_nodes(node1, node2); michael@0: michael@0: node1.setAttributeNS("http://mozilla.org/", "seamonkey", "rheet"); michael@0: check_neq_nodes(node1, node2); michael@0: michael@0: // this overwrites the namespaced "seamonkey" attribute added to node2 michael@0: // earlier, because this simply sets whatever attribute has the fully michael@0: // qualified name "seamonkey" (the setAttributeNS attribute string wasn't michael@0: // prefixed) -- consequently, node1 and node2 are still unequal michael@0: node2.setAttribute("seamonkey", "rheet"); michael@0: check_neq_nodes(node1, node2); michael@0: } michael@0: michael@0: function test_isEqualNode_clones() michael@0: { michael@0: // tests all elements and attributes in the document michael@0: var all_elts = doc.getElementsByTagName("*"); michael@0: for (var i = 0; i < all_elts.length; i++) michael@0: { michael@0: var elt = el(all_elts.item(i)); michael@0: check_eq_nodes(elt, elt.cloneNode(true)); michael@0: michael@0: var attrs = elt.attributes; michael@0: for (var j = 0; j < attrs.length; j++) michael@0: { michael@0: var attr = attrs.item(j); michael@0: check_eq_nodes(attr, attr.cloneNode(true)); michael@0: } michael@0: } michael@0: michael@0: var elm = doc.createElement("foo"); michael@0: check_eq_nodes(elm, elm.cloneNode(true)); michael@0: check_eq_nodes(elm, elm.cloneNode(false)); michael@0: michael@0: elm.setAttribute("fiz", "eit"); michael@0: check_eq_nodes(elm, elm.cloneNode(true)); michael@0: check_eq_nodes(elm, elm.cloneNode(false)); michael@0: michael@0: elm.setAttributeNS("http://example.com/", "trendoid", "arthroscope"); michael@0: check_eq_nodes(elm, elm.cloneNode(true)); michael@0: check_eq_nodes(elm, elm.cloneNode(false)); michael@0: michael@0: var elm2 = elm.cloneNode(true); michael@0: check_eq_nodes(elm, elm2); michael@0: michael@0: const TEXT = "fetishist"; michael@0: michael@0: elm.textContent = TEXT; michael@0: check_neq_nodes(elm, elm2); michael@0: michael@0: check_neq_nodes(elm, elm.cloneNode(false)); michael@0: check_eq_nodes(elm, elm.cloneNode(true)); michael@0: michael@0: elm2.appendChild(doc.createTextNode(TEXT)); michael@0: check_eq_nodes(elm, elm2); michael@0: michael@0: var att = doc.createAttribute("bar"); michael@0: check_eq_nodes(att, att.cloneNode(true)); michael@0: check_eq_nodes(att, att.cloneNode(false)); michael@0: } michael@0: michael@0: function test_isEqualNode_variety() michael@0: { michael@0: const nodes = michael@0: [ michael@0: doc.createElement("foo"), michael@0: doc.createElementNS("http://example.com/", "foo"), michael@0: doc.createElementNS("http://example.org/", "foo"), michael@0: doc.createElementNS("http://example.com/", "FOO"), michael@0: doc.createAttribute("foo", "href='biz'"), michael@0: doc.createAttributeNS("http://example.com/", "foo", "href='biz'"), michael@0: doc.createTextNode("foo"), michael@0: doc.createTextNode(" "), michael@0: doc.createTextNode(" "), michael@0: doc.createComment("foo"), michael@0: doc.createProcessingInstruction("foo", "href='biz'"), michael@0: doc.implementation.createDocumentType("foo", "href='biz'", ""), michael@0: doc.implementation.createDocument("http://example.com/", "foo", null), michael@0: doc.createDocumentFragment() michael@0: ]; michael@0: michael@0: for (var i = 0; i < nodes.length; i++) michael@0: { michael@0: for (var j = i; j < nodes.length; j++) michael@0: { michael@0: if (i == j) michael@0: check_eq_nodes(nodes[i], nodes[j]); michael@0: else michael@0: check_neq_nodes(nodes[i], nodes[j]); michael@0: } michael@0: } michael@0: } michael@0: michael@0: function test_isEqualNode_normalization() michael@0: { michael@0: var norm = doc.getElementById("test_normalization"); michael@0: var node1 = norm.childNodes.item(1); michael@0: var node2 = norm.childNodes.item(3); michael@0: michael@0: check_eq_nodes(node1, node2); michael@0: michael@0: node1.appendChild(doc.createTextNode("")); michael@0: check_neq_nodes(node1, node2); michael@0: michael@0: node1.normalize(); michael@0: check_eq_nodes(node1, node2); michael@0: michael@0: node2.appendChild(doc.createTextNode("fun")); michael@0: node2.appendChild(doc.createTextNode("ctor")); michael@0: node1.appendChild(doc.createTextNode("functor")); michael@0: check_neq_nodes(node1, node2); michael@0: michael@0: node1.normalize(); michael@0: check_neq_nodes(node1, node2); michael@0: michael@0: node2.normalize(); michael@0: check_eq_nodes(node1, node2); michael@0: michael@0: // reset michael@0: while (node1.hasChildNodes()) michael@0: node1.removeChild(node1.childNodes.item(0)); michael@0: while (node2.hasChildNodes()) michael@0: node2.removeChild(node2.childNodes.item(0)); michael@0: michael@0: // attribute normalization testing michael@0: michael@0: var at1 = doc.createAttribute("foo"); michael@0: var at2 = doc.createAttribute("foo"); michael@0: check_eq_nodes(at1, at2); michael@0: michael@0: // Attr.appendChild isn't implemented yet (bug 56758), so don't run this yet michael@0: if (false) michael@0: { michael@0: at1.appendChild(doc.createTextNode("rasp")); michael@0: at2.appendChild(doc.createTextNode("rasp")); michael@0: check_eq_nodes(at1, at2); michael@0: michael@0: at1.appendChild(doc.createTextNode("")); michael@0: check_neq_nodes(at1, at2); michael@0: michael@0: at1.normalize(); michael@0: check_eq_nodes(at1, at2); michael@0: michael@0: at1.appendChild(doc.createTextNode("berry")); michael@0: check_neq_nodes(at1, at2); michael@0: michael@0: at2.appendChild(doc.createTextNode("ber")); michael@0: check_neq_nodes(at1, at2); michael@0: michael@0: at2.appendChild(doc.createTextNode("ry")); michael@0: check_neq_nodes(at1, at2); michael@0: michael@0: at1.normalize(); michael@0: check_neq_nodes(at1, at2); michael@0: michael@0: at2.normalize(); michael@0: check_eq_nodes(at1, at2); michael@0: } michael@0: michael@0: node1.setAttributeNode(at1); michael@0: check_neq_nodes(node1, node2); michael@0: michael@0: node2.setAttributeNode(at2); michael@0: check_eq_nodes(node1, node2); michael@0: michael@0: var n1text1 = doc.createTextNode("ratfink"); michael@0: var n1elt = doc.createElement("fruitcake"); michael@0: var n1text2 = doc.createTextNode("hydrospanner"); michael@0: michael@0: node1.appendChild(n1text1); michael@0: node1.appendChild(n1elt); michael@0: node1.appendChild(n1text2); michael@0: michael@0: check_neq_nodes(node1, node2); michael@0: michael@0: var n2text1a = doc.createTextNode("rat"); michael@0: var n2text1b = doc.createTextNode("fink"); michael@0: var n2elt = doc.createElement("fruitcake"); michael@0: var n2text2 = doc.createTextNode("hydrospanner"); michael@0: michael@0: node2.appendChild(n2text1b); michael@0: node2.appendChild(n2elt); michael@0: node2.appendChild(n2text2); michael@0: check_neq_nodes(node1, node2); michael@0: michael@0: node2.insertBefore(n2text1a, n2text1b); michael@0: check_neq_nodes(node1, node2); michael@0: michael@0: var tmp_node1 = node1.cloneNode(true); michael@0: tmp_node1.normalize(); michael@0: var tmp_node2 = node2.cloneNode(true); michael@0: tmp_node2.normalize(); michael@0: check_eq_nodes(tmp_node1, tmp_node2); michael@0: michael@0: n2elt.appendChild(doc.createTextNode("")); michael@0: check_neq_nodes(node1, node2); michael@0: michael@0: tmp_node1 = node1.cloneNode(true); michael@0: tmp_node1.normalize(); michael@0: tmp_node2 = node2.cloneNode(true); michael@0: tmp_node2.normalize(); michael@0: check_eq_nodes(tmp_node1, tmp_node2); michael@0: michael@0: var typeText1 = doc.createTextNode("type"); michael@0: n2elt.appendChild(typeText1); michael@0: tmp_node1 = node1.cloneNode(true); michael@0: tmp_node1.normalize(); michael@0: tmp_node2 = node2.cloneNode(true); michael@0: tmp_node2.normalize(); michael@0: check_neq_nodes(tmp_node1, tmp_node2); michael@0: michael@0: n1elt.appendChild(doc.createTextNode("typedef")); michael@0: tmp_node1 = node1.cloneNode(true); michael@0: tmp_node1.normalize(); michael@0: tmp_node2 = node2.cloneNode(true); michael@0: tmp_node2.normalize(); michael@0: check_neq_nodes(tmp_node1, tmp_node2); michael@0: check_neq_nodes(n1elt, n2elt); michael@0: michael@0: var typeText2 = doc.createTextNode("def"); michael@0: n2elt.appendChild(typeText2); michael@0: tmp_node1 = node1.cloneNode(true); michael@0: tmp_node1.normalize(); michael@0: tmp_node2 = node2.cloneNode(true); michael@0: tmp_node2.normalize(); michael@0: check_eq_nodes(tmp_node1, tmp_node2); michael@0: check_neq_nodes(node1, node2); michael@0: michael@0: n2elt.insertBefore(doc.createTextNode(""), typeText2); michael@0: check_neq_nodes(node1, node2); michael@0: michael@0: n2elt.insertBefore(doc.createTextNode(""), typeText2); michael@0: check_neq_nodes(node1, node2); michael@0: michael@0: n2elt.insertBefore(doc.createTextNode(""), typeText1); michael@0: check_neq_nodes(node1, node2); michael@0: michael@0: node1.normalize(); michael@0: node2.normalize(); michael@0: check_eq_nodes(node1, node2); michael@0: } michael@0: michael@0: function test_isEqualNode_whitespace() michael@0: { michael@0: equality_check_kids("test_pi1", true); michael@0: equality_check_kids("test_pi2", true); michael@0: equality_check_kids("test_pi3", false); michael@0: equality_check_kids("test_pi4", true); michael@0: equality_check_kids("test_pi5", true); michael@0: michael@0: equality_check_kids("test_elt1", false); michael@0: equality_check_kids("test_elt2", false); michael@0: equality_check_kids("test_elt3", true); michael@0: equality_check_kids("test_elt4", false); michael@0: equality_check_kids("test_elt5", false); michael@0: michael@0: equality_check_kids("test_comment1", true); michael@0: equality_check_kids("test_comment2", false); michael@0: equality_check_kids("test_comment3", false); michael@0: equality_check_kids("test_comment4", true); michael@0: michael@0: equality_check_kids("test_text1", true); michael@0: equality_check_kids("test_text2", false); michael@0: equality_check_kids("test_text3", false); michael@0: michael@0: equality_check_kids("test_cdata1", false); michael@0: equality_check_kids("test_cdata2", true); michael@0: equality_check_kids("test_cdata3", false); michael@0: equality_check_kids("test_cdata4", false); michael@0: equality_check_kids("test_cdata5", false); michael@0: } michael@0: michael@0: function test_isEqualNode_namespaces() michael@0: { michael@0: equality_check_kids("test_ns1", false); michael@0: equality_check_kids("test_ns2", false); michael@0: michael@0: // XXX want more tests here! michael@0: } michael@0: michael@0: function test_isEqualNode_null() michael@0: { michael@0: check_neq_nodes(doc, null); michael@0: michael@0: var elts = doc.getElementsByTagName("*"); michael@0: for (var i = 0; i < elts.length; i++) michael@0: { michael@0: var elt = elts.item(i); michael@0: check_neq_nodes(elt, null); michael@0: michael@0: var attrs = elt.attributes; michael@0: for (var j = 0; j < attrs.length; j++) michael@0: { michael@0: var att = attrs.item(j); michael@0: check_neq_nodes(att, null); michael@0: michael@0: for (var k = 0; k < att.childNodes.length; k++) michael@0: { michael@0: check_neq_nodes(att.childNodes.item(k), null); michael@0: } michael@0: } michael@0: } michael@0: } michael@0: michael@0: function test_isEqualNode_wholeDoc() michael@0: { michael@0: doc = ParseFile("isequalnode_data.xml"); michael@0: var doc2 = ParseFile("isequalnode_data.xml"); michael@0: var tw1 = michael@0: doc.createTreeWalker(doc, Components.interfaces.nsIDOMNodeFilter.SHOW_ALL, michael@0: null); michael@0: var tw2 = michael@0: doc2.createTreeWalker(doc2, Components.interfaces.nsIDOMNodeFilter.SHOW_ALL, michael@0: null); michael@0: do { michael@0: check_eq_nodes(tw1.currentNode, tw2.currentNode); michael@0: tw1.nextNode(); michael@0: } while(tw2.nextNode()); michael@0: } michael@0: michael@0: // UTILITY FUNCTIONS michael@0: michael@0: function n(node) { return node ? node.QueryInterface(nsIDOMNode) : null; } michael@0: function el(node) { return node ? node.QueryInterface(nsIDOMElement) : null; } michael@0: function at(node) { return node ? node.QueryInterface(nsIDOMAttr) : null; } michael@0: michael@0: michael@0: // TESTING FUNCTIONS michael@0: michael@0: /** michael@0: * Compares the first and third (zero-indexed) child nodes of the element michael@0: * (typically to allow whitespace) referenced by parentId for isEqualNode michael@0: * equality or inequality based on the value of areEqual. michael@0: * michael@0: * Note that this means that the contents of the element referenced by parentId michael@0: * are whitespace-sensitive, and a stray space introduced during an edit to the michael@0: * file could result in a correct but unexpected (in)equality failure. michael@0: */ michael@0: function equality_check_kids(parentId, areEqual) michael@0: { michael@0: var parent = doc.getElementById(parentId); michael@0: var kid1 = parent.childNodes.item(1); michael@0: var kid2 = parent.childNodes.item(3); michael@0: michael@0: if (areEqual) michael@0: check_eq_nodes(kid1, kid2); michael@0: else michael@0: check_neq_nodes(kid1, kid2); michael@0: } michael@0: michael@0: function check_eq_nodes(n1, n2) michael@0: { michael@0: if (n1 && !n1.isEqualNode(n2)) michael@0: do_throw(n1 + " should be equal to " + n2); michael@0: if (n2 && !n2.isEqualNode(n1)) michael@0: do_throw(n2 + " should be equal to " + n1); michael@0: if (!n1 && !n2) michael@0: do_throw("nodes both null!"); michael@0: } michael@0: michael@0: function check_neq_nodes(n1, n2) michael@0: { michael@0: if (n1 && n1.isEqualNode(n2)) michael@0: do_throw(n1 + " should not be equal to " + n2); michael@0: if (n2 && n2.isEqualNode(n1)) michael@0: do_throw(n2 + " should not be equal to " + n1); michael@0: if (!n1 && !n2) michael@0: do_throw("n1 and n2 both null!"); michael@0: }