r103360 MediaWiki - Code Review archive

Repository:MediaWiki
Revision:r103359‎ | r103360 | r103361 >
Date:19:35, 16 November 2011
Author:tparscal
Status:ok
Tags:
Comment:
Renamed es.DocumentNode.test to es.DocumentBranchNode.test to reflect it's contents
Modified paths:
  • /trunk/extensions/VisualEditor/tests/es/es.DocumentBranchNode.test.js (added) (history)
  • /trunk/extensions/VisualEditor/tests/es/es.DocumentNode.test.js (deleted) (history)
  • /trunk/extensions/VisualEditor/tests/es/index.html (modified) (history)

Diff [purge]

Index: trunk/extensions/VisualEditor/tests/es/es.DocumentNode.test.js
@@ -1,1079 +0,0 @@
2 -module( 'es/bases' );
3 -
4 -/* Stubs */
5 -
6 -function DocumentBranchNodeStub( items, name, size ) {
7 - // Inheritance
8 - es.DocumentBranchNode.call( this, items );
9 -
10 - // Properties
11 - this.name = name;
12 - this.size = size;
13 -}
14 -
15 -DocumentBranchNodeStub.prototype.getContentLength = function() {
16 - return this.size;
17 -};
18 -
19 -DocumentBranchNodeStub.prototype.getElementLength = function() {
20 - // Mimic document data which has an opening and closing around the content
21 - return this.size + 2;
22 -};
23 -
24 -es.extendClass( DocumentBranchNodeStub, es.DocumentBranchNode );
25 -
26 -/* Tests */
27 -
28 -test( 'es.DocumentBranchNodeStub.getElementLength', 1, function() {
29 - // Test 1
30 - strictEqual(
31 - ( new DocumentBranchNodeStub( [], 'a', 0 ) ).getElementLength(),
32 - 2,
33 - 'DocumentBranchNodeStub.getElementLength() returns initialized length plus 2 for elements'
34 - );
35 -} );
36 -
37 -// Common stubs
38 -var a = new DocumentBranchNodeStub( [], 'a', 0 ),
39 - b = new DocumentBranchNodeStub( [], 'b', 1 ),
40 - c = new DocumentBranchNodeStub( [], 'c', 2 ),
41 - d = new DocumentBranchNodeStub( [], 'd', 3 ),
42 - e = new DocumentBranchNodeStub( [], 'e', 4 ),
43 - root1 = new DocumentBranchNodeStub( [a, b, c, d, e], 'root1', 20 );
44 -
45 -test( 'es.DocumentBranchNode.getRangeFromNode', 6, function() {
46 - // Tests 1 .. 6
47 - var getRangeFromNodeTests = [
48 - { 'input': a, 'output': new es.Range( 0, 2 ) },
49 - { 'input': b, 'output': new es.Range( 2, 5 ) },
50 - { 'input': c, 'output': new es.Range( 5, 9 ) },
51 - { 'input': d, 'output': new es.Range( 9, 14 ) },
52 - { 'input': e, 'output': new es.Range( 14, 20 ) },
53 - { 'input': null, 'output': null }
54 - ];
55 - for ( var i = 0; i < getRangeFromNodeTests.length; i++ ) {
56 - deepEqual(
57 - root1.getRangeFromNode( getRangeFromNodeTests[i].input ),
58 - getRangeFromNodeTests[i].output,
59 - 'getRangeFromNode returns the correct range or null if item is not found'
60 - );
61 - }
62 -} );
63 -
64 -test( 'es.DocumentBranchNode.getNodeFromOffset', 23, function() {
65 - // Tests 1 .. 22
66 - var getNodeFromOffsetTests = [
67 - // Test 1 - |[<a></a><b> </b><c> </c><d> </d><e> </e>]
68 - { 'input': -1, 'output': null },
69 - // Test 2 - [|<a></a><b> </b><c> </c><d> </d><e> </e>]
70 - { 'input': 0, 'output': root1 },
71 - // Test 3 - [<a>|</a><b> </b><c> </c><d> </d><e> </e>]
72 - { 'input': 1, 'output': a },
73 - // Test 4 - [<a></a>|<b> </b><c> </c><d> </d><e> </e>]
74 - { 'input': 2, 'output': root1 },
75 - // Test 5 - [<a></a><b>| </b><c> </c><d> </d><e> </e>]
76 - { 'input': 3, 'output': b },
77 - // Test 6 - [<a></a><b> |</b><c> </c><d> </d><e> </e>]
78 - { 'input': 4, 'output': b },
79 - // Test 7 - [<a></a><b> </b>|<c> </c><d> </d><e> </e>]
80 - { 'input': 5, 'output': root1 },
81 - // Test 8 - [<a></a><b> </b><c>| </c><d> </d><e> </e>]
82 - { 'input': 6, 'output': c },
83 - // Test 9 - [<a></a><b> </b><c> | </c><d> </d><e> </e>]
84 - { 'input': 7, 'output': c },
85 - // Test 10 - [<a></a><b> </b><c> |</c><d> </d><e> </e>]
86 - { 'input': 8, 'output': c },
87 - // Test 11 - [<a></a><b> </b><c> </c>|<d> </d><e> </e>]
88 - { 'input': 9, 'output': root1 },
89 - // Test 12 - [<a></a><b> </b><c> </c><d>| </d><e> </e>]
90 - { 'input': 10, 'output': d },
91 - // Test 13 - [<a></a><b> </b><c> </c><d> | </d><e> </e>]
92 - { 'input': 11, 'output': d },
93 - // Test 14 - [<a></a><b> </b><c> </c><d> | </d><e> </e>]
94 - { 'input': 12, 'output': d },
95 - // Test 15 - [<a></a><b> </b><c> </c><d> |</d><e> </e>]
96 - { 'input': 13, 'output': d },
97 - // Test 16 - [<a></a><b> </b><c> </c><d> </d>|<e> </e>]
98 - { 'input': 14, 'output': root1 },
99 - // Test 17 - [<a></a><b> </b><c> </c><d> </d><e>| </e>]
100 - { 'input': 15, 'output': e },
101 - // Test 18 - [<a></a><b> </b><c> </c><d> </d><e> | </e>]
102 - { 'input': 16, 'output': e },
103 - // Test 19 - [<a></a><b> </b><c> </c><d> </d><e> | </e>]
104 - { 'input': 17, 'output': e },
105 - // Test 20 - [<a></a><b> </b><c> </c><d> </d><e> | </e>]
106 - { 'input': 18, 'output': e },
107 - // Test 21 - [<a></a><b> </b><c> </c><d> </d><e> |</e>]
108 - { 'input': 19, 'output': e },
109 - // Test 22 - [<a></a><b> </b><c> </c><d> </d><e> </e>|]
110 - { 'input': 20, 'output': root1 },
111 - // Test 22 - [<a></a><b> </b><c> </c><d> </d><e> </e>]|
112 - { 'input': 21, 'output': null }
113 - ];
114 - for ( var i = 0; i < getNodeFromOffsetTests.length; i++ ) {
115 - ok(
116 - root1.getNodeFromOffset( getNodeFromOffsetTests[i].input ) ===
117 - getNodeFromOffsetTests[i].output,
118 - 'getNodeFromOffset finds the right item or returns null when out of range ' +
119 - '(' + getNodeFromOffsetTests[i].input + ')'
120 - );
121 - }
122 -} );
123 -
124 -test( 'es.DocumentBranchNode.getOffsetFromNode', 6, function() {
125 - // Tests 1 .. 6
126 - var getOffsetFromNodeTests = [
127 - { 'input': a, 'output': 0 },
128 - { 'input': b, 'output': 2 },
129 - { 'input': c, 'output': 5 },
130 - { 'input': d, 'output': 9 },
131 - { 'input': e, 'output': 14 },
132 - { 'input': null, 'output': -1 }
133 - ];
134 - for ( var i = 0; i < getOffsetFromNodeTests.length; i++ ) {
135 - strictEqual(
136 - root1.getOffsetFromNode( getOffsetFromNodeTests[i].input ),
137 - getOffsetFromNodeTests[i].output,
138 - 'getOffsetFromNode finds the right offset or returns -1 when node is not found'
139 - );
140 - }
141 -} );
142 -
143 -test( 'es.DocumentBranchNode.selectNodes', 75, function() {
144 -
145 - // selectNodes tests
146 -
147 - // <f> a b c d e f g h </f> <g> a b c d e f g h </g> <h> a b c d e f g h </h>
148 - //^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^
149 - //0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0
150 - // 0 1 2 3 4 5 6 7 8 0 1 2 3 4 5 6 7 8 0 1 2 3 4 5 6 7 8
151 - var f = new DocumentBranchNodeStub( [], 'f', 8 ),
152 - g = new DocumentBranchNodeStub( [], 'g', 8 ),
153 - h = new DocumentBranchNodeStub( [], 'h', 8 ),
154 - root2 = new DocumentBranchNodeStub( [f, g, h], 'root2', 30 ),
155 - big = es.DocumentModel.newFromPlainObject( esTest.obj );
156 -
157 - // Tests 1 ... 22
158 - // Possible positions are:
159 - // * before beginning
160 - // * at beginning
161 - // * middle
162 - // * at end
163 - // * past end
164 - var selectNodesTests = [
165 - // Complete set of combinations within the same node:
166 -
167 - // Test 1
168 - {
169 - 'node': root2,
170 - 'input': new es.Range( 0, 0 ),
171 - 'output': [],
172 - 'desc': 'Zero-length range before the beginning of a node'
173 - },
174 - // Test 2
175 - {
176 - 'node': root2,
177 - 'input': new es.Range( 0, 1 ),
178 - 'output': [{ 'node': f, 'range': new es.Range( 0, 0 ), 'globalRange': new es.Range( 1, 1 ) }],
179 - 'desc': 'Range starting before the beginning of a node and ending at the beginning'
180 - },
181 - // Test 3
182 - {
183 - 'node': root2,
184 - 'input': new es.Range( 10, 15 ),
185 - 'output': [{ 'node': g, 'range': new es.Range( 0, 4 ), 'globalRange': new es.Range( 11, 15 ) }],
186 - 'desc': 'Range starting before the beginning of a node and ending in the middle'
187 - },
188 - // Test 4
189 - {
190 - 'node': root2,
191 - 'input': new es.Range( 20, 29 ),
192 - 'output': [{ 'node': h, 'range': new es.Range( 0, 8 ), 'globalRange': new es.Range( 21, 29 ) }],
193 - 'desc': 'Range starting before the beginning of a node and ending at the end'
194 - },
195 - // Test 5
196 - {
197 - 'node': root2,
198 - 'input': new es.Range( 0, 10 ),
199 - 'output': [{ 'node': f, 'globalRange': new es.Range( 0, 10 ) } ],
200 - 'desc': 'Range starting before the beginning of a node and ending past the end'
201 - },
202 - // Test 6
203 - {
204 - 'node': root2,
205 - 'input': new es.Range( 11, 11 ),
206 - 'output': [{ 'node': g, 'range': new es.Range( 0, 0 ), 'globalRange': new es.Range( 11, 11 ) }],
207 - 'desc': 'Zero-length range at the beginning of a node'
208 - },
209 - // Test 7
210 - {
211 - 'node': root2,
212 - 'input': new es.Range( 21, 26 ),
213 - 'output': [{ 'node': h, 'range': new es.Range( 0, 5 ), 'globalRange': new es.Range( 21, 26 ) }],
214 - 'desc': 'Range starting at the beginning of a node and ending in the middle'
215 - },
216 - // Test 8
217 - {
218 - 'node': root2,
219 - 'input': new es.Range( 1, 9 ),
220 - 'output': [{ 'node': f, 'range': new es.Range( 0, 8 ), 'globalRange': new es.Range( 1, 9 ) }],
221 - 'desc': 'Range starting at the beginning of a node and ending at the end'
222 - },
223 - // Test 9
224 - {
225 - 'node': root2,
226 - 'input': new es.Range( 11, 20 ),
227 - 'output': [{ 'node': g, 'range': new es.Range( 0, 8 ), 'globalRange': new es.Range( 11, 19 ) }],
228 - 'desc': 'Range starting at the beginning of a node and ending past the end'
229 - },
230 - // Test 10
231 - {
232 - 'node': root2,
233 - 'input': new es.Range( 22, 22 ),
234 - 'output': [{ 'node': h, 'range': new es.Range( 1, 1 ), 'globalRange': new es.Range( 22, 22 ) }],
235 - 'desc': 'Zero-length range in the middle of a node'
236 - },
237 - // Test 11
238 - {
239 - 'node': root2,
240 - 'input': new es.Range( 2, 7 ),
241 - 'output': [{ 'node': f, 'range': new es.Range( 1, 6 ), 'globalRange': new es.Range( 2, 7 ) }],
242 - 'desc': 'Range starting and ending in the middle of the same node'
243 - },
244 - // Test 12
245 - {
246 - 'node': root2,
247 - 'input': new es.Range( 13, 19 ),
248 - 'output': [{ 'node': g, 'range': new es.Range( 2, 8 ), 'globalRange': new es.Range( 13, 19 ) }],
249 - 'desc': 'Range starting in the middle of a node and ending at the end'
250 - },
251 - // Test 13
252 - {
253 - 'node': root2,
254 - 'input': new es.Range( 24, 30 ),
255 - 'output': [{ 'node': h, 'range': new es.Range( 3, 8 ), 'globalRange': new es.Range( 24, 29 ) }],
256 - 'desc': 'Range starting in the middle of a node and ending past the end'
257 - },
258 - // Test 14
259 - {
260 - 'node': root2,
261 - 'input': new es.Range( 9, 9 ),
262 - 'output': [{ 'node': f, 'range': new es.Range( 8, 8 ), 'globalRange': new es.Range( 9, 9 ) }],
263 - 'desc': 'Zero-length range at the end of a node'
264 - },
265 - // Test 15
266 - {
267 - 'node': root2,
268 - 'input': new es.Range( 19, 20 ),
269 - 'output': [{ 'node': g, 'range': new es.Range( 8, 8 ), 'globalRange': new es.Range( 19, 19 ) }],
270 - 'desc': 'Range starting at the end of a node and ending past the end'
271 - },
272 - // Test 16
273 - {
274 - 'node': root2,
275 - 'input': new es.Range( 30, 30 ),
276 - 'output': [],
277 - 'desc': 'Zero-length range past the end of a node'
278 - },
279 - // Test 17
280 - {
281 - 'node': root2,
282 - 'input': new es.Range( 20, 20 ),
283 - 'output': [],
284 - 'desc': 'Zero-length range between two nodes'
285 - },
286 -
287 - // Complete set of combinations for cross-node selections. Generated with help of a script
288 -
289 - // Test 18
290 - {
291 - 'node': root2,
292 - 'input': new es.Range( 0, 11 ),
293 - 'output': [
294 - { 'node': f, 'globalRange': new es.Range( 0, 10 ) },
295 - { 'node': g, 'range': new es.Range( 0, 0 ), 'globalRange': new es.Range( 11, 11 ) }
296 - ],
297 - 'desc': 'Range starting before the beginning of the first node and ending at the beginning of the second node'
298 - },
299 - // Test 19
300 - {
301 - 'node': root2,
302 - 'input': new es.Range( 0, 14 ),
303 - 'output': [
304 - { 'node': f, 'globalRange': new es.Range( 0, 10 ) },
305 - { 'node': g, 'range': new es.Range( 0, 3 ), 'globalRange': new es.Range( 11, 14 ) }
306 - ],
307 - 'desc': 'Range starting before the beginning of the first node and ending in the middle of the second node'
308 - },
309 - // Test 20
310 - {
311 - 'node': root2,
312 - 'input': new es.Range( 0, 19 ),
313 - 'output': [
314 - { 'node': f, 'globalRange': new es.Range( 0, 10 ) },
315 - { 'node': g, 'range': new es.Range( 0, 8 ), 'globalRange': new es.Range( 11, 19 ) }
316 - ],
317 - 'desc': 'Range starting before the beginning of the first node and ending at the end of the second node'
318 - },
319 - // Test 21
320 - {
321 - 'node': root2,
322 - 'input': new es.Range( 0, 20 ),
323 - 'output': [
324 - { 'node': f, 'globalRange': new es.Range( 0, 10 ) },
325 - { 'node': g, 'globalRange': new es.Range( 10, 20 ) }
326 - ],
327 - 'desc': 'Range starting before the beginning of the first node and ending between the second and the third node'
328 - },
329 - // Test 22
330 - {
331 - 'node': root2,
332 - 'input': new es.Range( 0, 21 ),
333 - 'output': [
334 - { 'node': f, 'globalRange': new es.Range( 0, 10 ) },
335 - { 'node': g, 'globalRange': new es.Range( 10, 20 ) },
336 - { 'node': h, 'range': new es.Range( 0, 0 ), 'globalRange': new es.Range( 21, 21 ) }
337 - ],
338 - 'desc': 'Range starting before the beginning of the first node and ending at the beginning of the third node'
339 - },
340 - // Test 23
341 - {
342 - 'node': root2,
343 - 'input': new es.Range( 0, 27 ),
344 - 'output': [
345 - { 'node': f, 'globalRange': new es.Range( 0, 10 ) },
346 - { 'node': g, 'globalRange': new es.Range( 10, 20 ) },
347 - { 'node': h, 'range': new es.Range( 0, 6 ), 'globalRange': new es.Range( 21, 27 ) }
348 - ],
349 - 'desc': 'Range starting before the beginning of the first node and ending in the middle of the third node'
350 - },
351 - // Test 24
352 - {
353 - 'node': root2,
354 - 'input': new es.Range( 0, 29 ),
355 - 'output': [
356 - { 'node': f, 'globalRange': new es.Range( 0, 10 ) },
357 - { 'node': g, 'globalRange': new es.Range( 10, 20 ) },
358 - { 'node': h, 'range': new es.Range( 0, 8 ), 'globalRange': new es.Range( 21, 29 ) }
359 - ],
360 - 'desc': 'Range starting before the beginning of the first node and ending at the end of the third node'
361 - },
362 - // Test 25
363 - {
364 - 'node': root2,
365 - 'input': new es.Range( 0, 30 ),
366 - 'output': [
367 - { 'node': f, 'globalRange': new es.Range( 0, 10 ) },
368 - { 'node': g, 'globalRange': new es.Range( 10, 20 ) },
369 - { 'node': h, 'globalRange': new es.Range( 20, 30 ) }
370 - ],
371 - 'desc': 'Range starting before the beginning of the first node and ending past the end of the third node'
372 - },
373 - // Test 26
374 - {
375 - 'node': root2,
376 - 'input': new es.Range( 1, 11 ),
377 - 'output': [
378 - { 'node': f, 'range': new es.Range( 0, 8 ), 'globalRange': new es.Range( 1, 9 ) },
379 - { 'node': g, 'range': new es.Range( 0, 0 ), 'globalRange': new es.Range( 11, 11 ) }
380 - ],
381 - 'desc': 'Range starting at the beginning of the first node and ending at the beginning of the second node'
382 - },
383 - // Test 27
384 - {
385 - 'node': root2,
386 - 'input': new es.Range( 1, 14 ),
387 - 'output': [
388 - { 'node': f, 'range': new es.Range( 0, 8 ), 'globalRange': new es.Range( 1, 9 ) },
389 - { 'node': g, 'range': new es.Range( 0, 3 ), 'globalRange': new es.Range( 11, 14 ) }
390 - ],
391 - 'desc': 'Range starting at the beginning of the first node and ending in the middle of the second node'
392 - },
393 - // Test 28
394 - {
395 - 'node': root2,
396 - 'input': new es.Range( 1, 19 ),
397 - 'output': [
398 - { 'node': f, 'range': new es.Range( 0, 8 ), 'globalRange': new es.Range( 1, 9 ) },
399 - { 'node': g, 'range': new es.Range( 0, 8 ), 'globalRange': new es.Range( 11, 19 ) }
400 - ],
401 - 'desc': 'Range starting at the beginning of the first node and ending at the end of the second node'
402 - },
403 - // Test 29
404 - {
405 - 'node': root2,
406 - 'input': new es.Range( 1, 20 ),
407 - 'output': [
408 - { 'node': f, 'range': new es.Range( 0, 8 ), 'globalRange': new es.Range( 1, 9 ) },
409 - { 'node': g, 'globalRange': new es.Range( 10, 20 ) }
410 - ],
411 - 'desc': 'Range starting at the beginning of the first node and ending between the second and the third node'
412 - },
413 - // Test 30
414 - {
415 - 'node': root2,
416 - 'input': new es.Range( 1, 21 ),
417 - 'output': [
418 - { 'node': f, 'range': new es.Range( 0, 8 ), 'globalRange': new es.Range( 1, 9 ) },
419 - { 'node': g, 'globalRange': new es.Range( 10, 20 ) },
420 - { 'node': h, 'range': new es.Range( 0, 0 ), 'globalRange': new es.Range( 21, 21 ) }
421 - ],
422 - 'desc': 'Range starting at the beginning of the first node and ending at the beginning of the third node'
423 - },
424 - // Test 31
425 - {
426 - 'node': root2,
427 - 'input': new es.Range( 1, 27 ),
428 - 'output': [
429 - { 'node': f, 'range': new es.Range( 0, 8 ), 'globalRange': new es.Range( 1, 9 ) },
430 - { 'node': g, 'globalRange': new es.Range( 10, 20 ) },
431 - { 'node': h, 'range': new es.Range( 0, 6 ), 'globalRange': new es.Range( 21, 27 ) }
432 - ],
433 - 'desc': 'Range starting at the beginning of the first node and ending in the middle of the third node'
434 - },
435 - // Test 32
436 - {
437 - 'node': root2,
438 - 'input': new es.Range( 1, 29 ),
439 - 'output': [
440 - { 'node': f, 'range': new es.Range( 0, 8 ), 'globalRange': new es.Range( 1, 9 ) },
441 - { 'node': g, 'globalRange': new es.Range( 10, 20 ) },
442 - { 'node': h, 'range': new es.Range( 0, 8 ), 'globalRange': new es.Range( 21, 29 ) }
443 - ],
444 - 'desc': 'Range starting at the beginning of the first node and ending at the end of the third node'
445 - },
446 - // Test 33
447 - {
448 - 'node': root2,
449 - 'input': new es.Range( 1, 30 ),
450 - 'output': [
451 - { 'node': f, 'range': new es.Range( 0, 8 ), 'globalRange': new es.Range( 1, 9 ) },
452 - { 'node': g, 'globalRange': new es.Range( 10, 20 ) },
453 - { 'node': h, 'globalRange': new es.Range( 20, 30 ) }
454 - ],
455 - 'desc': 'Range starting at the beginning of the first node and ending past the end of the third node'
456 - },
457 - // Test 34
458 - {
459 - 'node': root2,
460 - 'input': new es.Range( 5, 11 ),
461 - 'output': [
462 - { 'node': f, 'range': new es.Range( 4, 8 ), 'globalRange': new es.Range( 5, 9 ) },
463 - { 'node': g, 'range': new es.Range( 0, 0 ), 'globalRange': new es.Range( 11, 11 ) }
464 - ],
465 - 'desc': 'Range starting in the middle of the first node and ending at the beginning of the second node'
466 - },
467 - // Test 35
468 - {
469 - 'node': root2,
470 - 'input': new es.Range( 5, 14 ),
471 - 'output': [
472 - { 'node': f, 'range': new es.Range( 4, 8 ), 'globalRange': new es.Range( 5, 9 ) },
473 - { 'node': g, 'range': new es.Range( 0, 3 ), 'globalRange': new es.Range( 11, 14 ) }
474 - ],
475 - 'desc': 'Range starting in the middle of the first node and ending in the middle of the second node'
476 - },
477 - // Test 36
478 - {
479 - 'node': root2,
480 - 'input': new es.Range( 5, 19 ),
481 - 'output': [
482 - { 'node': f, 'range': new es.Range( 4, 8 ), 'globalRange': new es.Range( 5, 9 ) },
483 - { 'node': g, 'range': new es.Range( 0, 8 ), 'globalRange': new es.Range( 11, 19 ) }
484 - ],
485 - 'desc': 'Range starting in the middle of the first node and ending at the end of the second node'
486 - },
487 - // Test 37
488 - {
489 - 'node': root2,
490 - 'input': new es.Range( 5, 20 ),
491 - 'output': [
492 - { 'node': f, 'range': new es.Range( 4, 8 ), 'globalRange': new es.Range( 5, 9 ) },
493 - { 'node': g, 'globalRange': new es.Range( 10, 20 ) }
494 - ],
495 - 'desc': 'Range starting in the middle of the first node and ending between the second and the third node'
496 - },
497 - // Test 38
498 - {
499 - 'node': root2,
500 - 'input': new es.Range( 5, 21 ),
501 - 'output': [
502 - { 'node': f, 'range': new es.Range( 4, 8 ), 'globalRange': new es.Range( 5, 9 ) },
503 - { 'node': g, 'globalRange': new es.Range( 10, 20 ) },
504 - { 'node': h, 'range': new es.Range( 0, 0 ), 'globalRange': new es.Range( 21, 21 ) }
505 - ],
506 - 'desc': 'Range starting in the middle of the first node and ending at the beginning of the third node'
507 - },
508 - // Test 39
509 - {
510 - 'node': root2,
511 - 'input': new es.Range( 5, 27 ),
512 - 'output': [
513 - { 'node': f, 'range': new es.Range( 4, 8 ), 'globalRange': new es.Range( 5, 9 ) },
514 - { 'node': g, 'globalRange': new es.Range( 10, 20 ) },
515 - { 'node': h, 'range': new es.Range( 0, 6 ), 'globalRange': new es.Range( 21, 27 ) }
516 - ],
517 - 'desc': 'Range starting in the middle of the first node and ending in the middle of the third node'
518 - },
519 - // Test 40
520 - {
521 - 'node': root2,
522 - 'input': new es.Range( 5, 29 ),
523 - 'output': [
524 - { 'node': f, 'range': new es.Range( 4, 8 ), 'globalRange': new es.Range( 5, 9 ) },
525 - { 'node': g, 'globalRange': new es.Range( 10, 20 ) },
526 - { 'node': h, 'range': new es.Range( 0, 8 ), 'globalRange': new es.Range( 21, 29 ) }
527 - ],
528 - 'desc': 'Range starting in the middle of the first node and ending at the end of the third node'
529 - },
530 - // Test 41
531 - {
532 - 'node': root2,
533 - 'input': new es.Range( 5, 30 ),
534 - 'output': [
535 - { 'node': f, 'range': new es.Range( 4, 8 ), 'globalRange': new es.Range( 5, 9 ) },
536 - { 'node': g, 'globalRange': new es.Range( 10, 20 ) },
537 - { 'node': h, 'globalRange': new es.Range( 20, 30 ) }
538 - ],
539 - 'desc': 'Range starting in the middle of the first node and ending past the end of the third node'
540 - },
541 - // Test 42
542 - {
543 - 'node': root2,
544 - 'input': new es.Range( 9, 11 ),
545 - 'output': [
546 - { 'node': f, 'range': new es.Range( 8, 8 ), 'globalRange': new es.Range( 9, 9 ) },
547 - { 'node': g, 'range': new es.Range( 0, 0 ), 'globalRange': new es.Range( 11, 11 ) }
548 - ],
549 - 'desc': 'Range starting at the end of the first node and ending at the beginning of the second node'
550 - },
551 - // Test 43
552 - {
553 - 'node': root2,
554 - 'input': new es.Range( 9, 14 ),
555 - 'output': [
556 - { 'node': f, 'range': new es.Range( 8, 8 ), 'globalRange': new es.Range( 9, 9 ) },
557 - { 'node': g, 'range': new es.Range( 0, 3 ), 'globalRange': new es.Range( 11, 14 ) }
558 - ],
559 - 'desc': 'Range starting at the end of the first node and ending in the middle of the second node'
560 - },
561 - // Test 44
562 - {
563 - 'node': root2,
564 - 'input': new es.Range( 9, 19 ),
565 - 'output': [
566 - { 'node': f, 'range': new es.Range( 8, 8 ), 'globalRange': new es.Range( 9, 9 ) },
567 - { 'node': g, 'range': new es.Range( 0, 8 ), 'globalRange': new es.Range( 11, 19 ) }
568 - ],
569 - 'desc': 'Range starting at the end of the first node and ending at the end of the second node'
570 - },
571 - // Test 45
572 - {
573 - 'node': root2,
574 - 'input': new es.Range( 9, 20 ),
575 - 'output': [
576 - { 'node': f, 'range': new es.Range( 8, 8 ), 'globalRange': new es.Range( 9, 9 ) },
577 - { 'node': g, 'globalRange': new es.Range( 10, 20 ) }
578 - ],
579 - 'desc': 'Range starting at the end of the first node and ending between the second and the third node'
580 - },
581 - // Test 46
582 - {
583 - 'node': root2,
584 - 'input': new es.Range( 9, 21 ),
585 - 'output': [
586 - { 'node': f, 'range': new es.Range( 8, 8 ), 'globalRange': new es.Range( 9, 9 ) },
587 - { 'node': g, 'globalRange': new es.Range( 10, 20 ) },
588 - { 'node': h, 'range': new es.Range( 0, 0 ), 'globalRange': new es.Range( 21, 21 ) }
589 - ],
590 - 'desc': 'Range starting at the end of the first node and ending at the beginning of the third node'
591 - },
592 - // Test 47
593 - {
594 - 'node': root2,
595 - 'input': new es.Range( 9, 27 ),
596 - 'output': [
597 - { 'node': f, 'range': new es.Range( 8, 8 ), 'globalRange': new es.Range( 9, 9 ) },
598 - { 'node': g, 'globalRange': new es.Range( 10, 20 ) },
599 - { 'node': h, 'range': new es.Range( 0, 6 ), 'globalRange': new es.Range( 21, 27 ) }
600 - ],
601 - 'desc': 'Range starting at the end of the first node and ending in the middle of the third node'
602 - },
603 - // Test 48
604 - {
605 - 'node': root2,
606 - 'input': new es.Range( 9, 29 ),
607 - 'output': [
608 - { 'node': f, 'range': new es.Range( 8, 8 ), 'globalRange': new es.Range( 9, 9 ) },
609 - { 'node': g, 'globalRange': new es.Range( 10, 20 ) },
610 - { 'node': h, 'range': new es.Range( 0, 8 ), 'globalRange': new es.Range( 21, 29 ) }
611 - ],
612 - 'desc': 'Range starting at the end of the first node and ending at the end of the third node'
613 - },
614 - // Test 49
615 - {
616 - 'node': root2,
617 - 'input': new es.Range( 9, 30 ),
618 - 'output': [
619 - { 'node': f, 'range': new es.Range( 8, 8 ), 'globalRange': new es.Range( 9, 9 ) },
620 - { 'node': g, 'globalRange': new es.Range( 10, 20 ) },
621 - { 'node': h, 'globalRange': new es.Range( 20, 30 ) }
622 - ],
623 - 'desc': 'Range starting at the end of the first node and ending past the end of the third node'
624 - },
625 - // Test 50
626 - {
627 - 'node': root2,
628 - 'input': new es.Range( 10, 21 ),
629 - 'output': [
630 - { 'node': g, 'globalRange': new es.Range( 10, 20 ) },
631 - { 'node': h, 'range': new es.Range( 0, 0 ), 'globalRange': new es.Range( 21, 21 ) }
632 - ],
633 - 'desc': 'Range starting between the first and the second node and ending at the beginning of the third node'
634 - },
635 - // Test 51
636 - {
637 - 'node': root2,
638 - 'input': new es.Range( 10, 27 ),
639 - 'output': [
640 - { 'node': g, 'globalRange': new es.Range( 10, 20 ) },
641 - { 'node': h, 'range': new es.Range( 0, 6 ), 'globalRange': new es.Range( 21, 27 ) }
642 - ],
643 - 'desc': 'Range starting between the first and the second node and ending in the middle of the third node'
644 - },
645 - // Test 52
646 - {
647 - 'node': root2,
648 - 'input': new es.Range( 10, 29 ),
649 - 'output': [
650 - { 'node': g, 'globalRange': new es.Range( 10, 20 ) },
651 - { 'node': h, 'range': new es.Range( 0, 8 ), 'globalRange': new es.Range( 21, 29 ) }
652 - ],
653 - 'desc': 'Range starting between the first and the second node and ending at the end of the third node'
654 - },
655 - // Test 53
656 - {
657 - 'node': root2,
658 - 'input': new es.Range( 10, 30 ),
659 - 'output': [
660 - { 'node': g, 'globalRange': new es.Range( 10, 20 ) },
661 - { 'node': h, 'globalRange': new es.Range( 20, 30 ) }
662 - ],
663 - 'desc': 'Range starting between the first and the second node and ending past the end of the third node'
664 - },
665 - // Test 54
666 - {
667 - 'node': root2,
668 - 'input': new es.Range( 11, 21 ),
669 - 'output': [
670 - { 'node': g, 'range': new es.Range( 0, 8 ), 'globalRange': new es.Range( 11, 19 ) },
671 - { 'node': h, 'range': new es.Range( 0, 0 ), 'globalRange': new es.Range( 21, 21 ) }
672 - ],
673 - 'desc': 'Range starting at the beginning of the second node and ending at the beginning of the third node'
674 - },
675 - // Test 55
676 - {
677 - 'node': root2,
678 - 'input': new es.Range( 11, 27 ),
679 - 'output': [
680 - { 'node': g, 'range': new es.Range( 0, 8 ), 'globalRange': new es.Range( 11, 19 ) },
681 - { 'node': h, 'range': new es.Range( 0, 6 ), 'globalRange': new es.Range( 21, 27 ) }
682 - ],
683 - 'desc': 'Range starting at the beginning of the second node and ending in the middle of the third node'
684 - },
685 - // Test 56
686 - {
687 - 'node': root2,
688 - 'input': new es.Range( 11, 29 ),
689 - 'output': [
690 - { 'node': g, 'range': new es.Range( 0, 8 ), 'globalRange': new es.Range( 11, 19 ) },
691 - { 'node': h, 'range': new es.Range( 0, 8 ), 'globalRange': new es.Range( 21, 29 ) }
692 - ],
693 - 'desc': 'Range starting at the beginning of the second node and ending at the end of the third node'
694 - },
695 - // Test 57
696 - {
697 - 'node': root2,
698 - 'input': new es.Range( 11, 30 ),
699 - 'output': [
700 - { 'node': g, 'range': new es.Range( 0, 8 ), 'globalRange': new es.Range( 11, 19 ) },
701 - { 'node': h, 'globalRange': new es.Range( 20, 30 ) }
702 - ],
703 - 'desc': 'Range starting at the beginning of the second node and ending past the end of the third node'
704 - },
705 - // Test 58
706 - {
707 - 'node': root2,
708 - 'input': new es.Range( 14, 21 ),
709 - 'output': [
710 - { 'node': g, 'range': new es.Range( 3, 8 ), 'globalRange': new es.Range( 14, 19 ) },
711 - { 'node': h, 'range': new es.Range( 0, 0 ), 'globalRange': new es.Range( 21, 21 ) }
712 - ],
713 - 'desc': 'Range starting in the middle of the second node and ending at the beginning of the third node'
714 - },
715 - // Test 59
716 - {
717 - 'node': root2,
718 - 'input': new es.Range( 14, 27 ),
719 - 'output': [
720 - { 'node': g, 'range': new es.Range( 3, 8 ), 'globalRange': new es.Range( 14, 19 ) },
721 - { 'node': h, 'range': new es.Range( 0, 6 ), 'globalRange': new es.Range( 21, 27 ) }
722 - ],
723 - 'desc': 'Range starting in the middle of the second node and ending in the middle of the third node'
724 - },
725 - // Test 60
726 - {
727 - 'node': root2,
728 - 'input': new es.Range( 14, 29 ),
729 - 'output': [
730 - { 'node': g, 'range': new es.Range( 3, 8 ), 'globalRange': new es.Range( 14, 19 ) },
731 - { 'node': h, 'range': new es.Range( 0, 8 ), 'globalRange': new es.Range( 21, 29 ) }
732 - ],
733 - 'desc': 'Range starting in the middle of the second node and ending at the end of the third node'
734 - },
735 - // Test 61
736 - {
737 - 'node': root2,
738 - 'input': new es.Range( 14, 30 ),
739 - 'output': [
740 - { 'node': g, 'range': new es.Range( 3, 8 ), 'globalRange': new es.Range( 14, 19 ) },
741 - { 'node': h, 'globalRange': new es.Range( 20, 30 ) }
742 - ],
743 - 'desc': 'Range starting in the middle of the second node and ending past the end of the third node'
744 - },
745 - // Test 62
746 - {
747 - 'node': root2,
748 - 'input': new es.Range( 19, 21 ),
749 - 'output': [
750 - { 'node': g, 'range': new es.Range( 8, 8 ), 'globalRange': new es.Range( 19, 19 ) },
751 - { 'node': h, 'range': new es.Range( 0, 0 ), 'globalRange': new es.Range( 21, 21 ) }
752 - ],
753 - 'desc': 'Range starting at the end of the second node and ending at the beginning of the third node'
754 - },
755 - // Test 63
756 - {
757 - 'node': root2,
758 - 'input': new es.Range( 19, 27 ),
759 - 'output': [
760 - { 'node': g, 'range': new es.Range( 8, 8 ), 'globalRange': new es.Range( 19, 19 ) },
761 - { 'node': h, 'range': new es.Range( 0, 6 ), 'globalRange': new es.Range( 21, 27 ) }
762 - ],
763 - 'desc': 'Range starting at the end of the second node and ending in the middle of the third node'
764 - },
765 - // Test 64
766 - {
767 - 'node': root2,
768 - 'input': new es.Range( 19, 29 ),
769 - 'output': [
770 - { 'node': g, 'range': new es.Range( 8, 8 ), 'globalRange': new es.Range( 19, 19 ) },
771 - { 'node': h, 'range': new es.Range( 0, 8 ), 'globalRange': new es.Range( 21, 29 ) }
772 - ],
773 - 'desc': 'Range starting at the end of the second node and ending at the end of the third node'
774 - },
775 - // Test 65
776 - {
777 - 'node': root2,
778 - 'input': new es.Range( 19, 30 ),
779 - 'output': [
780 - { 'node': g, 'range': new es.Range( 8, 8 ), 'globalRange': new es.Range( 19, 19 ) },
781 - { 'node': h, 'globalRange': new es.Range( 20, 30 ) }
782 - ],
783 - 'desc': 'Range starting at the end of the second node and ending past the end of the third node'
784 - },
785 - // Tests for childless nodes
786 -
787 - // Test 66
788 - {
789 - 'node': g,
790 - 'input': new es.Range( 1, 3 ),
791 - 'output': [
792 - { 'node': g, 'range': new es.Range( 1, 3 ), 'globalRange': new es.Range( 1, 3 ) }
793 - ],
794 - 'desc': 'Childless node given, range not out of bounds'
795 - },
796 - // Test 67
797 - {
798 - 'node': g,
799 - 'input': new es.Range( 0, 8 ),
800 - 'output': [
801 - { 'node': g, 'range': new es.Range( 0, 8 ), 'globalRange': new es.Range( 0, 8 ) }
802 - ],
803 - 'desc': 'Childless node given, range covers entire node'
804 - },
805 - // Tests for out-of-bounds cases
806 -
807 - // Test 68
808 - {
809 - 'node': g,
810 - 'input': new es.Range( -1, 3 ),
811 - 'exception': /^The start offset of the range is negative$/,
812 - 'desc': 'Childless node given, range start out of bounds'
813 - },
814 - // Test 69
815 - {
816 - 'node': g,
817 - 'input': new es.Range( 1, 9 ),
818 - 'exception': /^The end offset of the range is past the end of the node$/,
819 - 'desc': 'Childless node given, range end out of bounds'
820 - },
821 - // Test 70
822 - {
823 - 'node': root2,
824 - 'input': new es.Range( 31, 35 ),
825 - 'exception': /^The start offset of the range is past the end of the node$/,
826 - 'desc': 'Node with children given, range start out of bounds'
827 - },
828 - // Test 71
829 - {
830 - 'node': root2,
831 - 'input': new es.Range( 30, 35 ),
832 - 'exception': /^The end offset of the range is past the end of the node$/,
833 - 'desc': 'Node with children given, range end out of bounds'
834 - },
835 - // Tests for recursion cases
836 -
837 - // Test 72
838 - {
839 - 'node': big,
840 - 'input': new es.Range( 2, 10 ),
841 - 'output': [
842 - { 'node': big.children[0], 'range': new es.Range( 1, 3 ), 'globalRange': new es.Range( 2, 4 ) },
843 - { 'node': big.children[1], 'range': new es.Range( 0, 4 ), 'globalRange': new es.Range( 6, 10 ) }
844 - ],
845 - 'desc': 'Select from before the b to after the d'
846 - },
847 - // Test 73
848 - {
849 - 'node': big,
850 - 'input': new es.Range( 3, 33 ),
851 - 'output': [
852 - { 'node': big.children[0], 'range': new es.Range( 2, 3 ), 'globalRange': new es.Range( 3, 4 ) },
853 - { 'node': big.children[1], 'globalRange': new es.Range( 5, 31 ) },
854 - { 'node': big.children[2], 'range': new es.Range( 0, 1 ), 'globalRange': new es.Range( 32, 33 ) }
855 - ],
856 - 'desc': 'Select from before the c to after the h'
857 - },
858 - // Test 74
859 - {
860 - 'node': big,
861 - 'input': new es.Range( 9, 20 ),
862 - 'output': [
863 - { 'node': big.children[1].children[0].children[0].children[0], 'range': new es.Range( 0, 1 ), 'globalRange': new es.Range( 9, 10 ) },
864 - { 'node': big.children[1].children[0].children[0].children[1], 'range': new es.Range( 0, 8 ), 'globalRange': new es.Range( 12, 20 ) }
865 - ],
866 - 'desc': 'Select from before the d to after the f, with recursion'
867 - },
868 - // Test 75
869 - {
870 - 'node': big,
871 - 'input': new es.Range( 9, 20 ),
872 - 'shallow': true,
873 - 'output': [
874 - { 'node': big.children[1], 'range': new es.Range( 3, 14 ), 'globalRange': new es.Range( 9, 20 ) }
875 - ],
876 - 'desc': 'Select from before the d to after the f, without recursion'
877 - }
878 - ];
879 -
880 - function compare( a, b ) {
881 - if ( $.isArray( a ) && $.isArray( b ) && a.length === b.length ) {
882 - for ( var i = 0; i < a.length; i++ ) {
883 - if (
884 - a[i].node !== b[i].node ||
885 - (
886 - ( typeof a[i].range !== typeof b[i].range ) ||
887 - (
888 - a[i].range !== undefined &&
889 - (
890 - a[i].range.start !== b[i].range.start ||
891 - a[i].range.end !== b[i].range.end
892 - )
893 - )
894 - ) || (
895 - ( typeof a[i].globalRange !== typeof b[i].globalRange ) ||
896 - (
897 - a[i].globalRange !== undefined &&
898 - (
899 - a[i].globalRange.start !== b[i].globalRange.start ||
900 - a[i].globalRange.end !== b[i].globalRange.end
901 - )
902 - )
903 - )
904 - ) {
905 - return false;
906 - }
907 - }
908 - }
909 - return true;
910 - }
911 - function select( input, shallow ) {
912 - return function() {
913 - selectNodesTests[i].node.selectNodes( input, shallow );
914 - };
915 - }
916 -
917 - for ( var i = 0; i < selectNodesTests.length; i++ ) {
918 - if ( 'output' in selectNodesTests[i] ) {
919 - var result = selectNodesTests[i].node.selectNodes(
920 - selectNodesTests[i].input, selectNodesTests[i].shallow
921 - );
922 - ok(
923 - compare( result, selectNodesTests[i].output ),
924 - selectNodesTests[i].desc +
925 - ' (from ' + selectNodesTests[i].input.start +
926 - ' to ' + selectNodesTests[i].input.end + ')'
927 - );
928 - } else if ( 'exception' in selectNodesTests[i] ) {
929 - raises(
930 - function() {
931 - selectNodesTests[i].node.selectNodes(
932 - selectNodesTests[i].input,
933 - selectNodesTests[i].shallow
934 - );
935 - },
936 - selectNodesTests[i].exception,
937 - selectNodesTests[i].desc
938 - );
939 - }
940 - }
941 -} );
942 -
943 -test( 'es.DocumentBranchNode.traverseLeafNodes', 11, function() {
944 - var root3 = es.DocumentModel.newFromPlainObject( esTest.obj );
945 -
946 - var tests = [
947 - // Test 1 & 2
948 - {
949 - 'node': root3,
950 - 'output': [
951 - root3.children[0],
952 - root3.children[1].children[0].children[0].children[0],
953 - root3.children[1].children[0].children[0].children[1].children[0].children[0],
954 - root3.children[1].children[0].children[0].children[1].children[1].children[0],
955 - root3.children[1].children[0].children[0].children[1].children[2].children[0],
956 - root3.children[2]
957 - ],
958 - 'reverse': true,
959 - 'desc': 'Traversing the entire document returns all leaf nodes'
960 - },
961 - // Test 3 & 4
962 - {
963 - 'node': root3,
964 - 'output': [
965 - root3.children[0],
966 - root3.children[1].children[0].children[0].children[0],
967 - root3.children[1].children[0].children[0].children[1].children[0].children[0]
968 - ],
969 - 'reverse': [
970 - root3.children[2],
971 - root3.children[1].children[0].children[0].children[1].children[2].children[0],
972 - root3.children[1].children[0].children[0].children[1].children[1].children[0],
973 - root3.children[1].children[0].children[0].children[1].children[0].children[0]
974 - ],
975 - 'callback': function( node ) {
976 - if ( node === root3.children[1].children[0].children[0].children[1].children[0].children[0] ) {
977 - return false;
978 - }
979 - },
980 - 'desc': 'Returning false from the callback stops the traversal'
981 - },
982 - // Test 5 & 6
983 - {
984 - 'node': root3,
985 - 'output': [
986 - root3.children[1].children[0].children[0].children[1].children[1].children[0],
987 - root3.children[1].children[0].children[0].children[1].children[2].children[0],
988 - root3.children[2]
989 - ],
990 - 'reverse': [
991 - root3.children[1].children[0].children[0].children[1].children[1].children[0],
992 - root3.children[1].children[0].children[0].children[1].children[0].children[0],
993 - root3.children[1].children[0].children[0].children[0],
994 - root3.children[0]
995 - ],
996 - 'from': root3.children[1].children[0].children[0].children[1].children[1].children[0],
997 - 'desc': 'Starting at a leaf node returns that leaf node and everything after it',
998 - 'reverseDesc': 'Starting at a leaf node returns that leaf node and everything before it (in reverse)'
999 - },
1000 - // Test 7 & 8
1001 - {
1002 - 'node': root3,
1003 - 'output': [
1004 - root3.children[1].children[0].children[0].children[0],
1005 - root3.children[1].children[0].children[0].children[1].children[0].children[0],
1006 - root3.children[1].children[0].children[0].children[1].children[1].children[0],
1007 - root3.children[1].children[0].children[0].children[1].children[2].children[0],
1008 - root3.children[2]
1009 - ],
1010 - 'reverse': [
1011 - root3.children[0]
1012 - ],
1013 - 'from': root3.children[1],
1014 - 'desc': 'Starting at a non-leaf node returns all leaf nodes inside and after it',
1015 - 'reverseDesc': 'Starting at a non-leaf node returns all leaf nodes before it and none inside (in reverse)'
1016 - },
1017 - // Test 9 & 10
1018 - {
1019 - 'node': root3.children[1],
1020 - 'output': [
1021 - root3.children[1].children[0].children[0].children[0],
1022 - root3.children[1].children[0].children[0].children[1].children[0].children[0],
1023 - root3.children[1].children[0].children[0].children[1].children[1].children[0],
1024 - root3.children[1].children[0].children[0].children[1].children[2].children[0]
1025 - ],
1026 - 'reverse': true,
1027 - 'desc': 'Calling traverseLeafNodes() on a non-root node only returns leaf nodes inside that node'
1028 - },
1029 - // Test 11
1030 - {
1031 - 'node': root3.children[1],
1032 - 'from': root3.children[2],
1033 - 'exception': /^from parameter passed to traverseLeafNodes\(\) must be a descendant$/,
1034 - 'desc': 'Passing a sibling for from results in an exception'
1035 - }
1036 - ];
1037 -
1038 - for ( var i = 0; i < tests.length; i++ ) {
1039 - executeTest( tests[i] );
1040 - if ( tests[i].reverse !== undefined ) {
1041 - var reversed = {
1042 - 'node': tests[i].node,
1043 - 'from': tests[i].from,
1044 - 'callback': tests[i].callback,
1045 - 'exception': tests[i].exception,
1046 - 'isReversed': true,
1047 - 'desc': tests[i].reverseDesc || tests[i].desc + ' (in reverse)'
1048 - };
1049 - if ( tests[i].output !== undefined && tests[i].reverse === true ) {
1050 - reversed.output = tests[i].output.reverse();
1051 - } else {
1052 - reversed.output = tests[i].reverse;
1053 - }
1054 - executeTest( reversed );
1055 - }
1056 - }
1057 -
1058 - function executeTest( test ) {
1059 - var realLeaves = [],
1060 - callback = function( node ) {
1061 - var retval;
1062 - realLeaves.push( node );
1063 - if ( test.callback ) {
1064 - retval = test.callback( node );
1065 - if ( retval !== undefined ) {
1066 - return retval;
1067 - }
1068 - }
1069 - },
1070 - f = function() {
1071 - test.node.traverseLeafNodes( callback, test.from, test.isReversed );
1072 - };
1073 - if ( test.exception ) {
1074 - raises( f, test.exception, test.desc );
1075 - } else {
1076 - f();
1077 - ok( es.compareArrays( realLeaves, test.output ), test.desc );
1078 - }
1079 - }
1080 -} );
\ No newline at end of file
Index: trunk/extensions/VisualEditor/tests/es/es.DocumentBranchNode.test.js
@@ -0,0 +1,1079 @@
 2+module( 'es/bases' );
 3+
 4+/* Stubs */
 5+
 6+function DocumentBranchNodeStub( items, name, size ) {
 7+ // Inheritance
 8+ es.DocumentBranchNode.call( this, items );
 9+
 10+ // Properties
 11+ this.name = name;
 12+ this.size = size;
 13+}
 14+
 15+DocumentBranchNodeStub.prototype.getContentLength = function() {
 16+ return this.size;
 17+};
 18+
 19+DocumentBranchNodeStub.prototype.getElementLength = function() {
 20+ // Mimic document data which has an opening and closing around the content
 21+ return this.size + 2;
 22+};
 23+
 24+es.extendClass( DocumentBranchNodeStub, es.DocumentBranchNode );
 25+
 26+/* Tests */
 27+
 28+test( 'es.DocumentBranchNodeStub.getElementLength', 1, function() {
 29+ // Test 1
 30+ strictEqual(
 31+ ( new DocumentBranchNodeStub( [], 'a', 0 ) ).getElementLength(),
 32+ 2,
 33+ 'DocumentBranchNodeStub.getElementLength() returns initialized length plus 2 for elements'
 34+ );
 35+} );
 36+
 37+// Common stubs
 38+var a = new DocumentBranchNodeStub( [], 'a', 0 ),
 39+ b = new DocumentBranchNodeStub( [], 'b', 1 ),
 40+ c = new DocumentBranchNodeStub( [], 'c', 2 ),
 41+ d = new DocumentBranchNodeStub( [], 'd', 3 ),
 42+ e = new DocumentBranchNodeStub( [], 'e', 4 ),
 43+ root1 = new DocumentBranchNodeStub( [a, b, c, d, e], 'root1', 20 );
 44+
 45+test( 'es.DocumentBranchNode.getRangeFromNode', 6, function() {
 46+ // Tests 1 .. 6
 47+ var getRangeFromNodeTests = [
 48+ { 'input': a, 'output': new es.Range( 0, 2 ) },
 49+ { 'input': b, 'output': new es.Range( 2, 5 ) },
 50+ { 'input': c, 'output': new es.Range( 5, 9 ) },
 51+ { 'input': d, 'output': new es.Range( 9, 14 ) },
 52+ { 'input': e, 'output': new es.Range( 14, 20 ) },
 53+ { 'input': null, 'output': null }
 54+ ];
 55+ for ( var i = 0; i < getRangeFromNodeTests.length; i++ ) {
 56+ deepEqual(
 57+ root1.getRangeFromNode( getRangeFromNodeTests[i].input ),
 58+ getRangeFromNodeTests[i].output,
 59+ 'getRangeFromNode returns the correct range or null if item is not found'
 60+ );
 61+ }
 62+} );
 63+
 64+test( 'es.DocumentBranchNode.getNodeFromOffset', 23, function() {
 65+ // Tests 1 .. 22
 66+ var getNodeFromOffsetTests = [
 67+ // Test 1 - |[<a></a><b> </b><c> </c><d> </d><e> </e>]
 68+ { 'input': -1, 'output': null },
 69+ // Test 2 - [|<a></a><b> </b><c> </c><d> </d><e> </e>]
 70+ { 'input': 0, 'output': root1 },
 71+ // Test 3 - [<a>|</a><b> </b><c> </c><d> </d><e> </e>]
 72+ { 'input': 1, 'output': a },
 73+ // Test 4 - [<a></a>|<b> </b><c> </c><d> </d><e> </e>]
 74+ { 'input': 2, 'output': root1 },
 75+ // Test 5 - [<a></a><b>| </b><c> </c><d> </d><e> </e>]
 76+ { 'input': 3, 'output': b },
 77+ // Test 6 - [<a></a><b> |</b><c> </c><d> </d><e> </e>]
 78+ { 'input': 4, 'output': b },
 79+ // Test 7 - [<a></a><b> </b>|<c> </c><d> </d><e> </e>]
 80+ { 'input': 5, 'output': root1 },
 81+ // Test 8 - [<a></a><b> </b><c>| </c><d> </d><e> </e>]
 82+ { 'input': 6, 'output': c },
 83+ // Test 9 - [<a></a><b> </b><c> | </c><d> </d><e> </e>]
 84+ { 'input': 7, 'output': c },
 85+ // Test 10 - [<a></a><b> </b><c> |</c><d> </d><e> </e>]
 86+ { 'input': 8, 'output': c },
 87+ // Test 11 - [<a></a><b> </b><c> </c>|<d> </d><e> </e>]
 88+ { 'input': 9, 'output': root1 },
 89+ // Test 12 - [<a></a><b> </b><c> </c><d>| </d><e> </e>]
 90+ { 'input': 10, 'output': d },
 91+ // Test 13 - [<a></a><b> </b><c> </c><d> | </d><e> </e>]
 92+ { 'input': 11, 'output': d },
 93+ // Test 14 - [<a></a><b> </b><c> </c><d> | </d><e> </e>]
 94+ { 'input': 12, 'output': d },
 95+ // Test 15 - [<a></a><b> </b><c> </c><d> |</d><e> </e>]
 96+ { 'input': 13, 'output': d },
 97+ // Test 16 - [<a></a><b> </b><c> </c><d> </d>|<e> </e>]
 98+ { 'input': 14, 'output': root1 },
 99+ // Test 17 - [<a></a><b> </b><c> </c><d> </d><e>| </e>]
 100+ { 'input': 15, 'output': e },
 101+ // Test 18 - [<a></a><b> </b><c> </c><d> </d><e> | </e>]
 102+ { 'input': 16, 'output': e },
 103+ // Test 19 - [<a></a><b> </b><c> </c><d> </d><e> | </e>]
 104+ { 'input': 17, 'output': e },
 105+ // Test 20 - [<a></a><b> </b><c> </c><d> </d><e> | </e>]
 106+ { 'input': 18, 'output': e },
 107+ // Test 21 - [<a></a><b> </b><c> </c><d> </d><e> |</e>]
 108+ { 'input': 19, 'output': e },
 109+ // Test 22 - [<a></a><b> </b><c> </c><d> </d><e> </e>|]
 110+ { 'input': 20, 'output': root1 },
 111+ // Test 22 - [<a></a><b> </b><c> </c><d> </d><e> </e>]|
 112+ { 'input': 21, 'output': null }
 113+ ];
 114+ for ( var i = 0; i < getNodeFromOffsetTests.length; i++ ) {
 115+ ok(
 116+ root1.getNodeFromOffset( getNodeFromOffsetTests[i].input ) ===
 117+ getNodeFromOffsetTests[i].output,
 118+ 'getNodeFromOffset finds the right item or returns null when out of range ' +
 119+ '(' + getNodeFromOffsetTests[i].input + ')'
 120+ );
 121+ }
 122+} );
 123+
 124+test( 'es.DocumentBranchNode.getOffsetFromNode', 6, function() {
 125+ // Tests 1 .. 6
 126+ var getOffsetFromNodeTests = [
 127+ { 'input': a, 'output': 0 },
 128+ { 'input': b, 'output': 2 },
 129+ { 'input': c, 'output': 5 },
 130+ { 'input': d, 'output': 9 },
 131+ { 'input': e, 'output': 14 },
 132+ { 'input': null, 'output': -1 }
 133+ ];
 134+ for ( var i = 0; i < getOffsetFromNodeTests.length; i++ ) {
 135+ strictEqual(
 136+ root1.getOffsetFromNode( getOffsetFromNodeTests[i].input ),
 137+ getOffsetFromNodeTests[i].output,
 138+ 'getOffsetFromNode finds the right offset or returns -1 when node is not found'
 139+ );
 140+ }
 141+} );
 142+
 143+test( 'es.DocumentBranchNode.selectNodes', 75, function() {
 144+
 145+ // selectNodes tests
 146+
 147+ // <f> a b c d e f g h </f> <g> a b c d e f g h </g> <h> a b c d e f g h </h>
 148+ //^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^
 149+ //0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0
 150+ // 0 1 2 3 4 5 6 7 8 0 1 2 3 4 5 6 7 8 0 1 2 3 4 5 6 7 8
 151+ var f = new DocumentBranchNodeStub( [], 'f', 8 ),
 152+ g = new DocumentBranchNodeStub( [], 'g', 8 ),
 153+ h = new DocumentBranchNodeStub( [], 'h', 8 ),
 154+ root2 = new DocumentBranchNodeStub( [f, g, h], 'root2', 30 ),
 155+ big = es.DocumentModel.newFromPlainObject( esTest.obj );
 156+
 157+ // Tests 1 ... 22
 158+ // Possible positions are:
 159+ // * before beginning
 160+ // * at beginning
 161+ // * middle
 162+ // * at end
 163+ // * past end
 164+ var selectNodesTests = [
 165+ // Complete set of combinations within the same node:
 166+
 167+ // Test 1
 168+ {
 169+ 'node': root2,
 170+ 'input': new es.Range( 0, 0 ),
 171+ 'output': [],
 172+ 'desc': 'Zero-length range before the beginning of a node'
 173+ },
 174+ // Test 2
 175+ {
 176+ 'node': root2,
 177+ 'input': new es.Range( 0, 1 ),
 178+ 'output': [{ 'node': f, 'range': new es.Range( 0, 0 ), 'globalRange': new es.Range( 1, 1 ) }],
 179+ 'desc': 'Range starting before the beginning of a node and ending at the beginning'
 180+ },
 181+ // Test 3
 182+ {
 183+ 'node': root2,
 184+ 'input': new es.Range( 10, 15 ),
 185+ 'output': [{ 'node': g, 'range': new es.Range( 0, 4 ), 'globalRange': new es.Range( 11, 15 ) }],
 186+ 'desc': 'Range starting before the beginning of a node and ending in the middle'
 187+ },
 188+ // Test 4
 189+ {
 190+ 'node': root2,
 191+ 'input': new es.Range( 20, 29 ),
 192+ 'output': [{ 'node': h, 'range': new es.Range( 0, 8 ), 'globalRange': new es.Range( 21, 29 ) }],
 193+ 'desc': 'Range starting before the beginning of a node and ending at the end'
 194+ },
 195+ // Test 5
 196+ {
 197+ 'node': root2,
 198+ 'input': new es.Range( 0, 10 ),
 199+ 'output': [{ 'node': f, 'globalRange': new es.Range( 0, 10 ) } ],
 200+ 'desc': 'Range starting before the beginning of a node and ending past the end'
 201+ },
 202+ // Test 6
 203+ {
 204+ 'node': root2,
 205+ 'input': new es.Range( 11, 11 ),
 206+ 'output': [{ 'node': g, 'range': new es.Range( 0, 0 ), 'globalRange': new es.Range( 11, 11 ) }],
 207+ 'desc': 'Zero-length range at the beginning of a node'
 208+ },
 209+ // Test 7
 210+ {
 211+ 'node': root2,
 212+ 'input': new es.Range( 21, 26 ),
 213+ 'output': [{ 'node': h, 'range': new es.Range( 0, 5 ), 'globalRange': new es.Range( 21, 26 ) }],
 214+ 'desc': 'Range starting at the beginning of a node and ending in the middle'
 215+ },
 216+ // Test 8
 217+ {
 218+ 'node': root2,
 219+ 'input': new es.Range( 1, 9 ),
 220+ 'output': [{ 'node': f, 'range': new es.Range( 0, 8 ), 'globalRange': new es.Range( 1, 9 ) }],
 221+ 'desc': 'Range starting at the beginning of a node and ending at the end'
 222+ },
 223+ // Test 9
 224+ {
 225+ 'node': root2,
 226+ 'input': new es.Range( 11, 20 ),
 227+ 'output': [{ 'node': g, 'range': new es.Range( 0, 8 ), 'globalRange': new es.Range( 11, 19 ) }],
 228+ 'desc': 'Range starting at the beginning of a node and ending past the end'
 229+ },
 230+ // Test 10
 231+ {
 232+ 'node': root2,
 233+ 'input': new es.Range( 22, 22 ),
 234+ 'output': [{ 'node': h, 'range': new es.Range( 1, 1 ), 'globalRange': new es.Range( 22, 22 ) }],
 235+ 'desc': 'Zero-length range in the middle of a node'
 236+ },
 237+ // Test 11
 238+ {
 239+ 'node': root2,
 240+ 'input': new es.Range( 2, 7 ),
 241+ 'output': [{ 'node': f, 'range': new es.Range( 1, 6 ), 'globalRange': new es.Range( 2, 7 ) }],
 242+ 'desc': 'Range starting and ending in the middle of the same node'
 243+ },
 244+ // Test 12
 245+ {
 246+ 'node': root2,
 247+ 'input': new es.Range( 13, 19 ),
 248+ 'output': [{ 'node': g, 'range': new es.Range( 2, 8 ), 'globalRange': new es.Range( 13, 19 ) }],
 249+ 'desc': 'Range starting in the middle of a node and ending at the end'
 250+ },
 251+ // Test 13
 252+ {
 253+ 'node': root2,
 254+ 'input': new es.Range( 24, 30 ),
 255+ 'output': [{ 'node': h, 'range': new es.Range( 3, 8 ), 'globalRange': new es.Range( 24, 29 ) }],
 256+ 'desc': 'Range starting in the middle of a node and ending past the end'
 257+ },
 258+ // Test 14
 259+ {
 260+ 'node': root2,
 261+ 'input': new es.Range( 9, 9 ),
 262+ 'output': [{ 'node': f, 'range': new es.Range( 8, 8 ), 'globalRange': new es.Range( 9, 9 ) }],
 263+ 'desc': 'Zero-length range at the end of a node'
 264+ },
 265+ // Test 15
 266+ {
 267+ 'node': root2,
 268+ 'input': new es.Range( 19, 20 ),
 269+ 'output': [{ 'node': g, 'range': new es.Range( 8, 8 ), 'globalRange': new es.Range( 19, 19 ) }],
 270+ 'desc': 'Range starting at the end of a node and ending past the end'
 271+ },
 272+ // Test 16
 273+ {
 274+ 'node': root2,
 275+ 'input': new es.Range( 30, 30 ),
 276+ 'output': [],
 277+ 'desc': 'Zero-length range past the end of a node'
 278+ },
 279+ // Test 17
 280+ {
 281+ 'node': root2,
 282+ 'input': new es.Range( 20, 20 ),
 283+ 'output': [],
 284+ 'desc': 'Zero-length range between two nodes'
 285+ },
 286+
 287+ // Complete set of combinations for cross-node selections. Generated with help of a script
 288+
 289+ // Test 18
 290+ {
 291+ 'node': root2,
 292+ 'input': new es.Range( 0, 11 ),
 293+ 'output': [
 294+ { 'node': f, 'globalRange': new es.Range( 0, 10 ) },
 295+ { 'node': g, 'range': new es.Range( 0, 0 ), 'globalRange': new es.Range( 11, 11 ) }
 296+ ],
 297+ 'desc': 'Range starting before the beginning of the first node and ending at the beginning of the second node'
 298+ },
 299+ // Test 19
 300+ {
 301+ 'node': root2,
 302+ 'input': new es.Range( 0, 14 ),
 303+ 'output': [
 304+ { 'node': f, 'globalRange': new es.Range( 0, 10 ) },
 305+ { 'node': g, 'range': new es.Range( 0, 3 ), 'globalRange': new es.Range( 11, 14 ) }
 306+ ],
 307+ 'desc': 'Range starting before the beginning of the first node and ending in the middle of the second node'
 308+ },
 309+ // Test 20
 310+ {
 311+ 'node': root2,
 312+ 'input': new es.Range( 0, 19 ),
 313+ 'output': [
 314+ { 'node': f, 'globalRange': new es.Range( 0, 10 ) },
 315+ { 'node': g, 'range': new es.Range( 0, 8 ), 'globalRange': new es.Range( 11, 19 ) }
 316+ ],
 317+ 'desc': 'Range starting before the beginning of the first node and ending at the end of the second node'
 318+ },
 319+ // Test 21
 320+ {
 321+ 'node': root2,
 322+ 'input': new es.Range( 0, 20 ),
 323+ 'output': [
 324+ { 'node': f, 'globalRange': new es.Range( 0, 10 ) },
 325+ { 'node': g, 'globalRange': new es.Range( 10, 20 ) }
 326+ ],
 327+ 'desc': 'Range starting before the beginning of the first node and ending between the second and the third node'
 328+ },
 329+ // Test 22
 330+ {
 331+ 'node': root2,
 332+ 'input': new es.Range( 0, 21 ),
 333+ 'output': [
 334+ { 'node': f, 'globalRange': new es.Range( 0, 10 ) },
 335+ { 'node': g, 'globalRange': new es.Range( 10, 20 ) },
 336+ { 'node': h, 'range': new es.Range( 0, 0 ), 'globalRange': new es.Range( 21, 21 ) }
 337+ ],
 338+ 'desc': 'Range starting before the beginning of the first node and ending at the beginning of the third node'
 339+ },
 340+ // Test 23
 341+ {
 342+ 'node': root2,
 343+ 'input': new es.Range( 0, 27 ),
 344+ 'output': [
 345+ { 'node': f, 'globalRange': new es.Range( 0, 10 ) },
 346+ { 'node': g, 'globalRange': new es.Range( 10, 20 ) },
 347+ { 'node': h, 'range': new es.Range( 0, 6 ), 'globalRange': new es.Range( 21, 27 ) }
 348+ ],
 349+ 'desc': 'Range starting before the beginning of the first node and ending in the middle of the third node'
 350+ },
 351+ // Test 24
 352+ {
 353+ 'node': root2,
 354+ 'input': new es.Range( 0, 29 ),
 355+ 'output': [
 356+ { 'node': f, 'globalRange': new es.Range( 0, 10 ) },
 357+ { 'node': g, 'globalRange': new es.Range( 10, 20 ) },
 358+ { 'node': h, 'range': new es.Range( 0, 8 ), 'globalRange': new es.Range( 21, 29 ) }
 359+ ],
 360+ 'desc': 'Range starting before the beginning of the first node and ending at the end of the third node'
 361+ },
 362+ // Test 25
 363+ {
 364+ 'node': root2,
 365+ 'input': new es.Range( 0, 30 ),
 366+ 'output': [
 367+ { 'node': f, 'globalRange': new es.Range( 0, 10 ) },
 368+ { 'node': g, 'globalRange': new es.Range( 10, 20 ) },
 369+ { 'node': h, 'globalRange': new es.Range( 20, 30 ) }
 370+ ],
 371+ 'desc': 'Range starting before the beginning of the first node and ending past the end of the third node'
 372+ },
 373+ // Test 26
 374+ {
 375+ 'node': root2,
 376+ 'input': new es.Range( 1, 11 ),
 377+ 'output': [
 378+ { 'node': f, 'range': new es.Range( 0, 8 ), 'globalRange': new es.Range( 1, 9 ) },
 379+ { 'node': g, 'range': new es.Range( 0, 0 ), 'globalRange': new es.Range( 11, 11 ) }
 380+ ],
 381+ 'desc': 'Range starting at the beginning of the first node and ending at the beginning of the second node'
 382+ },
 383+ // Test 27
 384+ {
 385+ 'node': root2,
 386+ 'input': new es.Range( 1, 14 ),
 387+ 'output': [
 388+ { 'node': f, 'range': new es.Range( 0, 8 ), 'globalRange': new es.Range( 1, 9 ) },
 389+ { 'node': g, 'range': new es.Range( 0, 3 ), 'globalRange': new es.Range( 11, 14 ) }
 390+ ],
 391+ 'desc': 'Range starting at the beginning of the first node and ending in the middle of the second node'
 392+ },
 393+ // Test 28
 394+ {
 395+ 'node': root2,
 396+ 'input': new es.Range( 1, 19 ),
 397+ 'output': [
 398+ { 'node': f, 'range': new es.Range( 0, 8 ), 'globalRange': new es.Range( 1, 9 ) },
 399+ { 'node': g, 'range': new es.Range( 0, 8 ), 'globalRange': new es.Range( 11, 19 ) }
 400+ ],
 401+ 'desc': 'Range starting at the beginning of the first node and ending at the end of the second node'
 402+ },
 403+ // Test 29
 404+ {
 405+ 'node': root2,
 406+ 'input': new es.Range( 1, 20 ),
 407+ 'output': [
 408+ { 'node': f, 'range': new es.Range( 0, 8 ), 'globalRange': new es.Range( 1, 9 ) },
 409+ { 'node': g, 'globalRange': new es.Range( 10, 20 ) }
 410+ ],
 411+ 'desc': 'Range starting at the beginning of the first node and ending between the second and the third node'
 412+ },
 413+ // Test 30
 414+ {
 415+ 'node': root2,
 416+ 'input': new es.Range( 1, 21 ),
 417+ 'output': [
 418+ { 'node': f, 'range': new es.Range( 0, 8 ), 'globalRange': new es.Range( 1, 9 ) },
 419+ { 'node': g, 'globalRange': new es.Range( 10, 20 ) },
 420+ { 'node': h, 'range': new es.Range( 0, 0 ), 'globalRange': new es.Range( 21, 21 ) }
 421+ ],
 422+ 'desc': 'Range starting at the beginning of the first node and ending at the beginning of the third node'
 423+ },
 424+ // Test 31
 425+ {
 426+ 'node': root2,
 427+ 'input': new es.Range( 1, 27 ),
 428+ 'output': [
 429+ { 'node': f, 'range': new es.Range( 0, 8 ), 'globalRange': new es.Range( 1, 9 ) },
 430+ { 'node': g, 'globalRange': new es.Range( 10, 20 ) },
 431+ { 'node': h, 'range': new es.Range( 0, 6 ), 'globalRange': new es.Range( 21, 27 ) }
 432+ ],
 433+ 'desc': 'Range starting at the beginning of the first node and ending in the middle of the third node'
 434+ },
 435+ // Test 32
 436+ {
 437+ 'node': root2,
 438+ 'input': new es.Range( 1, 29 ),
 439+ 'output': [
 440+ { 'node': f, 'range': new es.Range( 0, 8 ), 'globalRange': new es.Range( 1, 9 ) },
 441+ { 'node': g, 'globalRange': new es.Range( 10, 20 ) },
 442+ { 'node': h, 'range': new es.Range( 0, 8 ), 'globalRange': new es.Range( 21, 29 ) }
 443+ ],
 444+ 'desc': 'Range starting at the beginning of the first node and ending at the end of the third node'
 445+ },
 446+ // Test 33
 447+ {
 448+ 'node': root2,
 449+ 'input': new es.Range( 1, 30 ),
 450+ 'output': [
 451+ { 'node': f, 'range': new es.Range( 0, 8 ), 'globalRange': new es.Range( 1, 9 ) },
 452+ { 'node': g, 'globalRange': new es.Range( 10, 20 ) },
 453+ { 'node': h, 'globalRange': new es.Range( 20, 30 ) }
 454+ ],
 455+ 'desc': 'Range starting at the beginning of the first node and ending past the end of the third node'
 456+ },
 457+ // Test 34
 458+ {
 459+ 'node': root2,
 460+ 'input': new es.Range( 5, 11 ),
 461+ 'output': [
 462+ { 'node': f, 'range': new es.Range( 4, 8 ), 'globalRange': new es.Range( 5, 9 ) },
 463+ { 'node': g, 'range': new es.Range( 0, 0 ), 'globalRange': new es.Range( 11, 11 ) }
 464+ ],
 465+ 'desc': 'Range starting in the middle of the first node and ending at the beginning of the second node'
 466+ },
 467+ // Test 35
 468+ {
 469+ 'node': root2,
 470+ 'input': new es.Range( 5, 14 ),
 471+ 'output': [
 472+ { 'node': f, 'range': new es.Range( 4, 8 ), 'globalRange': new es.Range( 5, 9 ) },
 473+ { 'node': g, 'range': new es.Range( 0, 3 ), 'globalRange': new es.Range( 11, 14 ) }
 474+ ],
 475+ 'desc': 'Range starting in the middle of the first node and ending in the middle of the second node'
 476+ },
 477+ // Test 36
 478+ {
 479+ 'node': root2,
 480+ 'input': new es.Range( 5, 19 ),
 481+ 'output': [
 482+ { 'node': f, 'range': new es.Range( 4, 8 ), 'globalRange': new es.Range( 5, 9 ) },
 483+ { 'node': g, 'range': new es.Range( 0, 8 ), 'globalRange': new es.Range( 11, 19 ) }
 484+ ],
 485+ 'desc': 'Range starting in the middle of the first node and ending at the end of the second node'
 486+ },
 487+ // Test 37
 488+ {
 489+ 'node': root2,
 490+ 'input': new es.Range( 5, 20 ),
 491+ 'output': [
 492+ { 'node': f, 'range': new es.Range( 4, 8 ), 'globalRange': new es.Range( 5, 9 ) },
 493+ { 'node': g, 'globalRange': new es.Range( 10, 20 ) }
 494+ ],
 495+ 'desc': 'Range starting in the middle of the first node and ending between the second and the third node'
 496+ },
 497+ // Test 38
 498+ {
 499+ 'node': root2,
 500+ 'input': new es.Range( 5, 21 ),
 501+ 'output': [
 502+ { 'node': f, 'range': new es.Range( 4, 8 ), 'globalRange': new es.Range( 5, 9 ) },
 503+ { 'node': g, 'globalRange': new es.Range( 10, 20 ) },
 504+ { 'node': h, 'range': new es.Range( 0, 0 ), 'globalRange': new es.Range( 21, 21 ) }
 505+ ],
 506+ 'desc': 'Range starting in the middle of the first node and ending at the beginning of the third node'
 507+ },
 508+ // Test 39
 509+ {
 510+ 'node': root2,
 511+ 'input': new es.Range( 5, 27 ),
 512+ 'output': [
 513+ { 'node': f, 'range': new es.Range( 4, 8 ), 'globalRange': new es.Range( 5, 9 ) },
 514+ { 'node': g, 'globalRange': new es.Range( 10, 20 ) },
 515+ { 'node': h, 'range': new es.Range( 0, 6 ), 'globalRange': new es.Range( 21, 27 ) }
 516+ ],
 517+ 'desc': 'Range starting in the middle of the first node and ending in the middle of the third node'
 518+ },
 519+ // Test 40
 520+ {
 521+ 'node': root2,
 522+ 'input': new es.Range( 5, 29 ),
 523+ 'output': [
 524+ { 'node': f, 'range': new es.Range( 4, 8 ), 'globalRange': new es.Range( 5, 9 ) },
 525+ { 'node': g, 'globalRange': new es.Range( 10, 20 ) },
 526+ { 'node': h, 'range': new es.Range( 0, 8 ), 'globalRange': new es.Range( 21, 29 ) }
 527+ ],
 528+ 'desc': 'Range starting in the middle of the first node and ending at the end of the third node'
 529+ },
 530+ // Test 41
 531+ {
 532+ 'node': root2,
 533+ 'input': new es.Range( 5, 30 ),
 534+ 'output': [
 535+ { 'node': f, 'range': new es.Range( 4, 8 ), 'globalRange': new es.Range( 5, 9 ) },
 536+ { 'node': g, 'globalRange': new es.Range( 10, 20 ) },
 537+ { 'node': h, 'globalRange': new es.Range( 20, 30 ) }
 538+ ],
 539+ 'desc': 'Range starting in the middle of the first node and ending past the end of the third node'
 540+ },
 541+ // Test 42
 542+ {
 543+ 'node': root2,
 544+ 'input': new es.Range( 9, 11 ),
 545+ 'output': [
 546+ { 'node': f, 'range': new es.Range( 8, 8 ), 'globalRange': new es.Range( 9, 9 ) },
 547+ { 'node': g, 'range': new es.Range( 0, 0 ), 'globalRange': new es.Range( 11, 11 ) }
 548+ ],
 549+ 'desc': 'Range starting at the end of the first node and ending at the beginning of the second node'
 550+ },
 551+ // Test 43
 552+ {
 553+ 'node': root2,
 554+ 'input': new es.Range( 9, 14 ),
 555+ 'output': [
 556+ { 'node': f, 'range': new es.Range( 8, 8 ), 'globalRange': new es.Range( 9, 9 ) },
 557+ { 'node': g, 'range': new es.Range( 0, 3 ), 'globalRange': new es.Range( 11, 14 ) }
 558+ ],
 559+ 'desc': 'Range starting at the end of the first node and ending in the middle of the second node'
 560+ },
 561+ // Test 44
 562+ {
 563+ 'node': root2,
 564+ 'input': new es.Range( 9, 19 ),
 565+ 'output': [
 566+ { 'node': f, 'range': new es.Range( 8, 8 ), 'globalRange': new es.Range( 9, 9 ) },
 567+ { 'node': g, 'range': new es.Range( 0, 8 ), 'globalRange': new es.Range( 11, 19 ) }
 568+ ],
 569+ 'desc': 'Range starting at the end of the first node and ending at the end of the second node'
 570+ },
 571+ // Test 45
 572+ {
 573+ 'node': root2,
 574+ 'input': new es.Range( 9, 20 ),
 575+ 'output': [
 576+ { 'node': f, 'range': new es.Range( 8, 8 ), 'globalRange': new es.Range( 9, 9 ) },
 577+ { 'node': g, 'globalRange': new es.Range( 10, 20 ) }
 578+ ],
 579+ 'desc': 'Range starting at the end of the first node and ending between the second and the third node'
 580+ },
 581+ // Test 46
 582+ {
 583+ 'node': root2,
 584+ 'input': new es.Range( 9, 21 ),
 585+ 'output': [
 586+ { 'node': f, 'range': new es.Range( 8, 8 ), 'globalRange': new es.Range( 9, 9 ) },
 587+ { 'node': g, 'globalRange': new es.Range( 10, 20 ) },
 588+ { 'node': h, 'range': new es.Range( 0, 0 ), 'globalRange': new es.Range( 21, 21 ) }
 589+ ],
 590+ 'desc': 'Range starting at the end of the first node and ending at the beginning of the third node'
 591+ },
 592+ // Test 47
 593+ {
 594+ 'node': root2,
 595+ 'input': new es.Range( 9, 27 ),
 596+ 'output': [
 597+ { 'node': f, 'range': new es.Range( 8, 8 ), 'globalRange': new es.Range( 9, 9 ) },
 598+ { 'node': g, 'globalRange': new es.Range( 10, 20 ) },
 599+ { 'node': h, 'range': new es.Range( 0, 6 ), 'globalRange': new es.Range( 21, 27 ) }
 600+ ],
 601+ 'desc': 'Range starting at the end of the first node and ending in the middle of the third node'
 602+ },
 603+ // Test 48
 604+ {
 605+ 'node': root2,
 606+ 'input': new es.Range( 9, 29 ),
 607+ 'output': [
 608+ { 'node': f, 'range': new es.Range( 8, 8 ), 'globalRange': new es.Range( 9, 9 ) },
 609+ { 'node': g, 'globalRange': new es.Range( 10, 20 ) },
 610+ { 'node': h, 'range': new es.Range( 0, 8 ), 'globalRange': new es.Range( 21, 29 ) }
 611+ ],
 612+ 'desc': 'Range starting at the end of the first node and ending at the end of the third node'
 613+ },
 614+ // Test 49
 615+ {
 616+ 'node': root2,
 617+ 'input': new es.Range( 9, 30 ),
 618+ 'output': [
 619+ { 'node': f, 'range': new es.Range( 8, 8 ), 'globalRange': new es.Range( 9, 9 ) },
 620+ { 'node': g, 'globalRange': new es.Range( 10, 20 ) },
 621+ { 'node': h, 'globalRange': new es.Range( 20, 30 ) }
 622+ ],
 623+ 'desc': 'Range starting at the end of the first node and ending past the end of the third node'
 624+ },
 625+ // Test 50
 626+ {
 627+ 'node': root2,
 628+ 'input': new es.Range( 10, 21 ),
 629+ 'output': [
 630+ { 'node': g, 'globalRange': new es.Range( 10, 20 ) },
 631+ { 'node': h, 'range': new es.Range( 0, 0 ), 'globalRange': new es.Range( 21, 21 ) }
 632+ ],
 633+ 'desc': 'Range starting between the first and the second node and ending at the beginning of the third node'
 634+ },
 635+ // Test 51
 636+ {
 637+ 'node': root2,
 638+ 'input': new es.Range( 10, 27 ),
 639+ 'output': [
 640+ { 'node': g, 'globalRange': new es.Range( 10, 20 ) },
 641+ { 'node': h, 'range': new es.Range( 0, 6 ), 'globalRange': new es.Range( 21, 27 ) }
 642+ ],
 643+ 'desc': 'Range starting between the first and the second node and ending in the middle of the third node'
 644+ },
 645+ // Test 52
 646+ {
 647+ 'node': root2,
 648+ 'input': new es.Range( 10, 29 ),
 649+ 'output': [
 650+ { 'node': g, 'globalRange': new es.Range( 10, 20 ) },
 651+ { 'node': h, 'range': new es.Range( 0, 8 ), 'globalRange': new es.Range( 21, 29 ) }
 652+ ],
 653+ 'desc': 'Range starting between the first and the second node and ending at the end of the third node'
 654+ },
 655+ // Test 53
 656+ {
 657+ 'node': root2,
 658+ 'input': new es.Range( 10, 30 ),
 659+ 'output': [
 660+ { 'node': g, 'globalRange': new es.Range( 10, 20 ) },
 661+ { 'node': h, 'globalRange': new es.Range( 20, 30 ) }
 662+ ],
 663+ 'desc': 'Range starting between the first and the second node and ending past the end of the third node'
 664+ },
 665+ // Test 54
 666+ {
 667+ 'node': root2,
 668+ 'input': new es.Range( 11, 21 ),
 669+ 'output': [
 670+ { 'node': g, 'range': new es.Range( 0, 8 ), 'globalRange': new es.Range( 11, 19 ) },
 671+ { 'node': h, 'range': new es.Range( 0, 0 ), 'globalRange': new es.Range( 21, 21 ) }
 672+ ],
 673+ 'desc': 'Range starting at the beginning of the second node and ending at the beginning of the third node'
 674+ },
 675+ // Test 55
 676+ {
 677+ 'node': root2,
 678+ 'input': new es.Range( 11, 27 ),
 679+ 'output': [
 680+ { 'node': g, 'range': new es.Range( 0, 8 ), 'globalRange': new es.Range( 11, 19 ) },
 681+ { 'node': h, 'range': new es.Range( 0, 6 ), 'globalRange': new es.Range( 21, 27 ) }
 682+ ],
 683+ 'desc': 'Range starting at the beginning of the second node and ending in the middle of the third node'
 684+ },
 685+ // Test 56
 686+ {
 687+ 'node': root2,
 688+ 'input': new es.Range( 11, 29 ),
 689+ 'output': [
 690+ { 'node': g, 'range': new es.Range( 0, 8 ), 'globalRange': new es.Range( 11, 19 ) },
 691+ { 'node': h, 'range': new es.Range( 0, 8 ), 'globalRange': new es.Range( 21, 29 ) }
 692+ ],
 693+ 'desc': 'Range starting at the beginning of the second node and ending at the end of the third node'
 694+ },
 695+ // Test 57
 696+ {
 697+ 'node': root2,
 698+ 'input': new es.Range( 11, 30 ),
 699+ 'output': [
 700+ { 'node': g, 'range': new es.Range( 0, 8 ), 'globalRange': new es.Range( 11, 19 ) },
 701+ { 'node': h, 'globalRange': new es.Range( 20, 30 ) }
 702+ ],
 703+ 'desc': 'Range starting at the beginning of the second node and ending past the end of the third node'
 704+ },
 705+ // Test 58
 706+ {
 707+ 'node': root2,
 708+ 'input': new es.Range( 14, 21 ),
 709+ 'output': [
 710+ { 'node': g, 'range': new es.Range( 3, 8 ), 'globalRange': new es.Range( 14, 19 ) },
 711+ { 'node': h, 'range': new es.Range( 0, 0 ), 'globalRange': new es.Range( 21, 21 ) }
 712+ ],
 713+ 'desc': 'Range starting in the middle of the second node and ending at the beginning of the third node'
 714+ },
 715+ // Test 59
 716+ {
 717+ 'node': root2,
 718+ 'input': new es.Range( 14, 27 ),
 719+ 'output': [
 720+ { 'node': g, 'range': new es.Range( 3, 8 ), 'globalRange': new es.Range( 14, 19 ) },
 721+ { 'node': h, 'range': new es.Range( 0, 6 ), 'globalRange': new es.Range( 21, 27 ) }
 722+ ],
 723+ 'desc': 'Range starting in the middle of the second node and ending in the middle of the third node'
 724+ },
 725+ // Test 60
 726+ {
 727+ 'node': root2,
 728+ 'input': new es.Range( 14, 29 ),
 729+ 'output': [
 730+ { 'node': g, 'range': new es.Range( 3, 8 ), 'globalRange': new es.Range( 14, 19 ) },
 731+ { 'node': h, 'range': new es.Range( 0, 8 ), 'globalRange': new es.Range( 21, 29 ) }
 732+ ],
 733+ 'desc': 'Range starting in the middle of the second node and ending at the end of the third node'
 734+ },
 735+ // Test 61
 736+ {
 737+ 'node': root2,
 738+ 'input': new es.Range( 14, 30 ),
 739+ 'output': [
 740+ { 'node': g, 'range': new es.Range( 3, 8 ), 'globalRange': new es.Range( 14, 19 ) },
 741+ { 'node': h, 'globalRange': new es.Range( 20, 30 ) }
 742+ ],
 743+ 'desc': 'Range starting in the middle of the second node and ending past the end of the third node'
 744+ },
 745+ // Test 62
 746+ {
 747+ 'node': root2,
 748+ 'input': new es.Range( 19, 21 ),
 749+ 'output': [
 750+ { 'node': g, 'range': new es.Range( 8, 8 ), 'globalRange': new es.Range( 19, 19 ) },
 751+ { 'node': h, 'range': new es.Range( 0, 0 ), 'globalRange': new es.Range( 21, 21 ) }
 752+ ],
 753+ 'desc': 'Range starting at the end of the second node and ending at the beginning of the third node'
 754+ },
 755+ // Test 63
 756+ {
 757+ 'node': root2,
 758+ 'input': new es.Range( 19, 27 ),
 759+ 'output': [
 760+ { 'node': g, 'range': new es.Range( 8, 8 ), 'globalRange': new es.Range( 19, 19 ) },
 761+ { 'node': h, 'range': new es.Range( 0, 6 ), 'globalRange': new es.Range( 21, 27 ) }
 762+ ],
 763+ 'desc': 'Range starting at the end of the second node and ending in the middle of the third node'
 764+ },
 765+ // Test 64
 766+ {
 767+ 'node': root2,
 768+ 'input': new es.Range( 19, 29 ),
 769+ 'output': [
 770+ { 'node': g, 'range': new es.Range( 8, 8 ), 'globalRange': new es.Range( 19, 19 ) },
 771+ { 'node': h, 'range': new es.Range( 0, 8 ), 'globalRange': new es.Range( 21, 29 ) }
 772+ ],
 773+ 'desc': 'Range starting at the end of the second node and ending at the end of the third node'
 774+ },
 775+ // Test 65
 776+ {
 777+ 'node': root2,
 778+ 'input': new es.Range( 19, 30 ),
 779+ 'output': [
 780+ { 'node': g, 'range': new es.Range( 8, 8 ), 'globalRange': new es.Range( 19, 19 ) },
 781+ { 'node': h, 'globalRange': new es.Range( 20, 30 ) }
 782+ ],
 783+ 'desc': 'Range starting at the end of the second node and ending past the end of the third node'
 784+ },
 785+ // Tests for childless nodes
 786+
 787+ // Test 66
 788+ {
 789+ 'node': g,
 790+ 'input': new es.Range( 1, 3 ),
 791+ 'output': [
 792+ { 'node': g, 'range': new es.Range( 1, 3 ), 'globalRange': new es.Range( 1, 3 ) }
 793+ ],
 794+ 'desc': 'Childless node given, range not out of bounds'
 795+ },
 796+ // Test 67
 797+ {
 798+ 'node': g,
 799+ 'input': new es.Range( 0, 8 ),
 800+ 'output': [
 801+ { 'node': g, 'range': new es.Range( 0, 8 ), 'globalRange': new es.Range( 0, 8 ) }
 802+ ],
 803+ 'desc': 'Childless node given, range covers entire node'
 804+ },
 805+ // Tests for out-of-bounds cases
 806+
 807+ // Test 68
 808+ {
 809+ 'node': g,
 810+ 'input': new es.Range( -1, 3 ),
 811+ 'exception': /^The start offset of the range is negative$/,
 812+ 'desc': 'Childless node given, range start out of bounds'
 813+ },
 814+ // Test 69
 815+ {
 816+ 'node': g,
 817+ 'input': new es.Range( 1, 9 ),
 818+ 'exception': /^The end offset of the range is past the end of the node$/,
 819+ 'desc': 'Childless node given, range end out of bounds'
 820+ },
 821+ // Test 70
 822+ {
 823+ 'node': root2,
 824+ 'input': new es.Range( 31, 35 ),
 825+ 'exception': /^The start offset of the range is past the end of the node$/,
 826+ 'desc': 'Node with children given, range start out of bounds'
 827+ },
 828+ // Test 71
 829+ {
 830+ 'node': root2,
 831+ 'input': new es.Range( 30, 35 ),
 832+ 'exception': /^The end offset of the range is past the end of the node$/,
 833+ 'desc': 'Node with children given, range end out of bounds'
 834+ },
 835+ // Tests for recursion cases
 836+
 837+ // Test 72
 838+ {
 839+ 'node': big,
 840+ 'input': new es.Range( 2, 10 ),
 841+ 'output': [
 842+ { 'node': big.children[0], 'range': new es.Range( 1, 3 ), 'globalRange': new es.Range( 2, 4 ) },
 843+ { 'node': big.children[1], 'range': new es.Range( 0, 4 ), 'globalRange': new es.Range( 6, 10 ) }
 844+ ],
 845+ 'desc': 'Select from before the b to after the d'
 846+ },
 847+ // Test 73
 848+ {
 849+ 'node': big,
 850+ 'input': new es.Range( 3, 33 ),
 851+ 'output': [
 852+ { 'node': big.children[0], 'range': new es.Range( 2, 3 ), 'globalRange': new es.Range( 3, 4 ) },
 853+ { 'node': big.children[1], 'globalRange': new es.Range( 5, 31 ) },
 854+ { 'node': big.children[2], 'range': new es.Range( 0, 1 ), 'globalRange': new es.Range( 32, 33 ) }
 855+ ],
 856+ 'desc': 'Select from before the c to after the h'
 857+ },
 858+ // Test 74
 859+ {
 860+ 'node': big,
 861+ 'input': new es.Range( 9, 20 ),
 862+ 'output': [
 863+ { 'node': big.children[1].children[0].children[0].children[0], 'range': new es.Range( 0, 1 ), 'globalRange': new es.Range( 9, 10 ) },
 864+ { 'node': big.children[1].children[0].children[0].children[1], 'range': new es.Range( 0, 8 ), 'globalRange': new es.Range( 12, 20 ) }
 865+ ],
 866+ 'desc': 'Select from before the d to after the f, with recursion'
 867+ },
 868+ // Test 75
 869+ {
 870+ 'node': big,
 871+ 'input': new es.Range( 9, 20 ),
 872+ 'shallow': true,
 873+ 'output': [
 874+ { 'node': big.children[1], 'range': new es.Range( 3, 14 ), 'globalRange': new es.Range( 9, 20 ) }
 875+ ],
 876+ 'desc': 'Select from before the d to after the f, without recursion'
 877+ }
 878+ ];
 879+
 880+ function compare( a, b ) {
 881+ if ( $.isArray( a ) && $.isArray( b ) && a.length === b.length ) {
 882+ for ( var i = 0; i < a.length; i++ ) {
 883+ if (
 884+ a[i].node !== b[i].node ||
 885+ (
 886+ ( typeof a[i].range !== typeof b[i].range ) ||
 887+ (
 888+ a[i].range !== undefined &&
 889+ (
 890+ a[i].range.start !== b[i].range.start ||
 891+ a[i].range.end !== b[i].range.end
 892+ )
 893+ )
 894+ ) || (
 895+ ( typeof a[i].globalRange !== typeof b[i].globalRange ) ||
 896+ (
 897+ a[i].globalRange !== undefined &&
 898+ (
 899+ a[i].globalRange.start !== b[i].globalRange.start ||
 900+ a[i].globalRange.end !== b[i].globalRange.end
 901+ )
 902+ )
 903+ )
 904+ ) {
 905+ return false;
 906+ }
 907+ }
 908+ }
 909+ return true;
 910+ }
 911+ function select( input, shallow ) {
 912+ return function() {
 913+ selectNodesTests[i].node.selectNodes( input, shallow );
 914+ };
 915+ }
 916+
 917+ for ( var i = 0; i < selectNodesTests.length; i++ ) {
 918+ if ( 'output' in selectNodesTests[i] ) {
 919+ var result = selectNodesTests[i].node.selectNodes(
 920+ selectNodesTests[i].input, selectNodesTests[i].shallow
 921+ );
 922+ ok(
 923+ compare( result, selectNodesTests[i].output ),
 924+ selectNodesTests[i].desc +
 925+ ' (from ' + selectNodesTests[i].input.start +
 926+ ' to ' + selectNodesTests[i].input.end + ')'
 927+ );
 928+ } else if ( 'exception' in selectNodesTests[i] ) {
 929+ raises(
 930+ function() {
 931+ selectNodesTests[i].node.selectNodes(
 932+ selectNodesTests[i].input,
 933+ selectNodesTests[i].shallow
 934+ );
 935+ },
 936+ selectNodesTests[i].exception,
 937+ selectNodesTests[i].desc
 938+ );
 939+ }
 940+ }
 941+} );
 942+
 943+test( 'es.DocumentBranchNode.traverseLeafNodes', 11, function() {
 944+ var root3 = es.DocumentModel.newFromPlainObject( esTest.obj );
 945+
 946+ var tests = [
 947+ // Test 1 & 2
 948+ {
 949+ 'node': root3,
 950+ 'output': [
 951+ root3.children[0],
 952+ root3.children[1].children[0].children[0].children[0],
 953+ root3.children[1].children[0].children[0].children[1].children[0].children[0],
 954+ root3.children[1].children[0].children[0].children[1].children[1].children[0],
 955+ root3.children[1].children[0].children[0].children[1].children[2].children[0],
 956+ root3.children[2]
 957+ ],
 958+ 'reverse': true,
 959+ 'desc': 'Traversing the entire document returns all leaf nodes'
 960+ },
 961+ // Test 3 & 4
 962+ {
 963+ 'node': root3,
 964+ 'output': [
 965+ root3.children[0],
 966+ root3.children[1].children[0].children[0].children[0],
 967+ root3.children[1].children[0].children[0].children[1].children[0].children[0]
 968+ ],
 969+ 'reverse': [
 970+ root3.children[2],
 971+ root3.children[1].children[0].children[0].children[1].children[2].children[0],
 972+ root3.children[1].children[0].children[0].children[1].children[1].children[0],
 973+ root3.children[1].children[0].children[0].children[1].children[0].children[0]
 974+ ],
 975+ 'callback': function( node ) {
 976+ if ( node === root3.children[1].children[0].children[0].children[1].children[0].children[0] ) {
 977+ return false;
 978+ }
 979+ },
 980+ 'desc': 'Returning false from the callback stops the traversal'
 981+ },
 982+ // Test 5 & 6
 983+ {
 984+ 'node': root3,
 985+ 'output': [
 986+ root3.children[1].children[0].children[0].children[1].children[1].children[0],
 987+ root3.children[1].children[0].children[0].children[1].children[2].children[0],
 988+ root3.children[2]
 989+ ],
 990+ 'reverse': [
 991+ root3.children[1].children[0].children[0].children[1].children[1].children[0],
 992+ root3.children[1].children[0].children[0].children[1].children[0].children[0],
 993+ root3.children[1].children[0].children[0].children[0],
 994+ root3.children[0]
 995+ ],
 996+ 'from': root3.children[1].children[0].children[0].children[1].children[1].children[0],
 997+ 'desc': 'Starting at a leaf node returns that leaf node and everything after it',
 998+ 'reverseDesc': 'Starting at a leaf node returns that leaf node and everything before it (in reverse)'
 999+ },
 1000+ // Test 7 & 8
 1001+ {
 1002+ 'node': root3,
 1003+ 'output': [
 1004+ root3.children[1].children[0].children[0].children[0],
 1005+ root3.children[1].children[0].children[0].children[1].children[0].children[0],
 1006+ root3.children[1].children[0].children[0].children[1].children[1].children[0],
 1007+ root3.children[1].children[0].children[0].children[1].children[2].children[0],
 1008+ root3.children[2]
 1009+ ],
 1010+ 'reverse': [
 1011+ root3.children[0]
 1012+ ],
 1013+ 'from': root3.children[1],
 1014+ 'desc': 'Starting at a non-leaf node returns all leaf nodes inside and after it',
 1015+ 'reverseDesc': 'Starting at a non-leaf node returns all leaf nodes before it and none inside (in reverse)'
 1016+ },
 1017+ // Test 9 & 10
 1018+ {
 1019+ 'node': root3.children[1],
 1020+ 'output': [
 1021+ root3.children[1].children[0].children[0].children[0],
 1022+ root3.children[1].children[0].children[0].children[1].children[0].children[0],
 1023+ root3.children[1].children[0].children[0].children[1].children[1].children[0],
 1024+ root3.children[1].children[0].children[0].children[1].children[2].children[0]
 1025+ ],
 1026+ 'reverse': true,
 1027+ 'desc': 'Calling traverseLeafNodes() on a non-root node only returns leaf nodes inside that node'
 1028+ },
 1029+ // Test 11
 1030+ {
 1031+ 'node': root3.children[1],
 1032+ 'from': root3.children[2],
 1033+ 'exception': /^from parameter passed to traverseLeafNodes\(\) must be a descendant$/,
 1034+ 'desc': 'Passing a sibling for from results in an exception'
 1035+ }
 1036+ ];
 1037+
 1038+ for ( var i = 0; i < tests.length; i++ ) {
 1039+ executeTest( tests[i] );
 1040+ if ( tests[i].reverse !== undefined ) {
 1041+ var reversed = {
 1042+ 'node': tests[i].node,
 1043+ 'from': tests[i].from,
 1044+ 'callback': tests[i].callback,
 1045+ 'exception': tests[i].exception,
 1046+ 'isReversed': true,
 1047+ 'desc': tests[i].reverseDesc || tests[i].desc + ' (in reverse)'
 1048+ };
 1049+ if ( tests[i].output !== undefined && tests[i].reverse === true ) {
 1050+ reversed.output = tests[i].output.reverse();
 1051+ } else {
 1052+ reversed.output = tests[i].reverse;
 1053+ }
 1054+ executeTest( reversed );
 1055+ }
 1056+ }
 1057+
 1058+ function executeTest( test ) {
 1059+ var realLeaves = [],
 1060+ callback = function( node ) {
 1061+ var retval;
 1062+ realLeaves.push( node );
 1063+ if ( test.callback ) {
 1064+ retval = test.callback( node );
 1065+ if ( retval !== undefined ) {
 1066+ return retval;
 1067+ }
 1068+ }
 1069+ },
 1070+ f = function() {
 1071+ test.node.traverseLeafNodes( callback, test.from, test.isReversed );
 1072+ };
 1073+ if ( test.exception ) {
 1074+ raises( f, test.exception, test.desc );
 1075+ } else {
 1076+ f();
 1077+ ok( es.compareArrays( realLeaves, test.output ), test.desc );
 1078+ }
 1079+ }
 1080+} );
\ No newline at end of file
Property changes on: trunk/extensions/VisualEditor/tests/es/es.DocumentBranchNode.test.js
___________________________________________________________________
Added: svn:eol-style
11081 + native
Index: trunk/extensions/VisualEditor/tests/es/index.html
@@ -43,7 +43,7 @@
4444 <script src="es.testData.js"></script>
4545 <script src="es.test.js"></script>
4646 <script src="es.TransactionProcessor.test.js"></script>
47 - <script src="es.DocumentNode.test.js"></script>
 47+ <script src="es.DocumentBranchNode.test.js"></script>
4848 <script src="es.DocumentModelBranchNode.test.js"></script>
4949 <script src="es.DocumentModel.test.js"></script>
5050 </body>

Status & tagging log