Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(332)

Side by Side Diff: third_party/WebKit/LayoutTests/imported/wpt/dom/ranges/Range-mutations.html

Issue 2468053002: Import wpt@9fcccf38b6be00f71ffa6bd6e29c5aa1ef25ee8c (Closed)
Patch Set: Skip cssom and svg/shapes, remove unwanted baseline Created 4 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
1 <!doctype html>
2 <title>Range mutation tests</title>
3 <link rel="author" title="Aryeh Gregor" href=ayg@aryeh.name>
4 <meta name=timeout content=long>
5
6 <div id=log></div>
7 <script src=/resources/testharness.js></script>
8 <script src=/resources/testharnessreport.js></script>
9 <script src=../common.js></script>
10 <script>
11 "use strict";
12
13 // These tests probably use too much abstraction and too little copy-paste.
14 // Reader beware.
15 //
16 // TODO:
17 //
18 // * Lots and lots and lots more different types of ranges
19 // * insertBefore() with DocumentFragments
20 // * Fill out other insert/remove tests
21 // * normalize() (https://www.w3.org/Bugs/Public/show_bug.cgi?id=13843)
22
23 // Give a textual description of the range we're testing, for the test names.
24 function describeRange(startContainer, startOffset, endContainer, endOffset) {
25 if (startContainer == endContainer && startOffset == endOffset) {
26 return "range collapsed at (" + startContainer + ", " + startOffset + ")";
27 } else if (startContainer == endContainer) {
28 return "range on " + startContainer + " from " + startOffset + " to " + endO ffset;
29 } else {
30 return "range from (" + startContainer + ", " + startOffset + ") to (" + end Container + ", " + endOffset + ")";
31 }
32 }
33
34 // Lists of the various types of nodes we'll want to use. We use strings that
35 // we can later eval(), so that we can produce legible test names.
36 var textNodes = [
37 "paras[0].firstChild",
38 "paras[1].firstChild",
39 "foreignTextNode",
40 "xmlTextNode",
41 "detachedTextNode",
42 "detachedForeignTextNode",
43 "detachedXmlTextNode",
44 ];
45 var commentNodes = [
46 "comment",
47 "foreignComment",
48 "xmlComment",
49 "detachedComment",
50 "detachedForeignComment",
51 "detachedXmlComment",
52 ];
53 var characterDataNodes = textNodes.concat(commentNodes);
54
55 // This function is slightly scary, but it works well enough, so . . .
56 // sourceTests is an array of test data that will be altered in mysterious ways
57 // before being passed off to doTest, descFn is something that takes an element
58 // of sourceTests and produces the first part of a human-readable description
59 // of the test, testFn is the function that doTest will call to do the actual
60 // work and tell it what results to expect.
61 function doTests(sourceTests, descFn, testFn) {
62 var tests = [];
63 for (var i = 0; i < sourceTests.length; i++) {
64 var params = sourceTests[i];
65 var len = params.length;
66 tests.push([
67 descFn(params) + ", with unselected " + describeRange(params[len - 4], par ams[len - 3], params[len - 2], params[len - 1]),
68 // The closure here ensures that the params that testFn get are the
69 // current version of params, not the version from the last
70 // iteration of this loop. We test that none of the parameters
71 // evaluate to undefined to catch bugs in our eval'ing, like
72 // mistyping a property name.
73 function(params) { return function() {
74 var evaledParams = params.map(eval);
75 for (var i = 0; i < evaledParams.length; i++) {
76 assert_true(typeof evaledParams[i] != "undefined",
77 "Test bug: " + params[i] + " is undefined");
78 }
79 return testFn.apply(null, evaledParams);
80 } }(params),
81 false,
82 params[len - 4],
83 params[len - 3],
84 params[len - 2],
85 params[len - 1]
86 ]);
87 tests.push([
88 descFn(params) + ", with selected " + describeRange(params[len - 4], param s[len - 3], params[len - 2], params[len - 1]),
89 function(params) { return function(selectedRange) {
90 var evaledParams = params.slice(0, len - 4).map(eval);
91 for (var i = 0; i < evaledParams.length; i++) {
92 assert_true(typeof evaledParams[i] != "undefined",
93 "Test bug: " + params[i] + " is undefined");
94 }
95 // Override input range with the one that was actually selected when com puting the expected result.
96 evaledParams = evaledParams.concat([selectedRange.startContainer, select edRange.startOffset, selectedRange.endContainer, selectedRange.endOffset]);
97 return testFn.apply(null, evaledParams);
98 } }(params),
99 true,
100 params[len - 4],
101 params[len - 3],
102 params[len - 2],
103 params[len - 1]
104 ]);
105 }
106 generate_tests(doTest, tests);
107 }
108
109 // Set up the range, call the callback function to do the DOM modification and
110 // tell us what to expect. The callback function needs to return a
111 // four-element array with the expected start/end containers/offsets, and
112 // receives no arguments. useSelection tells us whether the Range should be
113 // added to a Selection and the Selection tested to ensure that the mutation
114 // affects user selections as well as other ranges; every test is run with this
115 // both false and true, because when it's set to true WebKit and Opera fail all
116 // tests' sanity checks, which is unhelpful. The last four parameters just
117 // tell us what range to build.
118 function doTest(callback, useSelection, startContainer, startOffset, endContaine r, endOffset) {
119 // Recreate all the test nodes in case they were altered by the last test
120 // run.
121 setupRangeTests();
122 startContainer = eval(startContainer);
123 startOffset = eval(startOffset);
124 endContainer = eval(endContainer);
125 endOffset = eval(endOffset);
126
127 var ownerDoc = startContainer.nodeType == Node.DOCUMENT_NODE
128 ? startContainer
129 : startContainer.ownerDocument;
130 var range = ownerDoc.createRange();
131 range.setStart(startContainer, startOffset);
132 range.setEnd(endContainer, endOffset);
133
134 if (useSelection) {
135 getSelection().removeAllRanges();
136 getSelection().addRange(range);
137
138 // Some browsers refuse to add a range unless it results in an actual visibl e selection.
139 if (!getSelection().rangeCount)
140 return;
141
142 // Override range with the one that was actually selected as it differs in s ome browsers.
143 range = getSelection().getRangeAt(0);
144 }
145
146 var expected = callback(range);
147
148 assert_equals(range.startContainer, expected[0],
149 "Wrong start container");
150 assert_equals(range.startOffset, expected[1],
151 "Wrong start offset");
152 assert_equals(range.endContainer, expected[2],
153 "Wrong end container");
154 assert_equals(range.endOffset, expected[3],
155 "Wrong end offset");
156 }
157
158
159 // Now we get to the specific tests.
160
161 function testSplitText(oldNode, offset, startContainer, startOffset, endContaine r, endOffset) {
162 // Save these for later
163 var originalStartOffset = startOffset;
164 var originalEndOffset = endOffset;
165 var originalLength = oldNode.length;
166
167 var newNode;
168 try {
169 newNode = oldNode.splitText(offset);
170 } catch (e) {
171 // Should only happen if offset is negative
172 return [startContainer, startOffset, endContainer, endOffset];
173 }
174
175 // First we adjust for replacing data:
176 //
177 // "Replace data with offset offset, count count, and data the empty
178 // string."
179 //
180 // That translates to offset = offset, count = originalLength - offset,
181 // data = "". node is oldNode.
182 //
183 // "For every boundary point whose node is node, and whose offset is
184 // greater than offset but less than or equal to offset plus count, set its
185 // offset to offset."
186 if (startContainer == oldNode
187 && startOffset > offset
188 && startOffset <= originalLength) {
189 startOffset = offset;
190 }
191
192 if (endContainer == oldNode
193 && endOffset > offset
194 && endOffset <= originalLength) {
195 endOffset = offset;
196 }
197
198 // "For every boundary point whose node is node, and whose offset is
199 // greater than offset plus count, add the length of data to its offset,
200 // then subtract count from it."
201 //
202 // Can't happen: offset plus count is originalLength.
203
204 // Now we insert a node, if oldNode's parent isn't null: "For each boundary
205 // point whose node is the new parent of the affected node and whose offset
206 // is greater than the new index of the affected node, add one to the
207 // boundary point's offset."
208 if (startContainer == oldNode.parentNode
209 && startOffset > 1 + indexOf(oldNode)) {
210 startOffset++;
211 }
212
213 if (endContainer == oldNode.parentNode
214 && endOffset > 1 + indexOf(oldNode)) {
215 endOffset++;
216 }
217
218 // Finally, the splitText stuff itself:
219 //
220 // "If parent is not null, run these substeps:
221 //
222 // * "For each range whose start node is node and start offset is greater
223 // than offset, set its start node to new node and decrease its start
224 // offset by offset.
225 //
226 // * "For each range whose end node is node and end offset is greater
227 // than offset, set its end node to new node and decrease its end offset
228 // by offset.
229 //
230 // * "For each range whose start node is parent and start offset is equal
231 // to the index of node + 1, increase its start offset by one.
232 //
233 // * "For each range whose end node is parent and end offset is equal to
234 // the index of node + 1, increase its end offset by one."
235 if (oldNode.parentNode) {
236 if (startContainer == oldNode && originalStartOffset > offset) {
237 startContainer = newNode;
238 startOffset = originalStartOffset - offset;
239 }
240
241 if (endContainer == oldNode && originalEndOffset > offset) {
242 endContainer = newNode;
243 endOffset = originalEndOffset - offset;
244 }
245
246 if (startContainer == oldNode.parentNode
247 && startOffset == 1 + indexOf(oldNode)) {
248 startOffset++;
249 }
250
251 if (endContainer == oldNode.parentNode
252 && endOffset == 1 + indexOf(oldNode)) {
253 endOffset++;
254 }
255 }
256
257 return [startContainer, startOffset, endContainer, endOffset];
258 }
259
260 // The offset argument is unsigned, so per WebIDL -1 should wrap to 4294967295,
261 // which is probably longer than the length, so it should throw an exception.
262 // This is no different from the other cases where the offset is longer than
263 // the length, and the wrapping complicates my testing slightly, so I won't
264 // bother testing negative values here or in other cases.
265 var splitTextTests = [];
266 for (var i = 0; i < textNodes.length; i++) {
267 var node = textNodes[i];
268 splitTextTests.push([node, 376, node, 0, node, 1]);
269 splitTextTests.push([node, 0, node, 0, node, 0]);
270 splitTextTests.push([node, 1, node, 1, node, 1]);
271 splitTextTests.push([node, node + ".length", node, node + ".length", node, nod e + ".length"]);
272 splitTextTests.push([node, 1, node, 1, node, 3]);
273 splitTextTests.push([node, 2, node, 1, node, 3]);
274 splitTextTests.push([node, 3, node, 1, node, 3]);
275 }
276
277 splitTextTests.push(
278 ["paras[0].firstChild", 1, "paras[0]", 0, "paras[0]", 0],
279 ["paras[0].firstChild", 1, "paras[0]", 0, "paras[0]", 1],
280 ["paras[0].firstChild", 1, "paras[0]", 1, "paras[0]", 1],
281 ["paras[0].firstChild", 1, "paras[0].firstChild", 1, "paras[0]", 1],
282 ["paras[0].firstChild", 2, "paras[0].firstChild", 1, "paras[0]", 1],
283 ["paras[0].firstChild", 3, "paras[0].firstChild", 1, "paras[0]", 1],
284 ["paras[0].firstChild", 1, "paras[0]", 0, "paras[0].firstChild", 3],
285 ["paras[0].firstChild", 2, "paras[0]", 0, "paras[0].firstChild", 3],
286 ["paras[0].firstChild", 3, "paras[0]", 0, "paras[0].firstChild", 3]
287 );
288
289
290 function testReplaceDataAlgorithm(node, offset, count, data, callback, startCont ainer, startOffset, endContainer, endOffset) {
291 // Mutation works the same any time DOM Core's "replace data" algorithm is
292 // invoked. node, offset, count, data are as in that algorithm. The
293 // callback is what does the actual setting. Not to be confused with
294 // testReplaceData, which tests the replaceData() method.
295
296 // Barring any provision to the contrary, the containers and offsets must
297 // not change.
298 var expectedStartContainer = startContainer;
299 var expectedStartOffset = startOffset;
300 var expectedEndContainer = endContainer;
301 var expectedEndOffset = endOffset;
302
303 var originalParent = node.parentNode;
304 var originalData = node.data;
305
306 var exceptionThrown = false;
307 try {
308 callback();
309 } catch (e) {
310 // Should only happen if offset is greater than length
311 exceptionThrown = true;
312 }
313
314 assert_equals(node.parentNode, originalParent,
315 "Sanity check failed: changing data changed the parent");
316
317 // "User agents must run the following steps whenever they replace data of
318 // a CharacterData node, as though they were written in the specification
319 // for that algorithm after all other steps. In particular, the steps must
320 // not be executed if the algorithm threw an exception."
321 if (exceptionThrown) {
322 assert_equals(node.data, originalData,
323 "Sanity check failed: exception thrown but data changed");
324 } else {
325 assert_equals(node.data,
326 originalData.substr(0, offset) + data + originalData.substr(offset + count ),
327 "Sanity check failed: data not changed as expected");
328 }
329
330 // "For every boundary point whose node is node, and whose offset is
331 // greater than offset but less than or equal to offset plus count, set
332 // its offset to offset."
333 if (!exceptionThrown
334 && startContainer == node
335 && startOffset > offset
336 && startOffset <= offset + count) {
337 expectedStartOffset = offset;
338 }
339
340 if (!exceptionThrown
341 && endContainer == node
342 && endOffset > offset
343 && endOffset <= offset + count) {
344 expectedEndOffset = offset;
345 }
346
347 // "For every boundary point whose node is node, and whose offset is
348 // greater than offset plus count, add the length of data to its offset,
349 // then subtract count from it."
350 if (!exceptionThrown
351 && startContainer == node
352 && startOffset > offset + count) {
353 expectedStartOffset += data.length - count;
354 }
355
356 if (!exceptionThrown
357 && endContainer == node
358 && endOffset > offset + count) {
359 expectedEndOffset += data.length - count;
360 }
361
362 return [expectedStartContainer, expectedStartOffset, expectedEndContainer, exp ectedEndOffset];
363 }
364
365 function testInsertData(node, offset, data, startContainer, startOffset, endCont ainer, endOffset) {
366 return testReplaceDataAlgorithm(node, offset, 0, data,
367 function() { node.insertData(offset, data) },
368 startContainer, startOffset, endContainer, endOffset);
369 }
370
371 var insertDataTests = [];
372 for (var i = 0; i < characterDataNodes.length; i++) {
373 var node = characterDataNodes[i];
374 insertDataTests.push([node, 376, '"foo"', node, 0, node, 1]);
375 insertDataTests.push([node, 0, '"foo"', node, 0, node, 0]);
376 insertDataTests.push([node, 1, '"foo"', node, 1, node, 1]);
377 insertDataTests.push([node, node + ".length", '"foo"', node, node + ".length", node, node + ".length"]);
378 insertDataTests.push([node, 1, '"foo"', node, 1, node, 3]);
379 insertDataTests.push([node, 2, '"foo"', node, 1, node, 3]);
380 insertDataTests.push([node, 3, '"foo"', node, 1, node, 3]);
381
382 insertDataTests.push([node, 376, '""', node, 0, node, 1]);
383 insertDataTests.push([node, 0, '""', node, 0, node, 0]);
384 insertDataTests.push([node, 1, '""', node, 1, node, 1]);
385 insertDataTests.push([node, node + ".length", '""', node, node + ".length", no de, node + ".length"]);
386 insertDataTests.push([node, 1, '""', node, 1, node, 3]);
387 insertDataTests.push([node, 2, '""', node, 1, node, 3]);
388 insertDataTests.push([node, 3, '""', node, 1, node, 3]);
389 }
390
391 insertDataTests.push(
392 ["paras[0].firstChild", 1, '"foo"', "paras[0]", 0, "paras[0]", 0],
393 ["paras[0].firstChild", 1, '"foo"', "paras[0]", 0, "paras[0]", 1],
394 ["paras[0].firstChild", 1, '"foo"', "paras[0]", 1, "paras[0]", 1],
395 ["paras[0].firstChild", 1, '"foo"', "paras[0].firstChild", 1, "paras[0]", 1],
396 ["paras[0].firstChild", 2, '"foo"', "paras[0].firstChild", 1, "paras[0]", 1],
397 ["paras[0].firstChild", 3, '"foo"', "paras[0].firstChild", 1, "paras[0]", 1],
398 ["paras[0].firstChild", 1, '"foo"', "paras[0]", 0, "paras[0].firstChild", 3],
399 ["paras[0].firstChild", 2, '"foo"', "paras[0]", 0, "paras[0].firstChild", 3],
400 ["paras[0].firstChild", 3, '"foo"', "paras[0]", 0, "paras[0].firstChild", 3]
401 );
402
403
404 function testAppendData(node, data, startContainer, startOffset, endContainer, e ndOffset) {
405 return testReplaceDataAlgorithm(node, node.length, 0, data,
406 function() { node.appendData(data) },
407 startContainer, startOffset, endContainer, endOffset);
408 }
409
410 var appendDataTests = [];
411 for (var i = 0; i < characterDataNodes.length; i++) {
412 var node = characterDataNodes[i];
413 appendDataTests.push([node, '"foo"', node, 0, node, 1]);
414 appendDataTests.push([node, '"foo"', node, 0, node, 0]);
415 appendDataTests.push([node, '"foo"', node, 1, node, 1]);
416 appendDataTests.push([node, '"foo"', node, 0, node, node + ".length"]);
417 appendDataTests.push([node, '"foo"', node, 1, node, node + ".length"]);
418 appendDataTests.push([node, '"foo"', node, node + ".length", node, node + ".le ngth"]);
419 appendDataTests.push([node, '"foo"', node, 1, node, 3]);
420
421 appendDataTests.push([node, '""', node, 0, node, 1]);
422 appendDataTests.push([node, '""', node, 0, node, 0]);
423 appendDataTests.push([node, '""', node, 1, node, 1]);
424 appendDataTests.push([node, '""', node, 0, node, node + ".length"]);
425 appendDataTests.push([node, '""', node, 1, node, node + ".length"]);
426 appendDataTests.push([node, '""', node, node + ".length", node, node + ".lengt h"]);
427 appendDataTests.push([node, '""', node, 1, node, 3]);
428 }
429
430 appendDataTests.push(
431 ["paras[0].firstChild", '""', "paras[0]", 0, "paras[0]", 0],
432 ["paras[0].firstChild", '""', "paras[0]", 0, "paras[0]", 1],
433 ["paras[0].firstChild", '""', "paras[0]", 1, "paras[0]", 1],
434 ["paras[0].firstChild", '""', "paras[0].firstChild", 1, "paras[0]", 1],
435 ["paras[0].firstChild", '""', "paras[0]", 0, "paras[0].firstChild", 3],
436
437 ["paras[0].firstChild", '"foo"', "paras[0]", 0, "paras[0]", 0],
438 ["paras[0].firstChild", '"foo"', "paras[0]", 0, "paras[0]", 1],
439 ["paras[0].firstChild", '"foo"', "paras[0]", 1, "paras[0]", 1],
440 ["paras[0].firstChild", '"foo"', "paras[0].firstChild", 1, "paras[0]", 1],
441 ["paras[0].firstChild", '"foo"', "paras[0]", 0, "paras[0].firstChild", 3]
442 );
443
444
445 function testDeleteData(node, offset, count, startContainer, startOffset, endCon tainer, endOffset) {
446 return testReplaceDataAlgorithm(node, offset, count, "",
447 function() { node.deleteData(offset, count) },
448 startContainer, startOffset, endContainer, endOffset);
449 }
450
451 var deleteDataTests = [];
452 for (var i = 0; i < characterDataNodes.length; i++) {
453 var node = characterDataNodes[i];
454 deleteDataTests.push([node, 376, 2, node, 0, node, 1]);
455 deleteDataTests.push([node, 0, 2, node, 0, node, 0]);
456 deleteDataTests.push([node, 1, 2, node, 1, node, 1]);
457 deleteDataTests.push([node, node + ".length", 2, node, node + ".length", node, node + ".length"]);
458 deleteDataTests.push([node, 1, 2, node, 1, node, 3]);
459 deleteDataTests.push([node, 2, 2, node, 1, node, 3]);
460 deleteDataTests.push([node, 3, 2, node, 1, node, 3]);
461
462 deleteDataTests.push([node, 376, 0, node, 0, node, 1]);
463 deleteDataTests.push([node, 0, 0, node, 0, node, 0]);
464 deleteDataTests.push([node, 1, 0, node, 1, node, 1]);
465 deleteDataTests.push([node, node + ".length", 0, node, node + ".length", node, node + ".length"]);
466 deleteDataTests.push([node, 1, 0, node, 1, node, 3]);
467 deleteDataTests.push([node, 2, 0, node, 1, node, 3]);
468 deleteDataTests.push([node, 3, 0, node, 1, node, 3]);
469
470 deleteDataTests.push([node, 376, 631, node, 0, node, 1]);
471 deleteDataTests.push([node, 0, 631, node, 0, node, 0]);
472 deleteDataTests.push([node, 1, 631, node, 1, node, 1]);
473 deleteDataTests.push([node, node + ".length", 631, node, node + ".length", nod e, node + ".length"]);
474 deleteDataTests.push([node, 1, 631, node, 1, node, 3]);
475 deleteDataTests.push([node, 2, 631, node, 1, node, 3]);
476 deleteDataTests.push([node, 3, 631, node, 1, node, 3]);
477 }
478
479 deleteDataTests.push(
480 ["paras[0].firstChild", 1, 2, "paras[0]", 0, "paras[0]", 0],
481 ["paras[0].firstChild", 1, 2, "paras[0]", 0, "paras[0]", 1],
482 ["paras[0].firstChild", 1, 2, "paras[0]", 1, "paras[0]", 1],
483 ["paras[0].firstChild", 1, 2, "paras[0].firstChild", 1, "paras[0]", 1],
484 ["paras[0].firstChild", 2, 2, "paras[0].firstChild", 1, "paras[0]", 1],
485 ["paras[0].firstChild", 3, 2, "paras[0].firstChild", 1, "paras[0]", 1],
486 ["paras[0].firstChild", 1, 2, "paras[0]", 0, "paras[0].firstChild", 3],
487 ["paras[0].firstChild", 2, 2, "paras[0]", 0, "paras[0].firstChild", 3],
488 ["paras[0].firstChild", 3, 2, "paras[0]", 0, "paras[0].firstChild", 3]
489 );
490
491
492 function testReplaceData(node, offset, count, data, startContainer, startOffset, endContainer, endOffset) {
493 return testReplaceDataAlgorithm(node, offset, count, data,
494 function() { node.replaceData(offset, count, data) },
495 startContainer, startOffset, endContainer, endOffset);
496 }
497
498 var replaceDataTests = [];
499 for (var i = 0; i < characterDataNodes.length; i++) {
500 var node = characterDataNodes[i];
501 replaceDataTests.push([node, 376, 0, '"foo"', node, 0, node, 1]);
502 replaceDataTests.push([node, 0, 0, '"foo"', node, 0, node, 0]);
503 replaceDataTests.push([node, 1, 0, '"foo"', node, 1, node, 1]);
504 replaceDataTests.push([node, node + ".length", 0, '"foo"', node, node + ".leng th", node, node + ".length"]);
505 replaceDataTests.push([node, 1, 0, '"foo"', node, 1, node, 3]);
506 replaceDataTests.push([node, 2, 0, '"foo"', node, 1, node, 3]);
507 replaceDataTests.push([node, 3, 0, '"foo"', node, 1, node, 3]);
508
509 replaceDataTests.push([node, 376, 0, '""', node, 0, node, 1]);
510 replaceDataTests.push([node, 0, 0, '""', node, 0, node, 0]);
511 replaceDataTests.push([node, 1, 0, '""', node, 1, node, 1]);
512 replaceDataTests.push([node, node + ".length", 0, '""', node, node + ".length" , node, node + ".length"]);
513 replaceDataTests.push([node, 1, 0, '""', node, 1, node, 3]);
514 replaceDataTests.push([node, 2, 0, '""', node, 1, node, 3]);
515 replaceDataTests.push([node, 3, 0, '""', node, 1, node, 3]);
516
517 replaceDataTests.push([node, 376, 1, '"foo"', node, 0, node, 1]);
518 replaceDataTests.push([node, 0, 1, '"foo"', node, 0, node, 0]);
519 replaceDataTests.push([node, 1, 1, '"foo"', node, 1, node, 1]);
520 replaceDataTests.push([node, node + ".length", 1, '"foo"', node, node + ".leng th", node, node + ".length"]);
521 replaceDataTests.push([node, 1, 1, '"foo"', node, 1, node, 3]);
522 replaceDataTests.push([node, 2, 1, '"foo"', node, 1, node, 3]);
523 replaceDataTests.push([node, 3, 1, '"foo"', node, 1, node, 3]);
524
525 replaceDataTests.push([node, 376, 1, '""', node, 0, node, 1]);
526 replaceDataTests.push([node, 0, 1, '""', node, 0, node, 0]);
527 replaceDataTests.push([node, 1, 1, '""', node, 1, node, 1]);
528 replaceDataTests.push([node, node + ".length", 1, '""', node, node + ".length" , node, node + ".length"]);
529 replaceDataTests.push([node, 1, 1, '""', node, 1, node, 3]);
530 replaceDataTests.push([node, 2, 1, '""', node, 1, node, 3]);
531 replaceDataTests.push([node, 3, 1, '""', node, 1, node, 3]);
532
533 replaceDataTests.push([node, 376, 47, '"foo"', node, 0, node, 1]);
534 replaceDataTests.push([node, 0, 47, '"foo"', node, 0, node, 0]);
535 replaceDataTests.push([node, 1, 47, '"foo"', node, 1, node, 1]);
536 replaceDataTests.push([node, node + ".length", 47, '"foo"', node, node + ".len gth", node, node + ".length"]);
537 replaceDataTests.push([node, 1, 47, '"foo"', node, 1, node, 3]);
538 replaceDataTests.push([node, 2, 47, '"foo"', node, 1, node, 3]);
539 replaceDataTests.push([node, 3, 47, '"foo"', node, 1, node, 3]);
540
541 replaceDataTests.push([node, 376, 47, '""', node, 0, node, 1]);
542 replaceDataTests.push([node, 0, 47, '""', node, 0, node, 0]);
543 replaceDataTests.push([node, 1, 47, '""', node, 1, node, 1]);
544 replaceDataTests.push([node, node + ".length", 47, '""', node, node + ".length ", node, node + ".length"]);
545 replaceDataTests.push([node, 1, 47, '""', node, 1, node, 3]);
546 replaceDataTests.push([node, 2, 47, '""', node, 1, node, 3]);
547 replaceDataTests.push([node, 3, 47, '""', node, 1, node, 3]);
548 }
549
550 replaceDataTests.push(
551 ["paras[0].firstChild", 1, 0, '"foo"', "paras[0]", 0, "paras[0]", 0],
552 ["paras[0].firstChild", 1, 0, '"foo"', "paras[0]", 0, "paras[0]", 1],
553 ["paras[0].firstChild", 1, 0, '"foo"', "paras[0]", 1, "paras[0]", 1],
554 ["paras[0].firstChild", 1, 0, '"foo"', "paras[0].firstChild", 1, "paras[0]", 1 ],
555 ["paras[0].firstChild", 2, 0, '"foo"', "paras[0].firstChild", 1, "paras[0]", 1 ],
556 ["paras[0].firstChild", 3, 0, '"foo"', "paras[0].firstChild", 1, "paras[0]", 1 ],
557 ["paras[0].firstChild", 1, 0, '"foo"', "paras[0]", 0, "paras[0].firstChild", 3 ],
558 ["paras[0].firstChild", 2, 0, '"foo"', "paras[0]", 0, "paras[0].firstChild", 3 ],
559 ["paras[0].firstChild", 3, 0, '"foo"', "paras[0]", 0, "paras[0].firstChild", 3 ],
560
561 ["paras[0].firstChild", 1, 1, '"foo"', "paras[0]", 0, "paras[0]", 0],
562 ["paras[0].firstChild", 1, 1, '"foo"', "paras[0]", 0, "paras[0]", 1],
563 ["paras[0].firstChild", 1, 1, '"foo"', "paras[0]", 1, "paras[0]", 1],
564 ["paras[0].firstChild", 1, 1, '"foo"', "paras[0].firstChild", 1, "paras[0]", 1 ],
565 ["paras[0].firstChild", 2, 1, '"foo"', "paras[0].firstChild", 1, "paras[0]", 1 ],
566 ["paras[0].firstChild", 3, 1, '"foo"', "paras[0].firstChild", 1, "paras[0]", 1 ],
567 ["paras[0].firstChild", 1, 1, '"foo"', "paras[0]", 0, "paras[0].firstChild", 3 ],
568 ["paras[0].firstChild", 2, 1, '"foo"', "paras[0]", 0, "paras[0].firstChild", 3 ],
569 ["paras[0].firstChild", 3, 1, '"foo"', "paras[0]", 0, "paras[0].firstChild", 3 ],
570
571 ["paras[0].firstChild", 1, 47, '"foo"', "paras[0]", 0, "paras[0]", 0],
572 ["paras[0].firstChild", 1, 47, '"foo"', "paras[0]", 0, "paras[0]", 1],
573 ["paras[0].firstChild", 1, 47, '"foo"', "paras[0]", 1, "paras[0]", 1],
574 ["paras[0].firstChild", 1, 47, '"foo"', "paras[0].firstChild", 1, "paras[0]", 1],
575 ["paras[0].firstChild", 2, 47, '"foo"', "paras[0].firstChild", 1, "paras[0]", 1],
576 ["paras[0].firstChild", 3, 47, '"foo"', "paras[0].firstChild", 1, "paras[0]", 1],
577 ["paras[0].firstChild", 1, 47, '"foo"', "paras[0]", 0, "paras[0].firstChild", 3],
578 ["paras[0].firstChild", 2, 47, '"foo"', "paras[0]", 0, "paras[0].firstChild", 3],
579 ["paras[0].firstChild", 3, 47, '"foo"', "paras[0]", 0, "paras[0].firstChild", 3]
580 );
581
582
583 // There are lots of ways to set data, so we pass a callback that does the
584 // actual setting.
585 function testDataChange(node, attr, op, rval, startContainer, startOffset, endCo ntainer, endOffset) {
586 return testReplaceDataAlgorithm(node, 0, node.length, op == "=" ? rval : node[ attr] + rval,
587 function() {
588 if (op == "=") {
589 node[attr] = rval;
590 } else if (op == "+=") {
591 node[attr] += rval;
592 } else {
593 throw "Unknown op " + op;
594 }
595 },
596 startContainer, startOffset, endContainer, endOffset);
597 }
598
599 var dataChangeTests = [];
600 var dataChangeTestAttrs = ["data", "textContent", "nodeValue"];
601 for (var i = 0; i < characterDataNodes.length; i++) {
602 var node = characterDataNodes[i];
603 var dataChangeTestRanges = [
604 [node, 0, node, 0],
605 [node, 0, node, 1],
606 [node, 1, node, 1],
607 [node, 0, node, node + ".length"],
608 [node, 1, node, node + ".length"],
609 [node, node + ".length", node, node + ".length"],
610 ];
611
612 for (var j = 0; j < dataChangeTestRanges.length; j++) {
613 for (var k = 0; k < dataChangeTestAttrs.length; k++) {
614 dataChangeTests.push([
615 node,
616 '"' + dataChangeTestAttrs[k] + '"',
617 '"="',
618 '""',
619 ].concat(dataChangeTestRanges[j]));
620
621 dataChangeTests.push([
622 node,
623 '"' + dataChangeTestAttrs[k] + '"',
624 '"="',
625 '"foo"',
626 ].concat(dataChangeTestRanges[j]));
627
628 dataChangeTests.push([
629 node,
630 '"' + dataChangeTestAttrs[k] + '"',
631 '"="',
632 node + "." + dataChangeTestAttrs[k],
633 ].concat(dataChangeTestRanges[j]));
634
635 dataChangeTests.push([
636 node,
637 '"' + dataChangeTestAttrs[k] + '"',
638 '"+="',
639 '""',
640 ].concat(dataChangeTestRanges[j]));
641
642 dataChangeTests.push([
643 node,
644 '"' + dataChangeTestAttrs[k] + '"',
645 '"+="',
646 '"foo"',
647 ].concat(dataChangeTestRanges[j]));
648
649 dataChangeTests.push([
650 node,
651 '"' + dataChangeTestAttrs[k] + '"',
652 '"+="',
653 node + "." + dataChangeTestAttrs[k]
654 ].concat(dataChangeTestRanges[j]));
655 }
656 }
657 }
658
659
660 // Now we test node insertions and deletions, as opposed to just data changes.
661 // To avoid loads of repetition, we define modifyForRemove() and
662 // modifyForInsert().
663
664 // If we were to remove removedNode from its parent, what would the boundary
665 // point [node, offset] become? Returns [new node, new offset]. Must be
666 // called BEFORE the node is actually removed, so its parent is not null. (If
667 // the parent is null, it will do nothing.)
668 function modifyForRemove(removedNode, point) {
669 var oldParent = removedNode.parentNode;
670 var oldIndex = indexOf(removedNode);
671 if (!oldParent) {
672 return point;
673 }
674
675 // "For each boundary point whose node is removed node or a descendant of
676 // it, set the boundary point to (old parent, old index)."
677 if (point[0] == removedNode || isDescendant(point[0], removedNode)) {
678 return [oldParent, oldIndex];
679 }
680
681 // "For each boundary point whose node is old parent and whose offset is
682 // greater than old index, subtract one from its offset."
683 if (point[0] == oldParent && point[1] > oldIndex) {
684 return [point[0], point[1] - 1];
685 }
686
687 return point;
688 }
689
690 // Update the given boundary point [node, offset] to account for the fact that
691 // insertedNode was just inserted into its current position. This must be
692 // called AFTER insertedNode was already inserted.
693 function modifyForInsert(insertedNode, point) {
694 // "For each boundary point whose node is the new parent of the affected
695 // node and whose offset is greater than the new index of the affected
696 // node, add one to the boundary point's offset."
697 if (point[0] == insertedNode.parentNode && point[1] > indexOf(insertedNode)) {
698 return [point[0], point[1] + 1];
699 }
700
701 return point;
702 }
703
704
705 function testInsertBefore(newParent, affectedNode, refNode, startContainer, star tOffset, endContainer, endOffset) {
706 var expectedStart = [startContainer, startOffset];
707 var expectedEnd = [endContainer, endOffset];
708
709 expectedStart = modifyForRemove(affectedNode, expectedStart);
710 expectedEnd = modifyForRemove(affectedNode, expectedEnd);
711
712 try {
713 newParent.insertBefore(affectedNode, refNode);
714 } catch (e) {
715 // For our purposes, assume that DOM Core is true -- i.e., ignore
716 // mutation events and similar.
717 return [startContainer, startOffset, endContainer, endOffset];
718 }
719
720 expectedStart = modifyForInsert(affectedNode, expectedStart);
721 expectedEnd = modifyForInsert(affectedNode, expectedEnd);
722
723 return expectedStart.concat(expectedEnd);
724 }
725
726 var insertBeforeTests = [
727 // Moving a node to its current position
728 ["testDiv", "paras[0]", "paras[1]", "paras[0]", 0, "paras[0]", 0],
729 ["testDiv", "paras[0]", "paras[1]", "paras[0]", 0, "paras[0]", 1],
730 ["testDiv", "paras[0]", "paras[1]", "paras[0]", 1, "paras[0]", 1],
731 ["testDiv", "paras[0]", "paras[1]", "testDiv", 0, "testDiv", 2],
732 ["testDiv", "paras[0]", "paras[1]", "testDiv", 1, "testDiv", 1],
733 ["testDiv", "paras[0]", "paras[1]", "testDiv", 1, "testDiv", 2],
734 ["testDiv", "paras[0]", "paras[1]", "testDiv", 2, "testDiv", 2],
735
736 // Stuff that actually moves something. Note that paras[0] and paras[1]
737 // are both children of testDiv.
738 ["paras[0]", "paras[1]", "paras[0].firstChild", "paras[0]", 0, "paras[0]", 0],
739 ["paras[0]", "paras[1]", "paras[0].firstChild", "paras[0]", 0, "paras[0]", 1],
740 ["paras[0]", "paras[1]", "paras[0].firstChild", "paras[0]", 1, "paras[0]", 1],
741 ["paras[0]", "paras[1]", "paras[0].firstChild", "testDiv", 0, "testDiv", 1],
742 ["paras[0]", "paras[1]", "paras[0].firstChild", "testDiv", 0, "testDiv", 2],
743 ["paras[0]", "paras[1]", "paras[0].firstChild", "testDiv", 1, "testDiv", 1],
744 ["paras[0]", "paras[1]", "paras[0].firstChild", "testDiv", 1, "testDiv", 2],
745 ["paras[0]", "paras[1]", "null", "paras[0]", 0, "paras[0]", 0],
746 ["paras[0]", "paras[1]", "null", "paras[0]", 0, "paras[0]", 1],
747 ["paras[0]", "paras[1]", "null", "paras[0]", 1, "paras[0]", 1],
748 ["paras[0]", "paras[1]", "null", "testDiv", 0, "testDiv", 1],
749 ["paras[0]", "paras[1]", "null", "testDiv", 0, "testDiv", 2],
750 ["paras[0]", "paras[1]", "null", "testDiv", 1, "testDiv", 1],
751 ["paras[0]", "paras[1]", "null", "testDiv", 1, "testDiv", 2],
752 ["foreignDoc", "detachedComment", "foreignDoc.documentElement", "foreignDoc", 0, "foreignDoc", 0],
753 ["foreignDoc", "detachedComment", "foreignDoc.documentElement", "foreignDoc", 0, "foreignDoc", 1],
754 ["foreignDoc", "detachedComment", "foreignDoc.documentElement", "foreignDoc", 0, "foreignDoc", 2],
755 ["foreignDoc", "detachedComment", "foreignDoc.documentElement", "foreignDoc", 1, "foreignDoc", 1],
756 ["foreignDoc", "detachedComment", "foreignDoc.doctype", "foreignDoc", 0, "fore ignDoc", 0],
757 ["foreignDoc", "detachedComment", "foreignDoc.doctype", "foreignDoc", 0, "fore ignDoc", 1],
758 ["foreignDoc", "detachedComment", "foreignDoc.doctype", "foreignDoc", 0, "fore ignDoc", 2],
759 ["foreignDoc", "detachedComment", "foreignDoc.doctype", "foreignDoc", 1, "fore ignDoc", 1],
760 ["foreignDoc", "detachedComment", "null", "foreignDoc", 0, "foreignDoc", 1],
761 ["paras[0]", "xmlTextNode", "paras[0].firstChild", "paras[0]", 0, "paras[0]", 0],
762 ["paras[0]", "xmlTextNode", "paras[0].firstChild", "paras[0]", 0, "paras[0]", 1],
763 ["paras[0]", "xmlTextNode", "paras[0].firstChild", "paras[0]", 1, "paras[0]", 1],
764
765 // Stuff that throws exceptions
766 ["paras[0]", "paras[0]", "paras[0].firstChild", "paras[0]", 0, "paras[0]", 1],
767 ["paras[0]", "testDiv", "paras[0].firstChild", "paras[0]", 0, "paras[0]", 1],
768 ["paras[0]", "document", "paras[0].firstChild", "paras[0]", 0, "paras[0]", 1],
769 ["paras[0]", "foreignDoc", "paras[0].firstChild", "paras[0]", 0, "paras[0]", 1 ],
770 ["paras[0]", "document.doctype", "paras[0].firstChild", "paras[0]", 0, "paras[ 0]", 1],
771 ];
772
773
774 function testReplaceChild(newParent, newChild, oldChild, startContainer, startOf fset, endContainer, endOffset) {
775 var expectedStart = [startContainer, startOffset];
776 var expectedEnd = [endContainer, endOffset];
777
778 expectedStart = modifyForRemove(oldChild, expectedStart);
779 expectedEnd = modifyForRemove(oldChild, expectedEnd);
780
781 if (newChild != oldChild) {
782 // Don't do this twice, if they're the same!
783 expectedStart = modifyForRemove(newChild, expectedStart);
784 expectedEnd = modifyForRemove(newChild, expectedEnd);
785 }
786
787 try {
788 newParent.replaceChild(newChild, oldChild);
789 } catch (e) {
790 return [startContainer, startOffset, endContainer, endOffset];
791 }
792
793 expectedStart = modifyForInsert(newChild, expectedStart);
794 expectedEnd = modifyForInsert(newChild, expectedEnd);
795
796 return expectedStart.concat(expectedEnd);
797 }
798
799 var replaceChildTests = [
800 // Moving a node to its current position. Doesn't match most browsers'
801 // behavior, but we probably want to keep the spec the same anyway:
802 // https://bugzilla.mozilla.org/show_bug.cgi?id=647603
803 ["testDiv", "paras[0]", "paras[0]", "paras[0]", 0, "paras[0]", 0],
804 ["testDiv", "paras[0]", "paras[0]", "paras[0]", 0, "paras[0]", 1],
805 ["testDiv", "paras[0]", "paras[0]", "paras[0]", 1, "paras[0]", 1],
806 ["testDiv", "paras[0]", "paras[0]", "testDiv", 0, "testDiv", 2],
807 ["testDiv", "paras[0]", "paras[0]", "testDiv", 1, "testDiv", 1],
808 ["testDiv", "paras[0]", "paras[0]", "testDiv", 1, "testDiv", 2],
809 ["testDiv", "paras[0]", "paras[0]", "testDiv", 2, "testDiv", 2],
810
811 // Stuff that actually moves something.
812 ["paras[0]", "paras[1]", "paras[0].firstChild", "paras[0]", 0, "paras[0]", 0],
813 ["paras[0]", "paras[1]", "paras[0].firstChild", "paras[0]", 0, "paras[0]", 1],
814 ["paras[0]", "paras[1]", "paras[0].firstChild", "paras[0]", 1, "paras[0]", 1],
815 ["paras[0]", "paras[1]", "paras[0].firstChild", "testDiv", 0, "testDiv", 1],
816 ["paras[0]", "paras[1]", "paras[0].firstChild", "testDiv", 0, "testDiv", 2],
817 ["paras[0]", "paras[1]", "paras[0].firstChild", "testDiv", 1, "testDiv", 1],
818 ["paras[0]", "paras[1]", "paras[0].firstChild", "testDiv", 1, "testDiv", 2],
819 ["foreignDoc", "detachedComment", "foreignDoc.documentElement", "foreignDoc", 0, "foreignDoc", 0],
820 ["foreignDoc", "detachedComment", "foreignDoc.documentElement", "foreignDoc", 0, "foreignDoc", 1],
821 ["foreignDoc", "detachedComment", "foreignDoc.documentElement", "foreignDoc", 0, "foreignDoc", 2],
822 ["foreignDoc", "detachedComment", "foreignDoc.documentElement", "foreignDoc", 1, "foreignDoc", 1],
823 ["foreignDoc", "detachedComment", "foreignDoc.doctype", "foreignDoc", 0, "fore ignDoc", 0],
824 ["foreignDoc", "detachedComment", "foreignDoc.doctype", "foreignDoc", 0, "fore ignDoc", 1],
825 ["foreignDoc", "detachedComment", "foreignDoc.doctype", "foreignDoc", 0, "fore ignDoc", 2],
826 ["foreignDoc", "detachedComment", "foreignDoc.doctype", "foreignDoc", 1, "fore ignDoc", 1],
827 ["paras[0]", "xmlTextNode", "paras[0].firstChild", "paras[0]", 0, "paras[0]", 0],
828 ["paras[0]", "xmlTextNode", "paras[0].firstChild", "paras[0]", 0, "paras[0]", 1],
829 ["paras[0]", "xmlTextNode", "paras[0].firstChild", "paras[0]", 1, "paras[0]", 1],
830
831 // Stuff that throws exceptions
832 ["paras[0]", "paras[0]", "paras[0].firstChild", "paras[0]", 0, "paras[0]", 1],
833 ["paras[0]", "testDiv", "paras[0].firstChild", "paras[0]", 0, "paras[0]", 1],
834 ["paras[0]", "document", "paras[0].firstChild", "paras[0]", 0, "paras[0]", 1],
835 ["paras[0]", "foreignDoc", "paras[0].firstChild", "paras[0]", 0, "paras[0]", 1 ],
836 ["paras[0]", "document.doctype", "paras[0].firstChild", "paras[0]", 0, "paras[ 0]", 1],
837 ];
838
839
840 function testAppendChild(newParent, affectedNode, startContainer, startOffset, e ndContainer, endOffset) {
841 var expectedStart = [startContainer, startOffset];
842 var expectedEnd = [endContainer, endOffset];
843
844 expectedStart = modifyForRemove(affectedNode, expectedStart);
845 expectedEnd = modifyForRemove(affectedNode, expectedEnd);
846
847 try {
848 newParent.appendChild(affectedNode);
849 } catch (e) {
850 return [startContainer, startOffset, endContainer, endOffset];
851 }
852
853 // These two lines will actually never do anything, if you think about it,
854 // but let's leave them in so correctness is more obvious.
855 expectedStart = modifyForInsert(affectedNode, expectedStart);
856 expectedEnd = modifyForInsert(affectedNode, expectedEnd);
857
858 return expectedStart.concat(expectedEnd);
859 }
860
861 var appendChildTests = [
862 // Moving a node to its current position
863 ["testDiv", "testDiv.lastChild", "testDiv.lastChild", 0, "testDiv.lastChild", 0],
864 ["testDiv", "testDiv.lastChild", "testDiv.lastChild", 0, "testDiv.lastChild", 1],
865 ["testDiv", "testDiv.lastChild", "testDiv.lastChild", 1, "testDiv.lastChild", 1],
866 ["testDiv", "testDiv.lastChild", "testDiv", "testDiv.childNodes.length - 2", " testDiv", "testDiv.childNodes.length"],
867 ["testDiv", "testDiv.lastChild", "testDiv", "testDiv.childNodes.length - 2", " testDiv", "testDiv.childNodes.length - 1"],
868 ["testDiv", "testDiv.lastChild", "testDiv", "testDiv.childNodes.length - 1", " testDiv", "testDiv.childNodes.length"],
869 ["testDiv", "testDiv.lastChild", "testDiv", "testDiv.childNodes.length - 1", " testDiv", "testDiv.childNodes.length - 1"],
870 ["testDiv", "testDiv.lastChild", "testDiv", "testDiv.childNodes.length", "test Div", "testDiv.childNodes.length"],
871 ["detachedDiv", "detachedDiv.lastChild", "detachedDiv.lastChild", 0, "detached Div.lastChild", 0],
872 ["detachedDiv", "detachedDiv.lastChild", "detachedDiv.lastChild", 0, "detached Div.lastChild", 1],
873 ["detachedDiv", "detachedDiv.lastChild", "detachedDiv.lastChild", 1, "detached Div.lastChild", 1],
874 ["detachedDiv", "detachedDiv.lastChild", "detachedDiv", "detachedDiv.childNode s.length - 2", "detachedDiv", "detachedDiv.childNodes.length"],
875 ["detachedDiv", "detachedDiv.lastChild", "detachedDiv", "detachedDiv.childNode s.length - 2", "detachedDiv", "detachedDiv.childNodes.length - 1"],
876 ["detachedDiv", "detachedDiv.lastChild", "detachedDiv", "detachedDiv.childNode s.length - 1", "detachedDiv", "detachedDiv.childNodes.length"],
877 ["detachedDiv", "detachedDiv.lastChild", "detachedDiv", "detachedDiv.childNode s.length - 1", "detachedDiv", "detachedDiv.childNodes.length - 1"],
878 ["detachedDiv", "detachedDiv.lastChild", "detachedDiv", "detachedDiv.childNode s.length", "detachedDiv", "detachedDiv.childNodes.length"],
879
880 // Stuff that actually moves something
881 ["paras[0]", "paras[1]", "paras[0]", 0, "paras[0]", 0],
882 ["paras[0]", "paras[1]", "paras[0]", 0, "paras[0]", 1],
883 ["paras[0]", "paras[1]", "paras[0]", 1, "paras[0]", 1],
884 ["paras[0]", "paras[1]", "testDiv", 0, "testDiv", 1],
885 ["paras[0]", "paras[1]", "testDiv", 0, "testDiv", 2],
886 ["paras[0]", "paras[1]", "testDiv", 1, "testDiv", 1],
887 ["paras[0]", "paras[1]", "testDiv", 1, "testDiv", 2],
888 ["foreignDoc", "detachedComment", "foreignDoc", "foreignDoc.childNodes.length - 1", "foreignDoc", "foreignDoc.childNodes.length"],
889 ["foreignDoc", "detachedComment", "foreignDoc", "foreignDoc.childNodes.length - 1", "foreignDoc", "foreignDoc.childNodes.length - 1"],
890 ["foreignDoc", "detachedComment", "foreignDoc", "foreignDoc.childNodes.length" , "foreignDoc", "foreignDoc.childNodes.length"],
891 ["foreignDoc", "detachedComment", "detachedComment", 0, "detachedComment", 5],
892 ["paras[0]", "xmlTextNode", "paras[0]", 0, "paras[0]", 0],
893 ["paras[0]", "xmlTextNode", "paras[0]", 0, "paras[0]", 1],
894 ["paras[0]", "xmlTextNode", "paras[0]", 1, "paras[0]", 1],
895
896 // Stuff that throws exceptions
897 ["paras[0]", "paras[0]", "paras[0]", 0, "paras[0]", 1],
898 ["paras[0]", "testDiv", "paras[0]", 0, "paras[0]", 1],
899 ["paras[0]", "document", "paras[0]", 0, "paras[0]", 1],
900 ["paras[0]", "foreignDoc", "paras[0]", 0, "paras[0]", 1],
901 ["paras[0]", "document.doctype", "paras[0]", 0, "paras[0]", 1],
902 ];
903
904
905 function testRemoveChild(affectedNode, startContainer, startOffset, endContainer , endOffset) {
906 var expectedStart = [startContainer, startOffset];
907 var expectedEnd = [endContainer, endOffset];
908
909 expectedStart = modifyForRemove(affectedNode, expectedStart);
910 expectedEnd = modifyForRemove(affectedNode, expectedEnd);
911
912 // We don't test cases where the parent is wrong, so this should never
913 // throw an exception.
914 affectedNode.parentNode.removeChild(affectedNode);
915
916 return expectedStart.concat(expectedEnd);
917 }
918
919 var removeChildTests = [
920 ["paras[0]", "paras[0]", 0, "paras[0]", 0],
921 ["paras[0]", "paras[0]", 0, "paras[0]", 1],
922 ["paras[0]", "paras[0]", 1, "paras[0]", 1],
923 ["paras[0]", "testDiv", 0, "testDiv", 0],
924 ["paras[0]", "testDiv", 0, "testDiv", 1],
925 ["paras[0]", "testDiv", 1, "testDiv", 1],
926 ["paras[0]", "testDiv", 0, "testDiv", 2],
927 ["paras[0]", "testDiv", 1, "testDiv", 2],
928 ["paras[0]", "testDiv", 2, "testDiv", 2],
929
930 ["foreignDoc.documentElement", "foreignDoc", 0, "foreignDoc", "foreignDoc.chil dNodes.length"],
931 ];
932
933
934 // Finally run everything. All grouped together at the end so that I can
935 // easily comment out some of them, so I don't have to wait for all test types
936 // to debug only some of them.
937 doTests(splitTextTests, function(params) { return params[0] + ".splitText(" + pa rams[1] + ")" }, testSplitText);
938 doTests(insertDataTests, function(params) { return params[0] + ".insertData(" + params[1] + ", " + params[2] + ")" }, testInsertData);
939 doTests(appendDataTests, function(params) { return params[0] + ".appendData(" + params[1] + ")" }, testAppendData);
940 doTests(deleteDataTests, function(params) { return params[0] + ".deleteData(" + params[1] + ", " + params[2] + ")" }, testDeleteData);
941 doTests(replaceDataTests, function(params) { return params[0] + ".replaceData(" + params[1] + ", " + params[2] + ", " + params[3] + ")" }, testReplaceData);
942 doTests(dataChangeTests, function(params) { return params[0] + "." + eval(params [1]) + " " + eval(params[2]) + ' ' + params[3] }, testDataChange);
943 doTests(insertBeforeTests, function(params) { return params[0] + ".insertBefore( " + params[1] + ", " + params[2] + ")" }, testInsertBefore);
944 doTests(replaceChildTests, function(params) { return params[0] + ".replaceChild( " + params[1] + ", " + params[2] + ")" }, testReplaceChild);
945 doTests(appendChildTests, function(params) { return params[0] + ".appendChild(" + params[1] + ")" }, testAppendChild);
946 doTests(removeChildTests, function(params) { return params[0] + ".parentNode.rem oveChild(" + params[0] + ")" }, testRemoveChild);
947
948
949 testDiv.style.display = "none";
950 </script>
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698