|
1 /* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ |
|
2 /* This Source Code Form is subject to the terms of the Mozilla Public |
|
3 * License, v. 2.0. If a copy of the MPL was not distributed with this |
|
4 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ |
|
5 |
|
6 function run_test() |
|
7 { |
|
8 /* |
|
9 * NOTE: [i] is not allowed in this test, since it's done via classinfo and |
|
10 * we don't have that in xpcshell; the workaround is item(i). Suck. |
|
11 */ |
|
12 init(); |
|
13 |
|
14 test_isEqualNode_setAttribute(); |
|
15 test_isEqualNode_clones(); |
|
16 test_isEqualNode_variety(); |
|
17 test_isEqualNode_normalization(); |
|
18 test_isEqualNode_whitespace(); |
|
19 test_isEqualNode_namespaces(); |
|
20 test_isEqualNode_wholeDoc(); |
|
21 |
|
22 // XXX should Node.isEqualNode(null) throw or return false? |
|
23 //test_isEqualNode_null(); |
|
24 |
|
25 } |
|
26 |
|
27 // TEST CODE |
|
28 |
|
29 var doc, root; // cache for use in all tests |
|
30 |
|
31 function init() |
|
32 { |
|
33 doc = ParseFile("isequalnode_data.xml"); |
|
34 root = doc.documentElement; |
|
35 } |
|
36 |
|
37 function test_isEqualNode_setAttribute() |
|
38 { |
|
39 // NOTE: 0, 2 are whitespace |
|
40 var test1 = doc.getElementById("test_setAttribute"); |
|
41 var node1 = test1.childNodes.item(1); |
|
42 var node2 = test1.childNodes.item(3); |
|
43 |
|
44 check_eq_nodes(node1, node2); |
|
45 |
|
46 |
|
47 el(node1).setAttribute("bar", "baz"); |
|
48 check_neq_nodes(node1, node2); |
|
49 |
|
50 el(node2).setAttribute("bar", "baz"); |
|
51 check_eq_nodes(node1, node2); |
|
52 |
|
53 |
|
54 // the null namespace is equivalent to no namespace -- section 1.3.3 |
|
55 // (XML Namespaces) of DOM 3 Core |
|
56 node1.setAttributeNS(null, "quux", "17"); |
|
57 check_neq_nodes(node1, node2); |
|
58 |
|
59 node2.setAttribute("quux", "17"); |
|
60 check_eq_nodes(node1, node2); |
|
61 |
|
62 |
|
63 node2.setAttributeNS("http://mozilla.org/", "seamonkey", "rheet"); |
|
64 check_neq_nodes(node1, node2); |
|
65 |
|
66 node1.setAttribute("seamonkey", "rheet"); |
|
67 check_neq_nodes(node1, node2); |
|
68 |
|
69 node1.setAttributeNS("http://mozilla.org/", "seamonkey", "rheet"); |
|
70 check_neq_nodes(node1, node2); |
|
71 |
|
72 // this overwrites the namespaced "seamonkey" attribute added to node2 |
|
73 // earlier, because this simply sets whatever attribute has the fully |
|
74 // qualified name "seamonkey" (the setAttributeNS attribute string wasn't |
|
75 // prefixed) -- consequently, node1 and node2 are still unequal |
|
76 node2.setAttribute("seamonkey", "rheet"); |
|
77 check_neq_nodes(node1, node2); |
|
78 } |
|
79 |
|
80 function test_isEqualNode_clones() |
|
81 { |
|
82 // tests all elements and attributes in the document |
|
83 var all_elts = doc.getElementsByTagName("*"); |
|
84 for (var i = 0; i < all_elts.length; i++) |
|
85 { |
|
86 var elt = el(all_elts.item(i)); |
|
87 check_eq_nodes(elt, elt.cloneNode(true)); |
|
88 |
|
89 var attrs = elt.attributes; |
|
90 for (var j = 0; j < attrs.length; j++) |
|
91 { |
|
92 var attr = attrs.item(j); |
|
93 check_eq_nodes(attr, attr.cloneNode(true)); |
|
94 } |
|
95 } |
|
96 |
|
97 var elm = doc.createElement("foo"); |
|
98 check_eq_nodes(elm, elm.cloneNode(true)); |
|
99 check_eq_nodes(elm, elm.cloneNode(false)); |
|
100 |
|
101 elm.setAttribute("fiz", "eit"); |
|
102 check_eq_nodes(elm, elm.cloneNode(true)); |
|
103 check_eq_nodes(elm, elm.cloneNode(false)); |
|
104 |
|
105 elm.setAttributeNS("http://example.com/", "trendoid", "arthroscope"); |
|
106 check_eq_nodes(elm, elm.cloneNode(true)); |
|
107 check_eq_nodes(elm, elm.cloneNode(false)); |
|
108 |
|
109 var elm2 = elm.cloneNode(true); |
|
110 check_eq_nodes(elm, elm2); |
|
111 |
|
112 const TEXT = "fetishist"; |
|
113 |
|
114 elm.textContent = TEXT; |
|
115 check_neq_nodes(elm, elm2); |
|
116 |
|
117 check_neq_nodes(elm, elm.cloneNode(false)); |
|
118 check_eq_nodes(elm, elm.cloneNode(true)); |
|
119 |
|
120 elm2.appendChild(doc.createTextNode(TEXT)); |
|
121 check_eq_nodes(elm, elm2); |
|
122 |
|
123 var att = doc.createAttribute("bar"); |
|
124 check_eq_nodes(att, att.cloneNode(true)); |
|
125 check_eq_nodes(att, att.cloneNode(false)); |
|
126 } |
|
127 |
|
128 function test_isEqualNode_variety() |
|
129 { |
|
130 const nodes = |
|
131 [ |
|
132 doc.createElement("foo"), |
|
133 doc.createElementNS("http://example.com/", "foo"), |
|
134 doc.createElementNS("http://example.org/", "foo"), |
|
135 doc.createElementNS("http://example.com/", "FOO"), |
|
136 doc.createAttribute("foo", "href='biz'"), |
|
137 doc.createAttributeNS("http://example.com/", "foo", "href='biz'"), |
|
138 doc.createTextNode("foo"), |
|
139 doc.createTextNode(" "), |
|
140 doc.createTextNode(" "), |
|
141 doc.createComment("foo"), |
|
142 doc.createProcessingInstruction("foo", "href='biz'"), |
|
143 doc.implementation.createDocumentType("foo", "href='biz'", ""), |
|
144 doc.implementation.createDocument("http://example.com/", "foo", null), |
|
145 doc.createDocumentFragment() |
|
146 ]; |
|
147 |
|
148 for (var i = 0; i < nodes.length; i++) |
|
149 { |
|
150 for (var j = i; j < nodes.length; j++) |
|
151 { |
|
152 if (i == j) |
|
153 check_eq_nodes(nodes[i], nodes[j]); |
|
154 else |
|
155 check_neq_nodes(nodes[i], nodes[j]); |
|
156 } |
|
157 } |
|
158 } |
|
159 |
|
160 function test_isEqualNode_normalization() |
|
161 { |
|
162 var norm = doc.getElementById("test_normalization"); |
|
163 var node1 = norm.childNodes.item(1); |
|
164 var node2 = norm.childNodes.item(3); |
|
165 |
|
166 check_eq_nodes(node1, node2); |
|
167 |
|
168 node1.appendChild(doc.createTextNode("")); |
|
169 check_neq_nodes(node1, node2); |
|
170 |
|
171 node1.normalize(); |
|
172 check_eq_nodes(node1, node2); |
|
173 |
|
174 node2.appendChild(doc.createTextNode("fun")); |
|
175 node2.appendChild(doc.createTextNode("ctor")); |
|
176 node1.appendChild(doc.createTextNode("functor")); |
|
177 check_neq_nodes(node1, node2); |
|
178 |
|
179 node1.normalize(); |
|
180 check_neq_nodes(node1, node2); |
|
181 |
|
182 node2.normalize(); |
|
183 check_eq_nodes(node1, node2); |
|
184 |
|
185 // reset |
|
186 while (node1.hasChildNodes()) |
|
187 node1.removeChild(node1.childNodes.item(0)); |
|
188 while (node2.hasChildNodes()) |
|
189 node2.removeChild(node2.childNodes.item(0)); |
|
190 |
|
191 // attribute normalization testing |
|
192 |
|
193 var at1 = doc.createAttribute("foo"); |
|
194 var at2 = doc.createAttribute("foo"); |
|
195 check_eq_nodes(at1, at2); |
|
196 |
|
197 // Attr.appendChild isn't implemented yet (bug 56758), so don't run this yet |
|
198 if (false) |
|
199 { |
|
200 at1.appendChild(doc.createTextNode("rasp")); |
|
201 at2.appendChild(doc.createTextNode("rasp")); |
|
202 check_eq_nodes(at1, at2); |
|
203 |
|
204 at1.appendChild(doc.createTextNode("")); |
|
205 check_neq_nodes(at1, at2); |
|
206 |
|
207 at1.normalize(); |
|
208 check_eq_nodes(at1, at2); |
|
209 |
|
210 at1.appendChild(doc.createTextNode("berry")); |
|
211 check_neq_nodes(at1, at2); |
|
212 |
|
213 at2.appendChild(doc.createTextNode("ber")); |
|
214 check_neq_nodes(at1, at2); |
|
215 |
|
216 at2.appendChild(doc.createTextNode("ry")); |
|
217 check_neq_nodes(at1, at2); |
|
218 |
|
219 at1.normalize(); |
|
220 check_neq_nodes(at1, at2); |
|
221 |
|
222 at2.normalize(); |
|
223 check_eq_nodes(at1, at2); |
|
224 } |
|
225 |
|
226 node1.setAttributeNode(at1); |
|
227 check_neq_nodes(node1, node2); |
|
228 |
|
229 node2.setAttributeNode(at2); |
|
230 check_eq_nodes(node1, node2); |
|
231 |
|
232 var n1text1 = doc.createTextNode("ratfink"); |
|
233 var n1elt = doc.createElement("fruitcake"); |
|
234 var n1text2 = doc.createTextNode("hydrospanner"); |
|
235 |
|
236 node1.appendChild(n1text1); |
|
237 node1.appendChild(n1elt); |
|
238 node1.appendChild(n1text2); |
|
239 |
|
240 check_neq_nodes(node1, node2); |
|
241 |
|
242 var n2text1a = doc.createTextNode("rat"); |
|
243 var n2text1b = doc.createTextNode("fink"); |
|
244 var n2elt = doc.createElement("fruitcake"); |
|
245 var n2text2 = doc.createTextNode("hydrospanner"); |
|
246 |
|
247 node2.appendChild(n2text1b); |
|
248 node2.appendChild(n2elt); |
|
249 node2.appendChild(n2text2); |
|
250 check_neq_nodes(node1, node2); |
|
251 |
|
252 node2.insertBefore(n2text1a, n2text1b); |
|
253 check_neq_nodes(node1, node2); |
|
254 |
|
255 var tmp_node1 = node1.cloneNode(true); |
|
256 tmp_node1.normalize(); |
|
257 var tmp_node2 = node2.cloneNode(true); |
|
258 tmp_node2.normalize(); |
|
259 check_eq_nodes(tmp_node1, tmp_node2); |
|
260 |
|
261 n2elt.appendChild(doc.createTextNode("")); |
|
262 check_neq_nodes(node1, node2); |
|
263 |
|
264 tmp_node1 = node1.cloneNode(true); |
|
265 tmp_node1.normalize(); |
|
266 tmp_node2 = node2.cloneNode(true); |
|
267 tmp_node2.normalize(); |
|
268 check_eq_nodes(tmp_node1, tmp_node2); |
|
269 |
|
270 var typeText1 = doc.createTextNode("type"); |
|
271 n2elt.appendChild(typeText1); |
|
272 tmp_node1 = node1.cloneNode(true); |
|
273 tmp_node1.normalize(); |
|
274 tmp_node2 = node2.cloneNode(true); |
|
275 tmp_node2.normalize(); |
|
276 check_neq_nodes(tmp_node1, tmp_node2); |
|
277 |
|
278 n1elt.appendChild(doc.createTextNode("typedef")); |
|
279 tmp_node1 = node1.cloneNode(true); |
|
280 tmp_node1.normalize(); |
|
281 tmp_node2 = node2.cloneNode(true); |
|
282 tmp_node2.normalize(); |
|
283 check_neq_nodes(tmp_node1, tmp_node2); |
|
284 check_neq_nodes(n1elt, n2elt); |
|
285 |
|
286 var typeText2 = doc.createTextNode("def"); |
|
287 n2elt.appendChild(typeText2); |
|
288 tmp_node1 = node1.cloneNode(true); |
|
289 tmp_node1.normalize(); |
|
290 tmp_node2 = node2.cloneNode(true); |
|
291 tmp_node2.normalize(); |
|
292 check_eq_nodes(tmp_node1, tmp_node2); |
|
293 check_neq_nodes(node1, node2); |
|
294 |
|
295 n2elt.insertBefore(doc.createTextNode(""), typeText2); |
|
296 check_neq_nodes(node1, node2); |
|
297 |
|
298 n2elt.insertBefore(doc.createTextNode(""), typeText2); |
|
299 check_neq_nodes(node1, node2); |
|
300 |
|
301 n2elt.insertBefore(doc.createTextNode(""), typeText1); |
|
302 check_neq_nodes(node1, node2); |
|
303 |
|
304 node1.normalize(); |
|
305 node2.normalize(); |
|
306 check_eq_nodes(node1, node2); |
|
307 } |
|
308 |
|
309 function test_isEqualNode_whitespace() |
|
310 { |
|
311 equality_check_kids("test_pi1", true); |
|
312 equality_check_kids("test_pi2", true); |
|
313 equality_check_kids("test_pi3", false); |
|
314 equality_check_kids("test_pi4", true); |
|
315 equality_check_kids("test_pi5", true); |
|
316 |
|
317 equality_check_kids("test_elt1", false); |
|
318 equality_check_kids("test_elt2", false); |
|
319 equality_check_kids("test_elt3", true); |
|
320 equality_check_kids("test_elt4", false); |
|
321 equality_check_kids("test_elt5", false); |
|
322 |
|
323 equality_check_kids("test_comment1", true); |
|
324 equality_check_kids("test_comment2", false); |
|
325 equality_check_kids("test_comment3", false); |
|
326 equality_check_kids("test_comment4", true); |
|
327 |
|
328 equality_check_kids("test_text1", true); |
|
329 equality_check_kids("test_text2", false); |
|
330 equality_check_kids("test_text3", false); |
|
331 |
|
332 equality_check_kids("test_cdata1", false); |
|
333 equality_check_kids("test_cdata2", true); |
|
334 equality_check_kids("test_cdata3", false); |
|
335 equality_check_kids("test_cdata4", false); |
|
336 equality_check_kids("test_cdata5", false); |
|
337 } |
|
338 |
|
339 function test_isEqualNode_namespaces() |
|
340 { |
|
341 equality_check_kids("test_ns1", false); |
|
342 equality_check_kids("test_ns2", false); |
|
343 |
|
344 // XXX want more tests here! |
|
345 } |
|
346 |
|
347 function test_isEqualNode_null() |
|
348 { |
|
349 check_neq_nodes(doc, null); |
|
350 |
|
351 var elts = doc.getElementsByTagName("*"); |
|
352 for (var i = 0; i < elts.length; i++) |
|
353 { |
|
354 var elt = elts.item(i); |
|
355 check_neq_nodes(elt, null); |
|
356 |
|
357 var attrs = elt.attributes; |
|
358 for (var j = 0; j < attrs.length; j++) |
|
359 { |
|
360 var att = attrs.item(j); |
|
361 check_neq_nodes(att, null); |
|
362 |
|
363 for (var k = 0; k < att.childNodes.length; k++) |
|
364 { |
|
365 check_neq_nodes(att.childNodes.item(k), null); |
|
366 } |
|
367 } |
|
368 } |
|
369 } |
|
370 |
|
371 function test_isEqualNode_wholeDoc() |
|
372 { |
|
373 doc = ParseFile("isequalnode_data.xml"); |
|
374 var doc2 = ParseFile("isequalnode_data.xml"); |
|
375 var tw1 = |
|
376 doc.createTreeWalker(doc, Components.interfaces.nsIDOMNodeFilter.SHOW_ALL, |
|
377 null); |
|
378 var tw2 = |
|
379 doc2.createTreeWalker(doc2, Components.interfaces.nsIDOMNodeFilter.SHOW_ALL, |
|
380 null); |
|
381 do { |
|
382 check_eq_nodes(tw1.currentNode, tw2.currentNode); |
|
383 tw1.nextNode(); |
|
384 } while(tw2.nextNode()); |
|
385 } |
|
386 |
|
387 // UTILITY FUNCTIONS |
|
388 |
|
389 function n(node) { return node ? node.QueryInterface(nsIDOMNode) : null; } |
|
390 function el(node) { return node ? node.QueryInterface(nsIDOMElement) : null; } |
|
391 function at(node) { return node ? node.QueryInterface(nsIDOMAttr) : null; } |
|
392 |
|
393 |
|
394 // TESTING FUNCTIONS |
|
395 |
|
396 /** |
|
397 * Compares the first and third (zero-indexed) child nodes of the element |
|
398 * (typically to allow whitespace) referenced by parentId for isEqualNode |
|
399 * equality or inequality based on the value of areEqual. |
|
400 * |
|
401 * Note that this means that the contents of the element referenced by parentId |
|
402 * are whitespace-sensitive, and a stray space introduced during an edit to the |
|
403 * file could result in a correct but unexpected (in)equality failure. |
|
404 */ |
|
405 function equality_check_kids(parentId, areEqual) |
|
406 { |
|
407 var parent = doc.getElementById(parentId); |
|
408 var kid1 = parent.childNodes.item(1); |
|
409 var kid2 = parent.childNodes.item(3); |
|
410 |
|
411 if (areEqual) |
|
412 check_eq_nodes(kid1, kid2); |
|
413 else |
|
414 check_neq_nodes(kid1, kid2); |
|
415 } |
|
416 |
|
417 function check_eq_nodes(n1, n2) |
|
418 { |
|
419 if (n1 && !n1.isEqualNode(n2)) |
|
420 do_throw(n1 + " should be equal to " + n2); |
|
421 if (n2 && !n2.isEqualNode(n1)) |
|
422 do_throw(n2 + " should be equal to " + n1); |
|
423 if (!n1 && !n2) |
|
424 do_throw("nodes both null!"); |
|
425 } |
|
426 |
|
427 function check_neq_nodes(n1, n2) |
|
428 { |
|
429 if (n1 && n1.isEqualNode(n2)) |
|
430 do_throw(n1 + " should not be equal to " + n2); |
|
431 if (n2 && n2.isEqualNode(n1)) |
|
432 do_throw(n2 + " should not be equal to " + n1); |
|
433 if (!n1 && !n2) |
|
434 do_throw("n1 and n2 both null!"); |
|
435 } |