]> git.proxmox.com Git - extjs.git/blame - extjs/packages/core/test/specs/data/NodeInterface.js
add extjs 6.0.1 sources
[extjs.git] / extjs / packages / core / test / specs / data / NodeInterface.js
CommitLineData
6527f429
DM
1describe('Ext.data.NodeInterface', function() {\r
2 function spyOnEvent(object, eventName, fn) {\r
3 var obj = {\r
4 fn: fn || Ext.emptyFn\r
5 },\r
6 spy = spyOn(obj, "fn");\r
7 object.addListener(eventName, obj.fn);\r
8 return spy;\r
9 }\r
10\r
11 beforeEach(function() {\r
12 Ext.define('spec.TreeNode', {\r
13 extend: 'Ext.data.TreeModel',\r
14 fields: [\r
15 {name: 'text', type: 'string'}\r
16 ],\r
17 proxy: {\r
18 type: 'memory'\r
19 }\r
20 });\r
21 });\r
22\r
23 afterEach(function() {\r
24 Ext.undefine('spec.TreeNode');\r
25 Ext.data.Model.schema.clear();\r
26 });\r
27\r
28 describe('decorating', function() {\r
29 var fields;\r
30\r
31 beforeEach(function() {\r
32 fields = spec.TreeNode.prototype.fieldsMap;\r
33 });\r
34\r
35 it('should decorate the Model with a parentId field that has the same type as the idProperty', function() {\r
36 var field = fields.parentId,\r
37 type = fields[spec.TreeNode.idProperty].getType();\r
38\r
39 expect(field.getPersist()).toBe(true);\r
40 expect(field.getType()).toBe(type);\r
41 expect(field.getDefaultValue()).toBeNull();\r
42 });\r
43 it('should decorate the Model with an index field', function() {\r
44 var field = fields.index;\r
45\r
46 expect(field.getPersist()).toBe(false);\r
47 expect(field.getType()).toBe('int');\r
48 expect(field.getDefaultValue()).toBe(-1);\r
49 });\r
50 it('should decorate the Model with a depth field', function() {\r
51 var field = fields.depth;\r
52\r
53 expect(field.getPersist()).toBe(false);\r
54 expect(field.getType()).toBe('int');\r
55 expect(field.getDefaultValue()).toBe(0);\r
56 });\r
57 it('should decorate the Model with an expanded field', function() {\r
58 var field = fields.expanded;\r
59\r
60 expect(field.getPersist()).toBe(false);\r
61 expect(field.getType()).toBe('bool');\r
62 expect(field.getDefaultValue()).toBe(false);\r
63 });\r
64 it('should decorate the Model with an expandable field', function() {\r
65 var field = fields.expandable;\r
66\r
67 expect(field.getPersist()).toBe(false);\r
68 expect(field.getType()).toBe('bool');\r
69 expect(field.getDefaultValue()).toBe(true);\r
70 });\r
71 it('should decorate the Model with a checked field', function() {\r
72 var field = fields.checked;\r
73\r
74 expect(field.getPersist()).toBe(false);\r
75 expect(field.getType()).toBe('auto');\r
76 expect(field.getDefaultValue()).toBe(null);\r
77 });\r
78 it('should decorate the Model with a leaf field', function() {\r
79 var field = fields.leaf;\r
80\r
81 expect(field.getPersist()).toBe(true);\r
82 expect(field.getType()).toBe('bool');\r
83 expect(field.getDefaultValue()).toBe(false);\r
84 });\r
85 it('should decorate the Model with a cls field', function() {\r
86 var field = fields.cls;\r
87\r
88 expect(field.getPersist()).toBe(false);\r
89 expect(field.getType()).toBe('string');\r
90 expect(field.getDefaultValue()).toBe('');\r
91 });\r
92 it('should decorate the Model with an iconCls field', function() {\r
93 var field = fields.iconCls;\r
94\r
95 expect(field.getPersist()).toBe(false);\r
96 expect(field.getType()).toBe('string');\r
97 expect(field.getDefaultValue()).toBe('');\r
98 });\r
99 it('should decorate the Model with an icon field', function() {\r
100 var field = fields.icon;\r
101\r
102 expect(field.getPersist()).toBe(false);\r
103 expect(field.getType()).toBe('string');\r
104 expect(field.getDefaultValue()).toBe('');\r
105 });\r
106 it('should decorate the Model with a root field', function() {\r
107 var field = fields.root;\r
108\r
109 expect(field.getPersist()).toBe(false);\r
110 expect(field.getType()).toBe('bool');\r
111 expect(field.getDefaultValue()).toBe(false);\r
112 });\r
113 it('should decorate the Model with an isLast field', function() {\r
114 var field = fields.isLast;\r
115\r
116 expect(field.getPersist()).toBe(false);\r
117 expect(field.getType()).toBe('bool');\r
118 expect(field.getDefaultValue()).toBe(false);\r
119 });\r
120 it('should decorate the Model with an isFirst field', function() {\r
121 var field = fields.isFirst;\r
122\r
123 expect(field.getPersist()).toBe(false);\r
124 expect(field.getType()).toBe('bool');\r
125 expect(field.getDefaultValue()).toBe(false);\r
126 });\r
127 it('should decorate the Model with an allowDrop field', function() {\r
128 var field = fields.allowDrop;\r
129\r
130 expect(field.getPersist()).toBe(false);\r
131 expect(field.getType()).toBe('bool');\r
132 expect(field.getDefaultValue()).toBe(true);\r
133 });\r
134\r
135 it('should decorate the Model with an allowDrag field', function() {\r
136 var field = fields.allowDrag;\r
137\r
138 expect(field.getPersist()).toBe(false);\r
139 expect(field.getType()).toBe('bool');\r
140 expect(field.getDefaultValue()).toBe(true);\r
141 });\r
142 it('should decorate the Model with a loaded field', function() {\r
143 var field = fields.loaded;\r
144\r
145 expect(field.getPersist()).toBe(false);\r
146 expect(field.getType()).toBe('bool');\r
147 expect(field.getDefaultValue()).toBe(false);\r
148 });\r
149 it('should decorate the Model with a loading field', function() {\r
150 var field = fields.loading;\r
151\r
152 expect(field.getPersist()).toBe(false);\r
153 expect(field.getType()).toBe('bool');\r
154 expect(field.getDefaultValue()).toBe(false);\r
155 });\r
156 it('should decorate the Model with an href field', function() {\r
157 var field = fields.href;\r
158\r
159 expect(field.getPersist()).toBe(false);\r
160 expect(field.getType()).toBe('string');\r
161 expect(field.getDefaultValue()).toBe('');\r
162 });\r
163 it('should decorate the Model with an hrefTarget field', function() {\r
164 var field = fields.hrefTarget;\r
165\r
166 expect(field.getPersist()).toBe(false);\r
167 expect(field.getType()).toBe('string');\r
168 expect(field.getDefaultValue()).toBe('');\r
169 });\r
170 it('should decorate the Model with a qtip field', function() {\r
171 var field = fields.qtip;\r
172\r
173 expect(field.getPersist()).toBe(false);\r
174 expect(field.getType()).toBe('string');\r
175 expect(field.getDefaultValue()).toBe('');\r
176 });\r
177 it('should decorate the Model with a qtitle field', function() {\r
178 var field = fields.qtitle;\r
179\r
180 expect(field.getPersist()).toBe(false);\r
181 expect(field.getType()).toBe('string');\r
182 expect(field.getDefaultValue()).toBe('');\r
183 });\r
184 it('should decorate the Model with a children field', function() {\r
185 var field = fields.children;\r
186\r
187 expect(field.getPersist()).toBe(false);\r
188 expect(field.getType()).toBe('auto');\r
189 expect(field.getDefaultValue()).toBe(null);\r
190 });\r
191 it('should decorate Model class of a given record', function() {\r
192 var MyModel, record1, record2;\r
193 MyModel = Ext.define('spec.MyModel', {\r
194 extend: 'Ext.data.Model',\r
195 fields: [\r
196 {name: 'text', type: 'string'}\r
197 ],\r
198 proxy: {\r
199 type: 'memory'\r
200 }\r
201 });\r
202 record1 = MyModel.create({text: 'record1'});\r
203 record2 = MyModel.create({text: 'record2'});\r
204 expect(MyModel.prototype.isNode).toBeUndefined();\r
205 expect(record1.isNode).toBeUndefined();\r
206 expect(record2.isNode).toBeUndefined();\r
207 \r
208 Ext.data.NodeInterface.decorate(record1);\r
209 expect(MyModel.prototype.isNode).toBeTruthy();\r
210 expect(record1.isNode).toBeTruthy();\r
211 expect(record2.isNode).toBeTruthy();\r
212\r
213 Ext.undefine('spec.MyModel');\r
214 });\r
215\r
216 });\r
217\r
218\r
219 describe('methods', function() {\r
220 var leftChild, rightChild, rootNode, spareNode, spy;\r
221\r
222 function insertDefaultChildren() {\r
223 rootNode.appendChild(leftChild);\r
224 rootNode.appendChild(rightChild);\r
225 rootNode.updateInfo(false, {\r
226 isFirst: true,\r
227 isLast: true,\r
228 depth: 0,\r
229 index: 0,\r
230 parentId: null\r
231 });\r
232 }\r
233\r
234 beforeEach(function() {\r
235 leftChild = new spec.TreeNode({\r
236 id: 'left'\r
237 });\r
238 \r
239 rightChild = new spec.TreeNode({\r
240 id: 'right'\r
241 });\r
242 \r
243 rootNode = new spec.TreeNode({\r
244 id: 'root'\r
245 });\r
246 \r
247 //we use this in several tests as an example node to add\r
248 spareNode = new spec.TreeNode({\r
249 id: 'spare'\r
250 });\r
251\r
252 });\r
253 \r
254 describe("isFirst", function() {\r
255 beforeEach(function() {\r
256 insertDefaultChildren.call(this);\r
257 });\r
258 \r
259 it("should have rootNode which is first", function() {\r
260 expect(rootNode.isFirst()).toBe(true);\r
261 });\r
262 it("should have leftChild which is first", function() {\r
263 expect(leftChild.isFirst()).toBe(true);\r
264 });\r
265 it("should have rightChild which is not first", function() {\r
266 expect(rightChild.isFirst()).toBe(false);\r
267 });\r
268 });\r
269\r
270 describe("isLast", function() {\r
271 beforeEach(function(){\r
272 insertDefaultChildren.call(this);\r
273 });\r
274 \r
275 it("should have rootNode which is last", function() {\r
276 expect(rootNode.isLast()).toBe(true);\r
277 });\r
278 it("should have leftChild which is not last", function() {\r
279 expect(leftChild.isLast()).toBe(false);\r
280 });\r
281 it("should have rightChild which is last", function() {\r
282 expect(rightChild.isLast()).toBe(true);\r
283 });\r
284 });\r
285\r
286 describe("hasChildNodes", function() {\r
287 beforeEach(function() {\r
288 rootNode.appendChild(leftChild);\r
289 });\r
290 \r
291 it("should have rootNode with children", function() {\r
292 expect(rootNode.hasChildNodes()).toBe(true);\r
293 });\r
294 it("should have leftChild whithout children", function() {\r
295 expect(leftChild.hasChildNodes()).toBe(false);\r
296 });\r
297 });\r
298 \r
299 describe("isExpandable", function() {\r
300 it("should have node expandable if it has children", function() {\r
301 spareNode.appendChild(leftChild);\r
302 expect(spareNode.isExpandable()).toBe(true);\r
303 });\r
304 \r
305 it("should have node expandable if has no children", function() {\r
306 expect(spareNode.isExpandable()).toBe(true);\r
307 }); \r
308 it("should have node not expandable if it is a leaf node", function() {\r
309 spareNode.set('leaf', true);\r
310 expect(spareNode.isExpandable()).toBe(false);\r
311 }); \r
312 });\r
313\r
314 describe("append", function(){\r
315 describe("appending children", function() {\r
316 \r
317 it("should fire beforeappend", function() {\r
318 spy = spyOnEvent(rootNode, "beforeappend").andCallThrough();\r
319 \r
320 rootNode.appendChild(leftChild);\r
321 \r
322 expect(spy).toHaveBeenCalledWith(rootNode, leftChild);\r
323 });\r
324 \r
325 it("should cancel append if beforeappend return false", function() {\r
326 spy = spyOnEvent(rootNode, "beforeappend").andReturn(false);\r
327 expect(rootNode.appendChild(leftChild)).toBe(false);\r
328 \r
329 expect(spy.callCount).toEqual(1);\r
330 });\r
331 \r
332 it("should set firstChild", function() {\r
333 \r
334 rootNode.appendChild(leftChild);\r
335 \r
336 expect(rootNode.firstChild).toEqual(leftChild);\r
337 });\r
338 \r
339 it("should set lastChild", function() {\r
340 \r
341 rootNode.appendChild(leftChild);\r
342 \r
343 expect(rootNode.lastChild).toEqual(leftChild);\r
344 });\r
345 \r
346 it("should add node to childnodes", function() {\r
347 var childNodes;\r
348 \r
349 rootNode.appendChild(leftChild);\r
350 \r
351 childNodes = rootNode.childNodes;\r
352 \r
353 expect(childNodes.length).toEqual(1);\r
354 expect(childNodes[0]).toEqual(leftChild);\r
355 });\r
356 \r
357 it("should fire append event", function() {\r
358 spy = spyOnEvent(rootNode, "append").andCallThrough();\r
359 \r
360 rootNode.appendChild(leftChild);\r
361 \r
362 expect(spy).toHaveBeenCalledWith(rootNode, leftChild, 0);\r
363 });\r
364 \r
365 it("should return node", function() {\r
366 var ret = rootNode.appendChild(leftChild);\r
367 \r
368 expect(ret).toEqual(leftChild);\r
369 });\r
370 \r
371 it("should append array of nodes", function() {\r
372 rootNode.appendChild([leftChild, rightChild]);\r
373 \r
374 var childNodes = rootNode.childNodes;\r
375 \r
376 expect(childNodes[0]).toEqual(leftChild);\r
377 expect(childNodes[1]).toEqual(rightChild);\r
378 expect(childNodes.length).toEqual(2);\r
379 });\r
380 });\r
381 \r
382 describe("appending with existing siblings", function() {\r
383 beforeEach(function() {\r
384 insertDefaultChildren.call(this); \r
385 });\r
386 \r
387 it("should set next sibling", function() {\r
388 expect(leftChild.nextSibling).toEqual(rightChild);\r
389 expect(rightChild.nextSibling).toBeNull();\r
390 });\r
391 \r
392 it("should set previous sibling", function() {\r
393 expect(rightChild.previousSibling).toEqual(leftChild);\r
394 expect(leftChild.previousSibling).toBeNull();\r
395 });\r
396 });\r
397 \r
398 describe("appending children from an existing node", function() {\r
399 var oldParent, spy;\r
400 \r
401 beforeEach(function() {\r
402 oldParent = new spec.TreeNode({id: 'oldparent'});\r
403 oldParent.appendChild(spareNode);\r
404 });\r
405 \r
406 it("should remove from existing node", function() {\r
407 spy = spyOn(oldParent, "removeChild").andCallThrough();\r
408 \r
409 rootNode.appendChild(spareNode);\r
410 \r
411 expect(spy).toHaveBeenCalledWith(spareNode, false, undefined, true);\r
412 });\r
413 \r
414 it("should fire beforeremove event", function(){\r
415 spy = spyOnEvent(oldParent, "beforeremove").andCallThrough();\r
416 \r
417 rootNode.appendChild(spareNode);\r
418 \r
419 expect(spy).toHaveBeenCalledWith(oldParent, spareNode, true);\r
420 });\r
421 \r
422 it("should fire remove event", function(){\r
423 spy = spyOnEvent(oldParent, "remove").andCallThrough();\r
424 \r
425 rootNode.appendChild(spareNode);\r
426\r
427 // Just use the context argumemt from the args as the last arg\r
428 expect(spy).toHaveBeenCalledWith(oldParent, spareNode, true, spy.mostRecentCall.args[3]);\r
429 });\r
430\r
431 it("should fire beforemove event", function() {\r
432 spy = spyOnEvent(spareNode, "beforemove").andCallThrough();\r
433 \r
434 rootNode.appendChild(spareNode);\r
435\r
436 expect(spy).toHaveBeenCalledWith(spareNode, oldParent, rootNode, 0);\r
437 });\r
438 it("should fire move event", function() {\r
439 spy = spyOnEvent(spareNode, "move").andCallThrough();\r
440 \r
441 rootNode.appendChild(spareNode);\r
442 \r
443 expect(spy).toHaveBeenCalledWith(spareNode, oldParent, rootNode, 0); \r
444 });\r
445 });\r
446 });\r
447\r
448 describe("insert", function(){\r
449 \r
450 beforeEach(function(){\r
451 rootNode.appendChild(rightChild);\r
452 });\r
453 \r
454 describe("inserting children", function() {\r
455 it("should call appendChild if the node to insert before is null", function() {\r
456 spy = spyOn(rootNode, "appendChild");\r
457 \r
458 rootNode.insertBefore(leftChild);\r
459 \r
460 expect(spy).toHaveBeenCalledWith(leftChild);\r
461 });\r
462 \r
463 it("should do nothing if the node to insert before is equal to the node to insert", function() {\r
464 expect(rootNode.insertBefore(leftChild, leftChild)).toBe(false);\r
465 });\r
466 \r
467 it("should fire beforeinsert", function() {\r
468 spy = spyOnEvent(rootNode, "beforeinsert").andCallThrough();\r
469 \r
470 rootNode.insertBefore(leftChild, rightChild);\r
471 \r
472 expect(spy).toHaveBeenCalledWith(rootNode, leftChild, rightChild); \r
473 });\r
474 \r
475 it("should cancel insert if beforeinsert return false", function() {\r
476 spy = spyOnEvent(rootNode, "beforeinsert").andReturn(false);\r
477 \r
478 expect(rootNode.insertBefore(leftChild, rightChild)).toBe(false);\r
479 \r
480 expect(spy.callCount).toEqual(1);\r
481 });\r
482 \r
483 it("should set firstChild", function() {\r
484 rootNode.insertBefore(leftChild, rightChild);\r
485 \r
486 expect(rootNode.firstChild).toEqual(leftChild);\r
487 });\r
488 \r
489 it("should set lastChild", function() {\r
490 rootNode.insertBefore(leftChild, rightChild);\r
491 \r
492 expect(rootNode.lastChild).toEqual(rightChild);\r
493 });\r
494 \r
495 it("should fire insert", function() {\r
496 spy = spyOnEvent(rootNode, "insert").andCallThrough();\r
497 \r
498 rootNode.insertBefore(leftChild, rightChild);\r
499 \r
500 expect(spy).toHaveBeenCalledWith(rootNode, leftChild, rightChild); \r
501 });\r
502 \r
503 it("should update indexes for all siblings after the position where the node was inserted", function() {\r
504 rootNode.insertBefore(spareNode, rightChild);\r
505\r
506 rootNode.insertBefore(leftChild, spareNode);\r
507\r
508 expect(spareNode.get('index')).toEqual(1);\r
509 expect(rightChild.get('index')).toEqual(2);\r
510 });\r
511\r
512 \r
513 it("should handle siblings", function(){\r
514 expect(leftChild.previousSibling).toBeNull();\r
515 expect(leftChild.nextSibling).toBeNull();\r
516 expect(rightChild.previousSibling).toBeNull();\r
517 expect(rightChild.nextSibling).toBeNull();\r
518 \r
519 rootNode.insertBefore(leftChild, rightChild);\r
520 \r
521 expect(leftChild.previousSibling).toBeNull();\r
522 expect(leftChild.nextSibling).toEqual(rightChild);\r
523 expect(rightChild.previousSibling).toEqual(leftChild);\r
524 expect(rightChild.nextSibling).toBeNull();\r
525 });\r
526 \r
527 describe("move", function() {\r
528 beforeEach(function() {\r
529 rootNode.appendChild(leftChild);\r
530 });\r
531 \r
532 it("should fire beforemove", function() {\r
533 spy = spyOnEvent(leftChild, "beforemove").andCallThrough();\r
534 \r
535 rootNode.insertBefore(leftChild, rightChild);\r
536 \r
537 expect(spy).toHaveBeenCalledWith(leftChild, rootNode, rootNode, 0, rightChild); \r
538 });\r
539 \r
540 it("should cancel insert if beforemove return false", function() {\r
541 spy = spyOnEvent(leftChild, "beforemove").andReturn(false);\r
542 \r
543 expect(rootNode.insertBefore(leftChild, rightChild)).toBe(false);\r
544 \r
545 expect(spy.callCount).toEqual(1);\r
546 });\r
547 \r
548 it("should fire move", function() {\r
549 spy = spyOnEvent(leftChild, "move").andCallThrough();\r
550 \r
551 rootNode.insertBefore(leftChild, rightChild);\r
552 \r
553 expect(spy).toHaveBeenCalledWith(leftChild, rootNode, rootNode, 0, rightChild); \r
554 }); \r
555 \r
556 });\r
557 });\r
558 });\r
559\r
560 describe("removing children", function() {\r
561 it("should return false when removing bad node", function(){\r
562 expect(rootNode.removeChild(leftChild)).toBe(false); \r
563 });\r
564 \r
565 it("should fire beforeremove event", function(){\r
566 insertDefaultChildren.call(this);\r
567 \r
568 spy = spyOnEvent(rootNode, "beforeremove").andCallThrough();\r
569 \r
570 rootNode.removeChild(leftChild);\r
571 \r
572 expect(spy).toHaveBeenCalledWith(rootNode, leftChild, false);\r
573 });\r
574 \r
575 it("should cancel remove if beforeremove returns false", function() {\r
576 insertDefaultChildren.call(this);\r
577 \r
578 spy = spyOnEvent(rootNode, "beforeremove").andReturn(false);\r
579 \r
580 expect(rootNode.removeChild(leftChild)).toBe(false);\r
581 \r
582 expect(spy.callCount).toEqual(1);\r
583 });\r
584 \r
585 it("should fire remove event", function() {\r
586 insertDefaultChildren.call(this);\r
587 \r
588 spy = spyOnEvent(rootNode, "remove").andCallThrough();\r
589 \r
590 rootNode.removeChild(leftChild);\r
591\r
592 // Just use the context argumemt from the args as the last arg\r
593 expect(spy).toHaveBeenCalledWith(rootNode, leftChild, false, spy.mostRecentCall.args[3]);\r
594 });\r
595 \r
596 it("should remove child from childNodes", function() {\r
597 var childNodes, count;\r
598 \r
599 insertDefaultChildren.call(this);\r
600 \r
601 childNodes = rootNode.childNodes;\r
602 count = childNodes.length;\r
603 \r
604 rootNode.removeChild(leftChild);\r
605 \r
606 expect(childNodes.length).toEqual(count - 1);\r
607 expect(childNodes[0]).toEqual(rightChild);\r
608 });\r
609 \r
610 it("should manage siblings", function() {\r
611 insertDefaultChildren.call(this);\r
612 \r
613 //this gives us a third child - 'right' is actually now center\r
614 rootNode.appendChild(spareNode);\r
615 \r
616 rootNode.removeChild(rightChild);\r
617 \r
618 expect(leftChild.nextSibling, spareNode);\r
619 \r
620 expect(spareNode.previousSibling, leftChild);\r
621 });\r
622 \r
623 it("should erase node if asked", function() {\r
624 insertDefaultChildren.call(this);\r
625 \r
626 spy = spyOn(leftChild, "erase").andCallThrough();\r
627 \r
628 rootNode.removeChild(leftChild, true);\r
629 \r
630 expect(spy).toHaveBeenCalled();\r
631 });\r
632 \r
633 it("should clear node if asked", function() {\r
634 insertDefaultChildren.call(this);\r
635 \r
636 spy = spyOn(leftChild, "clear").andCallThrough();\r
637 \r
638 rootNode.removeChild(leftChild, false);\r
639 \r
640 expect(spy).toHaveBeenCalled();\r
641 }); \r
642 it("should update indexes for all siblings after the node's old position", function() {\r
643 insertDefaultChildren.call(this);\r
644\r
645 rootNode.appendChild(spareNode);\r
646\r
647 rootNode.removeChild(leftChild);\r
648\r
649 expect(rightChild.get('index')).toEqual(0);\r
650 expect(spareNode.get('index')).toEqual(1);\r
651 });\r
652 });\r
653 \r
654 describe("clearing references", function() {\r
655 beforeEach(function(){\r
656 insertDefaultChildren.call(this);\r
657 rootNode.appendChild(spareNode);\r
658 });\r
659 \r
660 it("should nullify parentNode", function() {\r
661 expect(rightChild.parentNode).not.toBeNull();\r
662 \r
663 rightChild.clear();\r
664 \r
665 expect(rightChild.parentNode).toBeNull();\r
666 });\r
667 \r
668 it("should nullifies nextSibling", function() {\r
669 expect(rightChild.nextSibling).not.toBeNull();\r
670 \r
671 rightChild.clear();\r
672 \r
673 expect(rightChild.nextSibling).toBeNull();\r
674 });\r
675 \r
676 it("should nullifies previousSibling", function() {\r
677 expect(rightChild.previousSibling).not.toBeNull();\r
678 \r
679 rightChild.clear();\r
680 \r
681 expect(rightChild.previousSibling).toBeNull();\r
682 });\r
683 \r
684 it("should remove lastChild and firstChild references", function() {\r
685 rightChild.clear(true);\r
686 \r
687 expect(rightChild.firstChild).toBeNull();\r
688 expect(rightChild.lastChild).toBeNull();\r
689 });\r
690 });\r
691\r
692 describe("item", function() {\r
693 it("should return the child node at the specified index", function() {\r
694 rootNode.appendChild(leftChild);\r
695 rootNode.appendChild(rightChild);\r
696 rootNode.appendChild(spareNode);\r
697 \r
698 expect(rootNode.getChildAt(0)).toEqual(leftChild);\r
699 expect(rootNode.getChildAt(1)).toEqual(rightChild);\r
700 expect(rootNode.getChildAt(2)).toEqual(spareNode);\r
701 });\r
702 });\r
703\r
704 describe("silent destroy", function() {\r
705 it("should purge node listeners", function() {\r
706 spy = spyOn(leftChild.mixins.observable, "clearListeners").andCallThrough();\r
707 \r
708 leftChild.destroy(true);\r
709 \r
710 expect(spy).toHaveBeenCalled();\r
711 });\r
712\r
713 it("should erase children", function() {\r
714 var spy2;\r
715 \r
716 insertDefaultChildren.call(this);\r
717 \r
718 spy = spyOn(leftChild, "erase").andCallThrough();\r
719 spy2 = spyOn(rightChild, "erase").andCallThrough();\r
720 \r
721 rootNode.erase();\r
722 \r
723 expect(spy).toHaveBeenCalled();\r
724 expect(spy2).toHaveBeenCalled();\r
725 });\r
726 \r
727 it("should nullify childNodes", function() {\r
728 insertDefaultChildren.call(this);\r
729 \r
730 expect(rootNode.childNodes).not.toBeNull();\r
731 \r
732 rootNode.erase(true);\r
733 \r
734 expect(rootNode.childNodes).toBeNull();\r
735 });\r
736 });\r
737\r
738 describe("non-silent destroy", function() {\r
739 it("should remove node", function() {\r
740 insertDefaultChildren.call(this);\r
741 \r
742 spy = spyOn(leftChild, "remove").andCallThrough();\r
743 \r
744 leftChild.erase(false);\r
745 \r
746 expect(spy).toHaveBeenCalled();\r
747 });\r
748 });\r
749 \r
750 describe("remove", function() {\r
751 it("should remove from parent", function() {\r
752 spy = spyOn(rootNode, "removeChild").andCallThrough();\r
753 \r
754 rootNode.appendChild(leftChild);\r
755 \r
756 leftChild.remove();\r
757 \r
758 expect(spy).toHaveBeenCalledWith(leftChild, undefined, undefined);\r
759 });\r
760 \r
761 it("should return node", function() {\r
762 expect(leftChild.remove()).toEqual(leftChild);\r
763 });\r
764 });\r
765 \r
766 describe("removeAll", function() {\r
767 it("should remove all children", function() {\r
768 rootNode.appendChild([leftChild, rightChild, spareNode]);\r
769 rootNode.removeAll();\r
770 expect(rootNode.childNodes.length).toBe(0);\r
771 });\r
772 });\r
773\r
774 describe("replacing children", function() {\r
775 beforeEach(function() {\r
776 insertDefaultChildren.call(this);\r
777 });\r
778 \r
779 it("should keep the same childNodes length", function() {\r
780 var count = rootNode.childNodes.length;\r
781 \r
782 rootNode.replaceChild(spareNode, leftChild);\r
783 \r
784 expect(rootNode.childNodes.length).toEqual(count);\r
785 });\r
786 \r
787 it("should replace node", function() {\r
788 rootNode.replaceChild(spareNode, leftChild);\r
789 \r
790 expect(rootNode.childNodes[0], spareNode);\r
791 });\r
792 });\r
793 \r
794 describe("getting depth", function() {\r
795 beforeEach(function() {\r
796 insertDefaultChildren.call(this);\r
797 leftChild.appendChild(spareNode);\r
798 });\r
799 \r
800 it("should have a depth of 0 for rootNode", function(){\r
801 expect(rootNode.getDepth()).toEqual(0);\r
802 });\r
803 \r
804 it("should have a depth of 1 for leftChild and rightChild", function(){\r
805 expect(rightChild.getDepth()).toEqual(1);\r
806 expect(leftChild.getDepth()).toEqual(1);\r
807 });\r
808 \r
809 it("should have a depth of 2 for spareNode", function(){\r
810 expect(spareNode.getDepth()).toEqual(2); \r
811 });\r
812 });\r
813\r
814 describe("getting path", function() {\r
815 beforeEach(function() {\r
816 insertDefaultChildren.call(this);\r
817 leftChild.appendChild(spareNode);\r
818 });\r
819 \r
820 it("should set root path", function() {\r
821 expect(rootNode.getPath()).toEqual("/root");\r
822 });\r
823 \r
824 it("should set middle path", function() {\r
825 expect(leftChild.getPath()).toEqual("/root/left");\r
826 expect(rightChild.getPath()).toEqual("/root/right");\r
827 });\r
828 \r
829 it("should set leaf path", function() {\r
830 expect(spareNode.getPath()).toEqual("/root/left/spare");\r
831 });\r
832 });\r
833 \r
834 describe("indexOf", function(){\r
835 it("should always return -1 when the node is empty", function(){\r
836 expect(rootNode.indexOf(spareNode)).toBe(-1);\r
837 });\r
838 \r
839 it("should return -1 when the passed node is not a child", function(){\r
840 rootNode.appendChild(leftChild);\r
841 expect(rootNode.indexOf(spareNode)).toBe(-1); \r
842 });\r
843 \r
844 it("should return the correct index when the node exists", function(){\r
845 rootNode.appendChild([leftChild, spareNode, rightChild]); \r
846 expect(rootNode.indexOf(spareNode)).toBe(1); \r
847 });\r
848 });\r
849 \r
850 describe("indexOfId", function(){\r
851 it("should always return -1 when the node is empty", function(){\r
852 expect(rootNode.indexOfId('spare')).toBe(-1);\r
853 });\r
854 \r
855 it("should return -1 when the passed node is not a child", function(){\r
856 rootNode.appendChild(leftChild);\r
857 expect(rootNode.indexOfId('spare')).toBe(-1); \r
858 });\r
859 \r
860 it("should return the correct index when the node exists", function(){\r
861 rootNode.appendChild([leftChild, spareNode, rightChild]); \r
862 expect(rootNode.indexOfId('spare')).toBe(1); \r
863 });\r
864 });\r
865 \r
866 describe("bubbling", function() {\r
867 var bubbleFn;\r
868 \r
869 beforeEach(function() {\r
870 insertDefaultChildren.call(this);\r
871 leftChild.appendChild(spareNode);\r
872 bubbleFn = jasmine.createSpy();\r
873 });\r
874 \r
875 it("should call bubbleFn 3 times", function() {\r
876 spareNode.bubble(bubbleFn);\r
877 \r
878 expect(bubbleFn.callCount).toEqual(3);\r
879 });\r
880 \r
881 it("should call bubbleFn with node spare, left, root", function() {\r
882 spareNode.bubble(bubbleFn);\r
883 \r
884 expect(bubbleFn.calls[0].args).toEqual([spareNode]);\r
885 expect(bubbleFn.calls[1].args).toEqual([leftChild]);\r
886 expect(bubbleFn.calls[2].args).toEqual([rootNode]);\r
887 });\r
888 \r
889 it("should call bubbleFn with a defined scope", function() {\r
890 spareNode.bubble(bubbleFn, fakeScope);\r
891 \r
892 expect(bubbleFn.calls[0].object).toBe(fakeScope);\r
893 expect(bubbleFn.calls[1].object).toBe(fakeScope);\r
894 expect(bubbleFn.calls[2].object).toBe(fakeScope);\r
895 });\r
896 \r
897 it("should call bubbleFn with customs arguments", function() {\r
898 var customArgs = ['some', 'args'];\r
899 \r
900 spareNode.bubble(bubbleFn, spareNode, customArgs);\r
901 \r
902 expect(bubbleFn.calls[0].args).toEqual(customArgs);\r
903 expect(bubbleFn.calls[1].args).toEqual(customArgs);\r
904 expect(bubbleFn.calls[2].args).toEqual(customArgs);\r
905 });\r
906 \r
907 it("should stop when bubbleFn return false", function() {\r
908 bubbleFn.andCallFake(function(node) {\r
909 if (node.getId() == 'left') {\r
910 return false;\r
911 }\r
912 });\r
913 \r
914 spareNode.bubble(bubbleFn);\r
915 \r
916 expect(bubbleFn.callCount).toEqual(2);\r
917 });\r
918 });\r
919 \r
920 describe("cascading", function() {\r
921 var cascadeFn;\r
922 \r
923 beforeEach(function(){\r
924 insertDefaultChildren.call(this);\r
925 leftChild.appendChild(spareNode);\r
926 cascadeFn = jasmine.createSpy();\r
927 });\r
928 \r
929 it("should call cascadeFn 4 times", function() {\r
930 rootNode.cascadeBy(cascadeFn);\r
931 \r
932 expect(cascadeFn.callCount).toEqual(4);\r
933 });\r
934 \r
935 it("should call cascadeFn with node root, leftChild, spareNode, rightChild", function() {\r
936 rootNode.cascadeBy(cascadeFn);\r
937 \r
938 expect(cascadeFn.calls[0].args).toEqual([rootNode]);\r
939 expect(cascadeFn.calls[1].args).toEqual([leftChild]);\r
940 expect(cascadeFn.calls[2].args).toEqual([spareNode]);\r
941 expect(cascadeFn.calls[3].args).toEqual([rightChild]);\r
942 });\r
943 \r
944 it("should call cascadeFn with a defined scope", function() {\r
945 rootNode.cascadeBy(cascadeFn, fakeScope);\r
946 \r
947 expect(cascadeFn.calls[0].object).toBe(fakeScope);\r
948 expect(cascadeFn.calls[1].object).toBe(fakeScope);\r
949 expect(cascadeFn.calls[2].object).toBe(fakeScope);\r
950 expect(cascadeFn.calls[3].object).toBe(fakeScope);\r
951 });\r
952 \r
953 it("should call cascadeFn with customs arguments", function() {\r
954 var customArgs = ['some', 'args'];\r
955 \r
956 rootNode.cascadeBy(cascadeFn, rootNode, customArgs);\r
957 \r
958 expect(cascadeFn.calls[0].args).toEqual(customArgs);\r
959 expect(cascadeFn.calls[1].args).toEqual(customArgs);\r
960 expect(cascadeFn.calls[2].args).toEqual(customArgs);\r
961 expect(cascadeFn.calls[3].args).toEqual(customArgs);\r
962 });\r
963 \r
964 it("should stop at end of branch when cascadeFn return false", function() {\r
965 cascadeFn.andCallFake(function(node) {\r
966 if (node.getId() == 'left') {\r
967 return false;\r
968 }\r
969 });\r
970 \r
971 rootNode.cascadeBy(cascadeFn);\r
972 \r
973 expect(cascadeFn.callCount).toEqual(3);\r
974 });\r
975 });\r
976\r
977 describe("each child", function() {\r
978 var eachFn;\r
979 \r
980 beforeEach(function (){\r
981 insertDefaultChildren.call(this);\r
982 eachFn = jasmine.createSpy();\r
983 });\r
984 \r
985 it("should be called 2 times", function() {\r
986 \r
987 rootNode.eachChild(eachFn);\r
988 \r
989 expect(eachFn.callCount).toEqual(2);\r
990 });\r
991 \r
992 it("should call eachFn with node root, leftChild, rightChild", function() {\r
993 rootNode.eachChild(eachFn);\r
994 \r
995 expect(eachFn.calls[0].args).toEqual([leftChild]);\r
996 expect(eachFn.calls[1].args).toEqual([rightChild]);\r
997 });\r
998 \r
999 it("should call eachFn with a defined scope", function() {\r
1000 rootNode.eachChild(eachFn, fakeScope);\r
1001 \r
1002 expect(eachFn.calls[0].object).toBe(fakeScope);\r
1003 expect(eachFn.calls[1].object).toBe(fakeScope);\r
1004 });\r
1005 \r
1006 it("should call eachFn with customs arguments", function() {\r
1007 var customArgs = ['some', 'args'];\r
1008 \r
1009 rootNode.eachChild(eachFn, rootNode, customArgs);\r
1010 \r
1011 expect(eachFn.calls[0].args).toEqual(customArgs);\r
1012 expect(eachFn.calls[1].args).toEqual(customArgs);\r
1013 });\r
1014 \r
1015 it("should stop when eachFn return false", function() {\r
1016 eachFn.andCallFake(function(node) {\r
1017 if (node.getId() == 'left') {\r
1018 return false;\r
1019 }\r
1020 });\r
1021 \r
1022 rootNode.eachChild(eachFn);\r
1023 \r
1024 expect(eachFn.callCount).toEqual(1);\r
1025 });\r
1026 });\r
1027 \r
1028 describe("ancestors", function() {\r
1029 beforeEach(function (){\r
1030 insertDefaultChildren.call(this);\r
1031 leftChild.appendChild(spareNode);\r
1032 });\r
1033 \r
1034 it("should have parent as ancestor", function() {\r
1035 expect(spareNode.isAncestor(leftChild)).toBe(true);\r
1036 });\r
1037 \r
1038 it("should have root as ancestor", function() {\r
1039 expect(spareNode.isAncestor(rootNode)).toBe(true);\r
1040 });\r
1041 \r
1042 it("should not have uncle as ancestor", function() {\r
1043 expect(spareNode.isAncestor(rightChild)).toBe(false);\r
1044 }); \r
1045 });\r
1046 \r
1047 describe("contains", function() {\r
1048 beforeEach(function (){\r
1049 insertDefaultChildren.call(this);\r
1050 leftChild.appendChild(spareNode);\r
1051 });\r
1052 \r
1053 it("should contain child", function() {\r
1054 expect(rootNode.contains(leftChild)).toBe(true);\r
1055 });\r
1056 \r
1057 it("should contain grand child", function() {\r
1058 expect(rootNode.contains(spareNode)).toBe(true);\r
1059 });\r
1060 \r
1061 it("should not contain parent", function() {\r
1062 expect(spareNode.contains(leftChild)).toBe(false);\r
1063 }); \r
1064 });\r
1065\r
1066 describe("finding children", function() {\r
1067 beforeEach(function (){\r
1068 insertDefaultChildren.call(this);\r
1069 leftChild.appendChild(spareNode);\r
1070 });\r
1071 \r
1072 describe("findChild", function() {\r
1073 it("should find shallow children", function() {\r
1074 expect(rootNode.findChild('id', 'left')).toEqual(leftChild);\r
1075 });\r
1076 \r
1077 it("should not find deep children if deep is not specified", function() {\r
1078 expect(rootNode.findChild('id', 'spare')).toBeNull();\r
1079 });\r
1080 \r
1081 it("should not find deep children if deep is false", function() {\r
1082 expect(rootNode.findChild('id', 'spare', false)).toBeNull();\r
1083 });\r
1084 \r
1085 it("should find deep children if deep is true", function() {\r
1086 expect(rootNode.findChild('id', 'spare', true)).toEqual(spareNode);\r
1087 }); \r
1088 });\r
1089 \r
1090 describe("findChildBy", function() {\r
1091 var child;\r
1092 \r
1093 it("should find shallow children", function(){\r
1094 child = rootNode.findChildBy(function(node) {\r
1095 return node.getId() == 'right';\r
1096 });\r
1097 \r
1098 expect(child).toEqual(rightChild);\r
1099 });\r
1100 \r
1101 it("should not find deep children if deep is not specified", function(){\r
1102 child = rootNode.findChildBy(function(node) {\r
1103 return node.getId() == 'spare';\r
1104 });\r
1105 \r
1106 expect(child).toBeNull();\r
1107 });\r
1108 \r
1109 it("should not find deep children if deep is false", function(){\r
1110 child = rootNode.findChildBy(function(node) {\r
1111 return node.getId() == 'spare';\r
1112 }, this, false);\r
1113 \r
1114 expect(child).toBeNull();\r
1115 });\r
1116 \r
1117 it("should find deep children if deep is true", function(){\r
1118 child = rootNode.findChildBy(function(node) {\r
1119 return node.getId() == 'spare';\r
1120 }, this, true);\r
1121 \r
1122 expect(child).toEqual(spareNode);\r
1123 });\r
1124 \r
1125 it("should call function with good scope", function(){\r
1126 var findChildFn = jasmine.createSpy().andReturn(false);\r
1127 \r
1128 child = rootNode.findChildBy(findChildFn, fakeScope, true);\r
1129 \r
1130 expect(findChildFn.calls[0].object).toBe(fakeScope);\r
1131 expect(findChildFn.calls[1].object).toBe(fakeScope);\r
1132 expect(findChildFn.calls[2].object).toBe(fakeScope); \r
1133 });\r
1134 });\r
1135 });\r
1136 \r
1137 describe("sort", function() {\r
1138 var node1,\r
1139 node2,\r
1140 node3,\r
1141 node4,\r
1142 sortFn;\r
1143 \r
1144 beforeEach(function() {\r
1145 Ext.define('spec.EmployeeTreeNode', {\r
1146 extend: 'Ext.data.Model',\r
1147 fields: [\r
1148 { name: 'lastname', type: 'string' },\r
1149 { name: 'firstname', type: 'string' }\r
1150 ]\r
1151 });\r
1152 Ext.data.NodeInterface.decorate(spec.EmployeeTreeNode);\r
1153 node1 = new spec.EmployeeTreeNode({lastname: "Avins", firstname: "Jamie"});\r
1154 node2 = new spec.EmployeeTreeNode({lastname: "Dougan", firstname: "Robert"});\r
1155 node3 = new spec.EmployeeTreeNode({lastname: "Ferrero", firstname: "Nicolas"});\r
1156 node4 = new spec.EmployeeTreeNode({lastname: "Spencer", firstname: "Edward"});\r
1157 \r
1158 rootNode.appendChild([node4, node2, node3, node1]);\r
1159 \r
1160 sortFn = jasmine.createSpy();\r
1161 sortFn.andCallFake(function(a, b){\r
1162 if (a.get('lastname') === b.get('lastname')) {\r
1163 return 0;\r
1164 }\r
1165 return (a.get('lastname') < b.get('lastname')) ? -1 : 1;\r
1166 });\r
1167 \r
1168 rootNode.sort(sortFn);\r
1169 });\r
1170 afterEach(function() {\r
1171 Ext.undefine('spec.EmployeeTreeNode');\r
1172 });\r
1173 \r
1174 it("should sort the child by lastname with the correct function", function() {\r
1175 expect(rootNode.childNodes[0]).toEqual(node1);\r
1176 expect(rootNode.childNodes[1]).toEqual(node2);\r
1177 expect(rootNode.childNodes[2]).toEqual(node3);\r
1178 expect(rootNode.childNodes[3]).toEqual(node4);\r
1179 });\r
1180 \r
1181 });\r
1182 \r
1183 describe("copy", function(){\r
1184 it("should not copy childNodes by default", function(){\r
1185 var node = new spec.TreeNode({\r
1186 text: 'Text',\r
1187 id: 1\r
1188 });\r
1189\r
1190 var newNode = node.copy();\r
1191 \r
1192 expect(newNode.getData()).toEqual({\r
1193 allowDrag: true,\r
1194 allowDrop: true,\r
1195 checked: null,\r
1196 children: null,\r
1197 cls: '',\r
1198 depth: 0,\r
1199 expandable: true,\r
1200 expanded: false,\r
1201 href: '',\r
1202 hrefTarget: '',\r
1203 icon: '',\r
1204 iconCls: '',\r
1205 id: 1,\r
1206 index: -1,\r
1207 isFirst: false,\r
1208 isLast: false,\r
1209 leaf: false,\r
1210 loaded: false,\r
1211 loading: false,\r
1212 parentId: null,\r
1213 qtip: '',\r
1214 qtitle: '',\r
1215 qshowDelay: 0,\r
1216 root: false,\r
1217 text: 'Text',\r
1218 visible: true\r
1219 });\r
1220 });\r
1221 \r
1222 it("should accept a new id", function(){\r
1223 var node = new spec.TreeNode({\r
1224 text: 'Text',\r
1225 id: 1\r
1226 });\r
1227 \r
1228 var newNode = node.copy(2);\r
1229 \r
1230 expect(newNode.getData()).toEqual({\r
1231 allowDrag: true,\r
1232 allowDrop: true,\r
1233 checked: null,\r
1234 children: null,\r
1235 cls: '',\r
1236 depth: 0,\r
1237 expandable: true,\r
1238 expanded: false,\r
1239 href: '',\r
1240 hrefTarget: '',\r
1241 icon: '',\r
1242 iconCls: '',\r
1243 id: 2,\r
1244 index: -1,\r
1245 isFirst: false,\r
1246 isLast: false,\r
1247 leaf: false,\r
1248 loaded: false,\r
1249 loading: false,\r
1250 parentId: null,\r
1251 qtip: '',\r
1252 qtitle: '',\r
1253 qshowDelay: 0,\r
1254 root: false,\r
1255 text: 'Text',\r
1256 visible: true\r
1257 });\r
1258 });\r
1259 \r
1260 it("should clone children if deep: true is specified", function(){\r
1261 var root = new spec.TreeNode({\r
1262 id: 1,\r
1263 text: 'Root'\r
1264 }); \r
1265 var child1 = root.appendChild(new spec.TreeNode({\r
1266 id: 2,\r
1267 text: 'Child1'\r
1268 }));\r
1269 var child2 = child1.appendChild(new spec.TreeNode({\r
1270 id: 3,\r
1271 text: 'Child2'\r
1272 }));\r
1273 child2.appendChild(new spec.TreeNode({\r
1274 id: 4,\r
1275 text: 'Child3'\r
1276 }));\r
1277 \r
1278 var newNode = root.copy(undefined, true);\r
1279 expect(newNode.childNodes[0].getId()).toBe(2);\r
1280 expect(newNode.childNodes[0].get('text')).toBe('Child1');\r
1281 \r
1282 newNode = newNode.childNodes[0];\r
1283 expect(newNode.childNodes[0].getId()).toBe(3);\r
1284 expect(newNode.childNodes[0].get('text')).toBe('Child2');\r
1285 \r
1286 newNode = newNode.childNodes[0];\r
1287 expect(newNode.childNodes[0].getId()).toBe(4);\r
1288 expect(newNode.childNodes[0].get('text')).toBe('Child3');\r
1289 });\r
1290 });\r
1291 \r
1292 });\r
1293 \r
1294 describe("serialize", function(){\r
1295 it('should create an object representation of the node', function() {\r
1296 var node = new spec.TreeNode({\r
1297 text: 'Root',\r
1298 id: 1\r
1299 }),\r
1300 c1 = node.appendChild(new spec.TreeNode({\r
1301 text: 'C1',\r
1302 id: 2\r
1303 })),\r
1304 c2 = node.appendChild(new spec.TreeNode({\r
1305 text: 'C1',\r
1306 id: 3\r
1307 }));\r
1308 c1.appendChild( new spec.TreeNode({\r
1309 text: 'c1.1',\r
1310 id: 4\r
1311 }));\r
1312 c2.appendChild( new spec.TreeNode({\r
1313 text: 'c2.1',\r
1314 id: 5\r
1315 }));\r
1316\r
1317 expect(node.serialize()).toEqual({\r
1318 "text": "Root",\r
1319 "id": 1,\r
1320 "parentId": null,\r
1321 "leaf": false,\r
1322 "children": [\r
1323 {\r
1324 "text": "C1",\r
1325 "id": 2,\r
1326 "parentId": 1,\r
1327 "leaf": false,\r
1328 "children": [\r
1329 {\r
1330 "text": "c1.1",\r
1331 "id": 4,\r
1332 "parentId": 2,\r
1333 "leaf": false\r
1334 }\r
1335 ]\r
1336 },\r
1337 {\r
1338 "text": "C1",\r
1339 "id": 3,\r
1340 "parentId": 1,\r
1341 "leaf": false,\r
1342 "children": [\r
1343 {\r
1344 "text": "c2.1",\r
1345 "id": 5,\r
1346 "parentId": 3,\r
1347 "leaf": false\r
1348 }\r
1349 ]\r
1350 }\r
1351 ]\r
1352 });\r
1353 });\r
1354\r
1355 it("should not include children if there are none", function(){\r
1356 var o = new spec.TreeNode({\r
1357 text: 'foo'\r
1358 }), s = o.serialize();\r
1359 \r
1360 expect(s.text).toBe('foo');\r
1361 expect(s.children).toBeUndefined();\r
1362 });\r
1363 \r
1364 it("should include children if they exist", function(){\r
1365 var o = new spec.TreeNode({\r
1366 text: 'foo'\r
1367 }), s;\r
1368 \r
1369 o.appendChild(new spec.TreeNode({\r
1370 text: 'bar'\r
1371 }));\r
1372 \r
1373 s = o.serialize();\r
1374 expect(s.text).toBe('foo');\r
1375 expect(s.children[0].text).toBe('bar');\r
1376 }); \r
1377 });\r
1378 \r
1379 describe("collapse", function() {\r
1380 it("should fire the collapse callback when there are no child nodes", function() {\r
1381 var root = new spec.TreeNode(),\r
1382 called;\r
1383 \r
1384 root.collapseChildren(false, function() {\r
1385 called = true;\r
1386 });\r
1387 expect(called).toBe(true);\r
1388 root = null;\r
1389 }); \r
1390 });\r
1391\r
1392 describe("modified property tracking", function() {\r
1393 // Tests for https://sencha.jira.com/browse/EXTJSIV-9223 and https://sencha.jira.com/browse/EXTJSIV-9165\r
1394 it("should track modifications of fields set as a result of node movement", function() {\r
1395\r
1396 // Create a TreeNode subclass in which the index property is persistent.\r
1397 Ext.define('spec.PersistentIndexTreeNode', {\r
1398 extend: 'Ext.data.TreeModel',\r
1399 fields: [\r
1400 {name: 'text', type: 'string'},\r
1401 {name: 'index', type: 'int', persist: true, defaultValue: -1}\r
1402 ],\r
1403 proxy: {\r
1404 type: 'memory'\r
1405 }\r
1406 });\r
1407\r
1408 var root = new spec.PersistentIndexTreeNode({\r
1409 id: 'TestRoot'\r
1410 }),\r
1411 root1 = new spec.PersistentIndexTreeNode({\r
1412 id: 'OtherTestRoot'\r
1413 }),\r
1414 node = new spec.PersistentIndexTreeNode({\r
1415 id: 'node'\r
1416 }),\r
1417 node1;\r
1418 root.appendChild(node);\r
1419\r
1420 // The modified shows that parentId was changed *from* null.\r
1421 // And the index was changed from -1 (not attached) to 0\r
1422 expect(node.modified).toEqual({\r
1423 index: -1,\r
1424 parentId: null\r
1425 });\r
1426\r
1427 // Clears modified\r
1428 node.commit();\r
1429 expect(node.modified).toBeNull();\r
1430\r
1431 // Move from parent "TestRoot", index 0 to parent "OtherTestRoot", index 0\r
1432 // Index should appear in modified object because it has moved parent\r
1433 root1.appendChild(node);\r
1434 expect(node.modified).toEqual({\r
1435 parentId: 'TestRoot',\r
1436 index: 0\r
1437 });\r
1438\r
1439 // Clears modified\r
1440 node.commit();\r
1441\r
1442 // Should clear the parentId, so the modified now indicates that it was removed from index 0 of "OtherTestRoot"\r
1443 // removeChild does NOT clear context data properties.\r
1444 // Mainly because TreeStore.clearRemovedOnLoad uses these values to determine whether\r
1445 // nodes in the removed list are descendants of a loading node so that tey can be evicted from the removed list.\r
1446 root1.removeChild(node);\r
1447 expect(node.modified).toEqual({\r
1448 lastParentId: undefined,\r
1449 parentId: 'OtherTestRoot'\r
1450 });\r
1451\r
1452 node = new spec.PersistentIndexTreeNode({\r
1453 id: 'node'\r
1454 });\r
1455 node1 = new spec.PersistentIndexTreeNode({\r
1456 id: 'node1'\r
1457 });\r
1458 root.clear();\r
1459 root.appendChild([node, node1]);\r
1460\r
1461 expect([node.get('index'), node1.get('index')]).toEqual([0, 1]);\r
1462 node.commit();\r
1463 node1.commit();\r
1464\r
1465 // Move node1 to index:0\r
1466 root.insertBefore(node1, node);\r
1467\r
1468 // Indexes data values are switched\r
1469 expect([node1.get('index'), node.get('index')]).toEqual([0, 1]);\r
1470\r
1471 // node1 must report that its index was modified from initial value 1\r
1472 expect(node1.modified).toEqual({\r
1473 index: 1\r
1474 });\r
1475\r
1476 // node must report that its index was modified from initial value 0\r
1477 expect(node.modified).toEqual({\r
1478 index: 0\r
1479 });\r
1480\r
1481 root1.appendChild(node1);\r
1482\r
1483 Ext.undefine('spec.PersistentIndexTreeNode');\r
1484 });\r
1485 });\r
1486});\r