]>
git.proxmox.com Git - extjs.git/blob - extjs/packages/core/test/specs/data/NodeInterface.js
1 describe('Ext.data.NodeInterface', function() {
2 function spyOnEvent(object
, eventName
, fn
) {
6 spy
= spyOn(obj
, "fn");
7 object
.addListener(eventName
, obj
.fn
);
11 beforeEach(function() {
12 Ext
.define('spec.TreeNode', {
13 extend
: 'Ext.data.TreeModel',
15 {name
: 'text', type
: 'string'}
23 afterEach(function() {
24 Ext
.undefine('spec.TreeNode');
25 Ext
.data
.Model
.schema
.clear();
28 describe('decorating', function() {
31 beforeEach(function() {
32 fields
= spec
.TreeNode
.prototype.fieldsMap
;
35 it('should decorate the Model with a parentId field that has the same type as the idProperty', function() {
36 var field
= fields
.parentId
,
37 type
= fields
[spec
.TreeNode
.idProperty
].getType();
39 expect(field
.getPersist()).toBe(true);
40 expect(field
.getType()).toBe(type
);
41 expect(field
.getDefaultValue()).toBeNull();
43 it('should decorate the Model with an index field', function() {
44 var field
= fields
.index
;
46 expect(field
.getPersist()).toBe(false);
47 expect(field
.getType()).toBe('int');
48 expect(field
.getDefaultValue()).toBe(-1);
50 it('should decorate the Model with a depth field', function() {
51 var field
= fields
.depth
;
53 expect(field
.getPersist()).toBe(false);
54 expect(field
.getType()).toBe('int');
55 expect(field
.getDefaultValue()).toBe(0);
57 it('should decorate the Model with an expanded field', function() {
58 var field
= fields
.expanded
;
60 expect(field
.getPersist()).toBe(false);
61 expect(field
.getType()).toBe('bool');
62 expect(field
.getDefaultValue()).toBe(false);
64 it('should decorate the Model with an expandable field', function() {
65 var field
= fields
.expandable
;
67 expect(field
.getPersist()).toBe(false);
68 expect(field
.getType()).toBe('bool');
69 expect(field
.getDefaultValue()).toBe(true);
71 it('should decorate the Model with a checked field', function() {
72 var field
= fields
.checked
;
74 expect(field
.getPersist()).toBe(false);
75 expect(field
.getType()).toBe('auto');
76 expect(field
.getDefaultValue()).toBe(null);
78 it('should decorate the Model with a leaf field', function() {
79 var field
= fields
.leaf
;
81 expect(field
.getPersist()).toBe(true);
82 expect(field
.getType()).toBe('bool');
83 expect(field
.getDefaultValue()).toBe(false);
85 it('should decorate the Model with a cls field', function() {
86 var field
= fields
.cls
;
88 expect(field
.getPersist()).toBe(false);
89 expect(field
.getType()).toBe('string');
90 expect(field
.getDefaultValue()).toBe('');
92 it('should decorate the Model with an iconCls field', function() {
93 var field
= fields
.iconCls
;
95 expect(field
.getPersist()).toBe(false);
96 expect(field
.getType()).toBe('string');
97 expect(field
.getDefaultValue()).toBe('');
99 it('should decorate the Model with an icon field', function() {
100 var field
= fields
.icon
;
102 expect(field
.getPersist()).toBe(false);
103 expect(field
.getType()).toBe('string');
104 expect(field
.getDefaultValue()).toBe('');
106 it('should decorate the Model with a root field', function() {
107 var field
= fields
.root
;
109 expect(field
.getPersist()).toBe(false);
110 expect(field
.getType()).toBe('bool');
111 expect(field
.getDefaultValue()).toBe(false);
113 it('should decorate the Model with an isLast field', function() {
114 var field
= fields
.isLast
;
116 expect(field
.getPersist()).toBe(false);
117 expect(field
.getType()).toBe('bool');
118 expect(field
.getDefaultValue()).toBe(false);
120 it('should decorate the Model with an isFirst field', function() {
121 var field
= fields
.isFirst
;
123 expect(field
.getPersist()).toBe(false);
124 expect(field
.getType()).toBe('bool');
125 expect(field
.getDefaultValue()).toBe(false);
127 it('should decorate the Model with an allowDrop field', function() {
128 var field
= fields
.allowDrop
;
130 expect(field
.getPersist()).toBe(false);
131 expect(field
.getType()).toBe('bool');
132 expect(field
.getDefaultValue()).toBe(true);
135 it('should decorate the Model with an allowDrag field', function() {
136 var field
= fields
.allowDrag
;
138 expect(field
.getPersist()).toBe(false);
139 expect(field
.getType()).toBe('bool');
140 expect(field
.getDefaultValue()).toBe(true);
142 it('should decorate the Model with a loaded field', function() {
143 var field
= fields
.loaded
;
145 expect(field
.getPersist()).toBe(false);
146 expect(field
.getType()).toBe('bool');
147 expect(field
.getDefaultValue()).toBe(false);
149 it('should decorate the Model with a loading field', function() {
150 var field
= fields
.loading
;
152 expect(field
.getPersist()).toBe(false);
153 expect(field
.getType()).toBe('bool');
154 expect(field
.getDefaultValue()).toBe(false);
156 it('should decorate the Model with an href field', function() {
157 var field
= fields
.href
;
159 expect(field
.getPersist()).toBe(false);
160 expect(field
.getType()).toBe('string');
161 expect(field
.getDefaultValue()).toBe('');
163 it('should decorate the Model with an hrefTarget field', function() {
164 var field
= fields
.hrefTarget
;
166 expect(field
.getPersist()).toBe(false);
167 expect(field
.getType()).toBe('string');
168 expect(field
.getDefaultValue()).toBe('');
170 it('should decorate the Model with a qtip field', function() {
171 var field
= fields
.qtip
;
173 expect(field
.getPersist()).toBe(false);
174 expect(field
.getType()).toBe('string');
175 expect(field
.getDefaultValue()).toBe('');
177 it('should decorate the Model with a qtitle field', function() {
178 var field
= fields
.qtitle
;
180 expect(field
.getPersist()).toBe(false);
181 expect(field
.getType()).toBe('string');
182 expect(field
.getDefaultValue()).toBe('');
184 it('should decorate the Model with a children field', function() {
185 var field
= fields
.children
;
187 expect(field
.getPersist()).toBe(false);
188 expect(field
.getType()).toBe('auto');
189 expect(field
.getDefaultValue()).toBe(null);
191 it('should decorate Model class of a given record', function() {
192 var MyModel
, record1
, record2
;
193 MyModel
= Ext
.define('spec.MyModel', {
194 extend
: 'Ext.data.Model',
196 {name
: 'text', type
: 'string'}
202 record1
= MyModel
.create({text
: 'record1'});
203 record2
= MyModel
.create({text
: 'record2'});
204 expect(MyModel
.prototype.isNode
).toBeUndefined();
205 expect(record1
.isNode
).toBeUndefined();
206 expect(record2
.isNode
).toBeUndefined();
208 Ext
.data
.NodeInterface
.decorate(record1
);
209 expect(MyModel
.prototype.isNode
).toBeTruthy();
210 expect(record1
.isNode
).toBeTruthy();
211 expect(record2
.isNode
).toBeTruthy();
213 Ext
.undefine('spec.MyModel');
219 describe('methods', function() {
220 var leftChild
, rightChild
, rootNode
, spareNode
, spy
;
222 function insertDefaultChildren() {
223 rootNode
.appendChild(leftChild
);
224 rootNode
.appendChild(rightChild
);
225 rootNode
.updateInfo(false, {
234 beforeEach(function() {
235 leftChild
= new spec
.TreeNode({
239 rightChild
= new spec
.TreeNode({
243 rootNode
= new spec
.TreeNode({
247 //we use this in several tests as an example node to add
248 spareNode
= new spec
.TreeNode({
254 describe("isFirst", function() {
255 beforeEach(function() {
256 insertDefaultChildren
.call(this);
259 it("should have rootNode which is first", function() {
260 expect(rootNode
.isFirst()).toBe(true);
262 it("should have leftChild which is first", function() {
263 expect(leftChild
.isFirst()).toBe(true);
265 it("should have rightChild which is not first", function() {
266 expect(rightChild
.isFirst()).toBe(false);
270 describe("isLast", function() {
271 beforeEach(function(){
272 insertDefaultChildren
.call(this);
275 it("should have rootNode which is last", function() {
276 expect(rootNode
.isLast()).toBe(true);
278 it("should have leftChild which is not last", function() {
279 expect(leftChild
.isLast()).toBe(false);
281 it("should have rightChild which is last", function() {
282 expect(rightChild
.isLast()).toBe(true);
286 describe("hasChildNodes", function() {
287 beforeEach(function() {
288 rootNode
.appendChild(leftChild
);
291 it("should have rootNode with children", function() {
292 expect(rootNode
.hasChildNodes()).toBe(true);
294 it("should have leftChild whithout children", function() {
295 expect(leftChild
.hasChildNodes()).toBe(false);
299 describe("isExpandable", function() {
300 it("should have node expandable if it has children", function() {
301 spareNode
.appendChild(leftChild
);
302 expect(spareNode
.isExpandable()).toBe(true);
305 it("should have node expandable if has no children", function() {
306 expect(spareNode
.isExpandable()).toBe(true);
308 it("should have node not expandable if it is a leaf node", function() {
309 spareNode
.set('leaf', true);
310 expect(spareNode
.isExpandable()).toBe(false);
314 describe("append", function(){
315 describe("appending children", function() {
317 it("should fire beforeappend", function() {
318 spy
= spyOnEvent(rootNode
, "beforeappend").andCallThrough();
320 rootNode
.appendChild(leftChild
);
322 expect(spy
).toHaveBeenCalledWith(rootNode
, leftChild
);
325 it("should cancel append if beforeappend return false", function() {
326 spy
= spyOnEvent(rootNode
, "beforeappend").andReturn(false);
327 expect(rootNode
.appendChild(leftChild
)).toBe(false);
329 expect(spy
.callCount
).toEqual(1);
332 it("should set firstChild", function() {
334 rootNode
.appendChild(leftChild
);
336 expect(rootNode
.firstChild
).toEqual(leftChild
);
339 it("should set lastChild", function() {
341 rootNode
.appendChild(leftChild
);
343 expect(rootNode
.lastChild
).toEqual(leftChild
);
346 it("should add node to childnodes", function() {
349 rootNode
.appendChild(leftChild
);
351 childNodes
= rootNode
.childNodes
;
353 expect(childNodes
.length
).toEqual(1);
354 expect(childNodes
[0]).toEqual(leftChild
);
357 it("should fire append event", function() {
358 spy
= spyOnEvent(rootNode
, "append").andCallThrough();
360 rootNode
.appendChild(leftChild
);
362 expect(spy
).toHaveBeenCalledWith(rootNode
, leftChild
, 0);
365 it("should return node", function() {
366 var ret
= rootNode
.appendChild(leftChild
);
368 expect(ret
).toEqual(leftChild
);
371 it("should append array of nodes", function() {
372 rootNode
.appendChild([leftChild
, rightChild
]);
374 var childNodes
= rootNode
.childNodes
;
376 expect(childNodes
[0]).toEqual(leftChild
);
377 expect(childNodes
[1]).toEqual(rightChild
);
378 expect(childNodes
.length
).toEqual(2);
382 describe("appending with existing siblings", function() {
383 beforeEach(function() {
384 insertDefaultChildren
.call(this);
387 it("should set next sibling", function() {
388 expect(leftChild
.nextSibling
).toEqual(rightChild
);
389 expect(rightChild
.nextSibling
).toBeNull();
392 it("should set previous sibling", function() {
393 expect(rightChild
.previousSibling
).toEqual(leftChild
);
394 expect(leftChild
.previousSibling
).toBeNull();
398 describe("appending children from an existing node", function() {
401 beforeEach(function() {
402 oldParent
= new spec
.TreeNode({id
: 'oldparent'});
403 oldParent
.appendChild(spareNode
);
406 it("should remove from existing node", function() {
407 spy
= spyOn(oldParent
, "removeChild").andCallThrough();
409 rootNode
.appendChild(spareNode
);
411 expect(spy
).toHaveBeenCalledWith(spareNode
, false, undefined, true);
414 it("should fire beforeremove event", function(){
415 spy
= spyOnEvent(oldParent
, "beforeremove").andCallThrough();
417 rootNode
.appendChild(spareNode
);
419 expect(spy
).toHaveBeenCalledWith(oldParent
, spareNode
, true);
422 it("should fire remove event", function(){
423 spy
= spyOnEvent(oldParent
, "remove").andCallThrough();
425 rootNode
.appendChild(spareNode
);
427 // Just use the context argumemt from the args as the last arg
428 expect(spy
).toHaveBeenCalledWith(oldParent
, spareNode
, true, spy
.mostRecentCall
.args
[3]);
431 it("should fire beforemove event", function() {
432 spy
= spyOnEvent(spareNode
, "beforemove").andCallThrough();
434 rootNode
.appendChild(spareNode
);
436 expect(spy
).toHaveBeenCalledWith(spareNode
, oldParent
, rootNode
, 0);
438 it("should fire move event", function() {
439 spy
= spyOnEvent(spareNode
, "move").andCallThrough();
441 rootNode
.appendChild(spareNode
);
443 expect(spy
).toHaveBeenCalledWith(spareNode
, oldParent
, rootNode
, 0);
448 describe("insert", function(){
450 beforeEach(function(){
451 rootNode
.appendChild(rightChild
);
454 describe("inserting children", function() {
455 it("should call appendChild if the node to insert before is null", function() {
456 spy
= spyOn(rootNode
, "appendChild");
458 rootNode
.insertBefore(leftChild
);
460 expect(spy
).toHaveBeenCalledWith(leftChild
);
463 it("should do nothing if the node to insert before is equal to the node to insert", function() {
464 expect(rootNode
.insertBefore(leftChild
, leftChild
)).toBe(false);
467 it("should fire beforeinsert", function() {
468 spy
= spyOnEvent(rootNode
, "beforeinsert").andCallThrough();
470 rootNode
.insertBefore(leftChild
, rightChild
);
472 expect(spy
).toHaveBeenCalledWith(rootNode
, leftChild
, rightChild
);
475 it("should cancel insert if beforeinsert return false", function() {
476 spy
= spyOnEvent(rootNode
, "beforeinsert").andReturn(false);
478 expect(rootNode
.insertBefore(leftChild
, rightChild
)).toBe(false);
480 expect(spy
.callCount
).toEqual(1);
483 it("should set firstChild", function() {
484 rootNode
.insertBefore(leftChild
, rightChild
);
486 expect(rootNode
.firstChild
).toEqual(leftChild
);
489 it("should set lastChild", function() {
490 rootNode
.insertBefore(leftChild
, rightChild
);
492 expect(rootNode
.lastChild
).toEqual(rightChild
);
495 it("should fire insert", function() {
496 spy
= spyOnEvent(rootNode
, "insert").andCallThrough();
498 rootNode
.insertBefore(leftChild
, rightChild
);
500 expect(spy
).toHaveBeenCalledWith(rootNode
, leftChild
, rightChild
);
503 it("should update indexes for all siblings after the position where the node was inserted", function() {
504 rootNode
.insertBefore(spareNode
, rightChild
);
506 rootNode
.insertBefore(leftChild
, spareNode
);
508 expect(spareNode
.get('index')).toEqual(1);
509 expect(rightChild
.get('index')).toEqual(2);
513 it("should handle siblings", function(){
514 expect(leftChild
.previousSibling
).toBeNull();
515 expect(leftChild
.nextSibling
).toBeNull();
516 expect(rightChild
.previousSibling
).toBeNull();
517 expect(rightChild
.nextSibling
).toBeNull();
519 rootNode
.insertBefore(leftChild
, rightChild
);
521 expect(leftChild
.previousSibling
).toBeNull();
522 expect(leftChild
.nextSibling
).toEqual(rightChild
);
523 expect(rightChild
.previousSibling
).toEqual(leftChild
);
524 expect(rightChild
.nextSibling
).toBeNull();
527 describe("move", function() {
528 beforeEach(function() {
529 rootNode
.appendChild(leftChild
);
532 it("should fire beforemove", function() {
533 spy
= spyOnEvent(leftChild
, "beforemove").andCallThrough();
535 rootNode
.insertBefore(leftChild
, rightChild
);
537 expect(spy
).toHaveBeenCalledWith(leftChild
, rootNode
, rootNode
, 0, rightChild
);
540 it("should cancel insert if beforemove return false", function() {
541 spy
= spyOnEvent(leftChild
, "beforemove").andReturn(false);
543 expect(rootNode
.insertBefore(leftChild
, rightChild
)).toBe(false);
545 expect(spy
.callCount
).toEqual(1);
548 it("should fire move", function() {
549 spy
= spyOnEvent(leftChild
, "move").andCallThrough();
551 rootNode
.insertBefore(leftChild
, rightChild
);
553 expect(spy
).toHaveBeenCalledWith(leftChild
, rootNode
, rootNode
, 0, rightChild
);
560 describe("removing children", function() {
561 it("should return false when removing bad node", function(){
562 expect(rootNode
.removeChild(leftChild
)).toBe(false);
565 it("should fire beforeremove event", function(){
566 insertDefaultChildren
.call(this);
568 spy
= spyOnEvent(rootNode
, "beforeremove").andCallThrough();
570 rootNode
.removeChild(leftChild
);
572 expect(spy
).toHaveBeenCalledWith(rootNode
, leftChild
, false);
575 it("should cancel remove if beforeremove returns false", function() {
576 insertDefaultChildren
.call(this);
578 spy
= spyOnEvent(rootNode
, "beforeremove").andReturn(false);
580 expect(rootNode
.removeChild(leftChild
)).toBe(false);
582 expect(spy
.callCount
).toEqual(1);
585 it("should fire remove event", function() {
586 insertDefaultChildren
.call(this);
588 spy
= spyOnEvent(rootNode
, "remove").andCallThrough();
590 rootNode
.removeChild(leftChild
);
592 // Just use the context argumemt from the args as the last arg
593 expect(spy
).toHaveBeenCalledWith(rootNode
, leftChild
, false, spy
.mostRecentCall
.args
[3]);
596 it("should remove child from childNodes", function() {
597 var childNodes
, count
;
599 insertDefaultChildren
.call(this);
601 childNodes
= rootNode
.childNodes
;
602 count
= childNodes
.length
;
604 rootNode
.removeChild(leftChild
);
606 expect(childNodes
.length
).toEqual(count
- 1);
607 expect(childNodes
[0]).toEqual(rightChild
);
610 it("should manage siblings", function() {
611 insertDefaultChildren
.call(this);
613 //this gives us a third child - 'right' is actually now center
614 rootNode
.appendChild(spareNode
);
616 rootNode
.removeChild(rightChild
);
618 expect(leftChild
.nextSibling
, spareNode
);
620 expect(spareNode
.previousSibling
, leftChild
);
623 it("should erase node if asked", function() {
624 insertDefaultChildren
.call(this);
626 spy
= spyOn(leftChild
, "erase").andCallThrough();
628 rootNode
.removeChild(leftChild
, true);
630 expect(spy
).toHaveBeenCalled();
633 it("should clear node if asked", function() {
634 insertDefaultChildren
.call(this);
636 spy
= spyOn(leftChild
, "clear").andCallThrough();
638 rootNode
.removeChild(leftChild
, false);
640 expect(spy
).toHaveBeenCalled();
642 it("should update indexes for all siblings after the node's old position", function() {
643 insertDefaultChildren
.call(this);
645 rootNode
.appendChild(spareNode
);
647 rootNode
.removeChild(leftChild
);
649 expect(rightChild
.get('index')).toEqual(0);
650 expect(spareNode
.get('index')).toEqual(1);
654 describe("clearing references", function() {
655 beforeEach(function(){
656 insertDefaultChildren
.call(this);
657 rootNode
.appendChild(spareNode
);
660 it("should nullify parentNode", function() {
661 expect(rightChild
.parentNode
).not
.toBeNull();
665 expect(rightChild
.parentNode
).toBeNull();
668 it("should nullifies nextSibling", function() {
669 expect(rightChild
.nextSibling
).not
.toBeNull();
673 expect(rightChild
.nextSibling
).toBeNull();
676 it("should nullifies previousSibling", function() {
677 expect(rightChild
.previousSibling
).not
.toBeNull();
681 expect(rightChild
.previousSibling
).toBeNull();
684 it("should remove lastChild and firstChild references", function() {
685 rightChild
.clear(true);
687 expect(rightChild
.firstChild
).toBeNull();
688 expect(rightChild
.lastChild
).toBeNull();
692 describe("item", function() {
693 it("should return the child node at the specified index", function() {
694 rootNode
.appendChild(leftChild
);
695 rootNode
.appendChild(rightChild
);
696 rootNode
.appendChild(spareNode
);
698 expect(rootNode
.getChildAt(0)).toEqual(leftChild
);
699 expect(rootNode
.getChildAt(1)).toEqual(rightChild
);
700 expect(rootNode
.getChildAt(2)).toEqual(spareNode
);
704 describe("silent destroy", function() {
705 it("should purge node listeners", function() {
706 spy
= spyOn(leftChild
.mixins
.observable
, "clearListeners").andCallThrough();
708 leftChild
.destroy(true);
710 expect(spy
).toHaveBeenCalled();
713 it("should erase children", function() {
716 insertDefaultChildren
.call(this);
718 spy
= spyOn(leftChild
, "erase").andCallThrough();
719 spy2
= spyOn(rightChild
, "erase").andCallThrough();
723 expect(spy
).toHaveBeenCalled();
724 expect(spy2
).toHaveBeenCalled();
727 it("should nullify childNodes", function() {
728 insertDefaultChildren
.call(this);
730 expect(rootNode
.childNodes
).not
.toBeNull();
732 rootNode
.erase(true);
734 expect(rootNode
.childNodes
).toBeNull();
738 describe("non-silent destroy", function() {
739 it("should remove node", function() {
740 insertDefaultChildren
.call(this);
742 spy
= spyOn(leftChild
, "remove").andCallThrough();
744 leftChild
.erase(false);
746 expect(spy
).toHaveBeenCalled();
750 describe("remove", function() {
751 it("should remove from parent", function() {
752 spy
= spyOn(rootNode
, "removeChild").andCallThrough();
754 rootNode
.appendChild(leftChild
);
758 expect(spy
).toHaveBeenCalledWith(leftChild
, undefined, undefined);
761 it("should return node", function() {
762 expect(leftChild
.remove()).toEqual(leftChild
);
766 describe("removeAll", function() {
767 it("should remove all children", function() {
768 rootNode
.appendChild([leftChild
, rightChild
, spareNode
]);
769 rootNode
.removeAll();
770 expect(rootNode
.childNodes
.length
).toBe(0);
774 describe("replacing children", function() {
775 beforeEach(function() {
776 insertDefaultChildren
.call(this);
779 it("should keep the same childNodes length", function() {
780 var count
= rootNode
.childNodes
.length
;
782 rootNode
.replaceChild(spareNode
, leftChild
);
784 expect(rootNode
.childNodes
.length
).toEqual(count
);
787 it("should replace node", function() {
788 rootNode
.replaceChild(spareNode
, leftChild
);
790 expect(rootNode
.childNodes
[0], spareNode
);
794 describe("getting depth", function() {
795 beforeEach(function() {
796 insertDefaultChildren
.call(this);
797 leftChild
.appendChild(spareNode
);
800 it("should have a depth of 0 for rootNode", function(){
801 expect(rootNode
.getDepth()).toEqual(0);
804 it("should have a depth of 1 for leftChild and rightChild", function(){
805 expect(rightChild
.getDepth()).toEqual(1);
806 expect(leftChild
.getDepth()).toEqual(1);
809 it("should have a depth of 2 for spareNode", function(){
810 expect(spareNode
.getDepth()).toEqual(2);
814 describe("getting path", function() {
815 beforeEach(function() {
816 insertDefaultChildren
.call(this);
817 leftChild
.appendChild(spareNode
);
820 it("should set root path", function() {
821 expect(rootNode
.getPath()).toEqual("/root");
824 it("should set middle path", function() {
825 expect(leftChild
.getPath()).toEqual("/root/left");
826 expect(rightChild
.getPath()).toEqual("/root/right");
829 it("should set leaf path", function() {
830 expect(spareNode
.getPath()).toEqual("/root/left/spare");
834 describe("indexOf", function(){
835 it("should always return -1 when the node is empty", function(){
836 expect(rootNode
.indexOf(spareNode
)).toBe(-1);
839 it("should return -1 when the passed node is not a child", function(){
840 rootNode
.appendChild(leftChild
);
841 expect(rootNode
.indexOf(spareNode
)).toBe(-1);
844 it("should return the correct index when the node exists", function(){
845 rootNode
.appendChild([leftChild
, spareNode
, rightChild
]);
846 expect(rootNode
.indexOf(spareNode
)).toBe(1);
850 describe("indexOfId", function(){
851 it("should always return -1 when the node is empty", function(){
852 expect(rootNode
.indexOfId('spare')).toBe(-1);
855 it("should return -1 when the passed node is not a child", function(){
856 rootNode
.appendChild(leftChild
);
857 expect(rootNode
.indexOfId('spare')).toBe(-1);
860 it("should return the correct index when the node exists", function(){
861 rootNode
.appendChild([leftChild
, spareNode
, rightChild
]);
862 expect(rootNode
.indexOfId('spare')).toBe(1);
866 describe("bubbling", function() {
869 beforeEach(function() {
870 insertDefaultChildren
.call(this);
871 leftChild
.appendChild(spareNode
);
872 bubbleFn
= jasmine
.createSpy();
875 it("should call bubbleFn 3 times", function() {
876 spareNode
.bubble(bubbleFn
);
878 expect(bubbleFn
.callCount
).toEqual(3);
881 it("should call bubbleFn with node spare, left, root", function() {
882 spareNode
.bubble(bubbleFn
);
884 expect(bubbleFn
.calls
[0].args
).toEqual([spareNode
]);
885 expect(bubbleFn
.calls
[1].args
).toEqual([leftChild
]);
886 expect(bubbleFn
.calls
[2].args
).toEqual([rootNode
]);
889 it("should call bubbleFn with a defined scope", function() {
890 spareNode
.bubble(bubbleFn
, fakeScope
);
892 expect(bubbleFn
.calls
[0].object
).toBe(fakeScope
);
893 expect(bubbleFn
.calls
[1].object
).toBe(fakeScope
);
894 expect(bubbleFn
.calls
[2].object
).toBe(fakeScope
);
897 it("should call bubbleFn with customs arguments", function() {
898 var customArgs
= ['some', 'args'];
900 spareNode
.bubble(bubbleFn
, spareNode
, customArgs
);
902 expect(bubbleFn
.calls
[0].args
).toEqual(customArgs
);
903 expect(bubbleFn
.calls
[1].args
).toEqual(customArgs
);
904 expect(bubbleFn
.calls
[2].args
).toEqual(customArgs
);
907 it("should stop when bubbleFn return false", function() {
908 bubbleFn
.andCallFake(function(node
) {
909 if (node
.getId() == 'left') {
914 spareNode
.bubble(bubbleFn
);
916 expect(bubbleFn
.callCount
).toEqual(2);
920 describe("cascading", function() {
923 beforeEach(function(){
924 insertDefaultChildren
.call(this);
925 leftChild
.appendChild(spareNode
);
926 cascadeFn
= jasmine
.createSpy();
929 it("should call cascadeFn 4 times", function() {
930 rootNode
.cascadeBy(cascadeFn
);
932 expect(cascadeFn
.callCount
).toEqual(4);
935 it("should call cascadeFn with node root, leftChild, spareNode, rightChild", function() {
936 rootNode
.cascadeBy(cascadeFn
);
938 expect(cascadeFn
.calls
[0].args
).toEqual([rootNode
]);
939 expect(cascadeFn
.calls
[1].args
).toEqual([leftChild
]);
940 expect(cascadeFn
.calls
[2].args
).toEqual([spareNode
]);
941 expect(cascadeFn
.calls
[3].args
).toEqual([rightChild
]);
944 it("should call cascadeFn with a defined scope", function() {
945 rootNode
.cascadeBy(cascadeFn
, fakeScope
);
947 expect(cascadeFn
.calls
[0].object
).toBe(fakeScope
);
948 expect(cascadeFn
.calls
[1].object
).toBe(fakeScope
);
949 expect(cascadeFn
.calls
[2].object
).toBe(fakeScope
);
950 expect(cascadeFn
.calls
[3].object
).toBe(fakeScope
);
953 it("should call cascadeFn with customs arguments", function() {
954 var customArgs
= ['some', 'args'];
956 rootNode
.cascadeBy(cascadeFn
, rootNode
, customArgs
);
958 expect(cascadeFn
.calls
[0].args
).toEqual(customArgs
);
959 expect(cascadeFn
.calls
[1].args
).toEqual(customArgs
);
960 expect(cascadeFn
.calls
[2].args
).toEqual(customArgs
);
961 expect(cascadeFn
.calls
[3].args
).toEqual(customArgs
);
964 it("should stop at end of branch when cascadeFn return false", function() {
965 cascadeFn
.andCallFake(function(node
) {
966 if (node
.getId() == 'left') {
971 rootNode
.cascadeBy(cascadeFn
);
973 expect(cascadeFn
.callCount
).toEqual(3);
977 describe("each child", function() {
980 beforeEach(function (){
981 insertDefaultChildren
.call(this);
982 eachFn
= jasmine
.createSpy();
985 it("should be called 2 times", function() {
987 rootNode
.eachChild(eachFn
);
989 expect(eachFn
.callCount
).toEqual(2);
992 it("should call eachFn with node root, leftChild, rightChild", function() {
993 rootNode
.eachChild(eachFn
);
995 expect(eachFn
.calls
[0].args
).toEqual([leftChild
]);
996 expect(eachFn
.calls
[1].args
).toEqual([rightChild
]);
999 it("should call eachFn with a defined scope", function() {
1000 rootNode
.eachChild(eachFn
, fakeScope
);
1002 expect(eachFn
.calls
[0].object
).toBe(fakeScope
);
1003 expect(eachFn
.calls
[1].object
).toBe(fakeScope
);
1006 it("should call eachFn with customs arguments", function() {
1007 var customArgs
= ['some', 'args'];
1009 rootNode
.eachChild(eachFn
, rootNode
, customArgs
);
1011 expect(eachFn
.calls
[0].args
).toEqual(customArgs
);
1012 expect(eachFn
.calls
[1].args
).toEqual(customArgs
);
1015 it("should stop when eachFn return false", function() {
1016 eachFn
.andCallFake(function(node
) {
1017 if (node
.getId() == 'left') {
1022 rootNode
.eachChild(eachFn
);
1024 expect(eachFn
.callCount
).toEqual(1);
1028 describe("ancestors", function() {
1029 beforeEach(function (){
1030 insertDefaultChildren
.call(this);
1031 leftChild
.appendChild(spareNode
);
1034 it("should have parent as ancestor", function() {
1035 expect(spareNode
.isAncestor(leftChild
)).toBe(true);
1038 it("should have root as ancestor", function() {
1039 expect(spareNode
.isAncestor(rootNode
)).toBe(true);
1042 it("should not have uncle as ancestor", function() {
1043 expect(spareNode
.isAncestor(rightChild
)).toBe(false);
1047 describe("contains", function() {
1048 beforeEach(function (){
1049 insertDefaultChildren
.call(this);
1050 leftChild
.appendChild(spareNode
);
1053 it("should contain child", function() {
1054 expect(rootNode
.contains(leftChild
)).toBe(true);
1057 it("should contain grand child", function() {
1058 expect(rootNode
.contains(spareNode
)).toBe(true);
1061 it("should not contain parent", function() {
1062 expect(spareNode
.contains(leftChild
)).toBe(false);
1066 describe("finding children", function() {
1067 beforeEach(function (){
1068 insertDefaultChildren
.call(this);
1069 leftChild
.appendChild(spareNode
);
1072 describe("findChild", function() {
1073 it("should find shallow children", function() {
1074 expect(rootNode
.findChild('id', 'left')).toEqual(leftChild
);
1077 it("should not find deep children if deep is not specified", function() {
1078 expect(rootNode
.findChild('id', 'spare')).toBeNull();
1081 it("should not find deep children if deep is false", function() {
1082 expect(rootNode
.findChild('id', 'spare', false)).toBeNull();
1085 it("should find deep children if deep is true", function() {
1086 expect(rootNode
.findChild('id', 'spare', true)).toEqual(spareNode
);
1090 describe("findChildBy", function() {
1093 it("should find shallow children", function(){
1094 child
= rootNode
.findChildBy(function(node
) {
1095 return node
.getId() == 'right';
1098 expect(child
).toEqual(rightChild
);
1101 it("should not find deep children if deep is not specified", function(){
1102 child
= rootNode
.findChildBy(function(node
) {
1103 return node
.getId() == 'spare';
1106 expect(child
).toBeNull();
1109 it("should not find deep children if deep is false", function(){
1110 child
= rootNode
.findChildBy(function(node
) {
1111 return node
.getId() == 'spare';
1114 expect(child
).toBeNull();
1117 it("should find deep children if deep is true", function(){
1118 child
= rootNode
.findChildBy(function(node
) {
1119 return node
.getId() == 'spare';
1122 expect(child
).toEqual(spareNode
);
1125 it("should call function with good scope", function(){
1126 var findChildFn
= jasmine
.createSpy().andReturn(false);
1128 child
= rootNode
.findChildBy(findChildFn
, fakeScope
, true);
1130 expect(findChildFn
.calls
[0].object
).toBe(fakeScope
);
1131 expect(findChildFn
.calls
[1].object
).toBe(fakeScope
);
1132 expect(findChildFn
.calls
[2].object
).toBe(fakeScope
);
1137 describe("sort", function() {
1144 beforeEach(function() {
1145 Ext
.define('spec.EmployeeTreeNode', {
1146 extend
: 'Ext.data.Model',
1148 { name
: 'lastname', type
: 'string' },
1149 { name
: 'firstname', type
: 'string' }
1152 Ext
.data
.NodeInterface
.decorate(spec
.EmployeeTreeNode
);
1153 node1
= new spec
.EmployeeTreeNode({lastname
: "Avins", firstname
: "Jamie"});
1154 node2
= new spec
.EmployeeTreeNode({lastname
: "Dougan", firstname
: "Robert"});
1155 node3
= new spec
.EmployeeTreeNode({lastname
: "Ferrero", firstname
: "Nicolas"});
1156 node4
= new spec
.EmployeeTreeNode({lastname
: "Spencer", firstname
: "Edward"});
1158 rootNode
.appendChild([node4
, node2
, node3
, node1
]);
1160 sortFn
= jasmine
.createSpy();
1161 sortFn
.andCallFake(function(a
, b
){
1162 if (a
.get('lastname') === b
.get('lastname')) {
1165 return (a
.get('lastname') < b
.get('lastname')) ? -1 : 1;
1168 rootNode
.sort(sortFn
);
1170 afterEach(function() {
1171 Ext
.undefine('spec.EmployeeTreeNode');
1174 it("should sort the child by lastname with the correct function", function() {
1175 expect(rootNode
.childNodes
[0]).toEqual(node1
);
1176 expect(rootNode
.childNodes
[1]).toEqual(node2
);
1177 expect(rootNode
.childNodes
[2]).toEqual(node3
);
1178 expect(rootNode
.childNodes
[3]).toEqual(node4
);
1183 describe("copy", function(){
1184 it("should not copy childNodes by default", function(){
1185 var node
= new spec
.TreeNode({
1190 var newNode
= node
.copy();
1192 expect(newNode
.getData()).toEqual({
1222 it("should accept a new id", function(){
1223 var node
= new spec
.TreeNode({
1228 var newNode
= node
.copy(2);
1230 expect(newNode
.getData()).toEqual({
1260 it("should clone children if deep: true is specified", function(){
1261 var root
= new spec
.TreeNode({
1265 var child1
= root
.appendChild(new spec
.TreeNode({
1269 var child2
= child1
.appendChild(new spec
.TreeNode({
1273 child2
.appendChild(new spec
.TreeNode({
1278 var newNode
= root
.copy(undefined, true);
1279 expect(newNode
.childNodes
[0].getId()).toBe(2);
1280 expect(newNode
.childNodes
[0].get('text')).toBe('Child1');
1282 newNode
= newNode
.childNodes
[0];
1283 expect(newNode
.childNodes
[0].getId()).toBe(3);
1284 expect(newNode
.childNodes
[0].get('text')).toBe('Child2');
1286 newNode
= newNode
.childNodes
[0];
1287 expect(newNode
.childNodes
[0].getId()).toBe(4);
1288 expect(newNode
.childNodes
[0].get('text')).toBe('Child3');
1294 describe("serialize", function(){
1295 it('should create an object representation of the node', function() {
1296 var node
= new spec
.TreeNode({
1300 c1
= node
.appendChild(new spec
.TreeNode({
1304 c2
= node
.appendChild(new spec
.TreeNode({
1308 c1
.appendChild( new spec
.TreeNode({
1312 c2
.appendChild( new spec
.TreeNode({
1317 expect(node
.serialize()).toEqual({
1355 it("should not include children if there are none", function(){
1356 var o
= new spec
.TreeNode({
1358 }), s
= o
.serialize();
1360 expect(s
.text
).toBe('foo');
1361 expect(s
.children
).toBeUndefined();
1364 it("should include children if they exist", function(){
1365 var o
= new spec
.TreeNode({
1369 o
.appendChild(new spec
.TreeNode({
1374 expect(s
.text
).toBe('foo');
1375 expect(s
.children
[0].text
).toBe('bar');
1379 describe("collapse", function() {
1380 it("should fire the collapse callback when there are no child nodes", function() {
1381 var root
= new spec
.TreeNode(),
1384 root
.collapseChildren(false, function() {
1387 expect(called
).toBe(true);
1392 describe("modified property tracking", function() {
1393 // Tests for https://sencha.jira.com/browse/EXTJSIV-9223 and https://sencha.jira.com/browse/EXTJSIV-9165
1394 it("should track modifications of fields set as a result of node movement", function() {
1396 // Create a TreeNode subclass in which the index property is persistent.
1397 Ext
.define('spec.PersistentIndexTreeNode', {
1398 extend
: 'Ext.data.TreeModel',
1400 {name
: 'text', type
: 'string'},
1401 {name
: 'index', type
: 'int', persist
: true, defaultValue
: -1}
1408 var root
= new spec
.PersistentIndexTreeNode({
1411 root1
= new spec
.PersistentIndexTreeNode({
1414 node
= new spec
.PersistentIndexTreeNode({
1418 root
.appendChild(node
);
1420 // The modified shows that parentId was changed *from* null.
1421 // And the index was changed from -1 (not attached) to 0
1422 expect(node
.modified
).toEqual({
1429 expect(node
.modified
).toBeNull();
1431 // Move from parent "TestRoot", index 0 to parent "OtherTestRoot", index 0
1432 // Index should appear in modified object because it has moved parent
1433 root1
.appendChild(node
);
1434 expect(node
.modified
).toEqual({
1435 parentId
: 'TestRoot',
1442 // Should clear the parentId, so the modified now indicates that it was removed from index 0 of "OtherTestRoot"
1443 // removeChild does NOT clear context data properties.
1444 // Mainly because TreeStore.clearRemovedOnLoad uses these values to determine whether
1445 // nodes in the removed list are descendants of a loading node so that tey can be evicted from the removed list.
1446 root1
.removeChild(node
);
1447 expect(node
.modified
).toEqual({
1448 lastParentId
: undefined,
1449 parentId
: 'OtherTestRoot'
1452 node
= new spec
.PersistentIndexTreeNode({
1455 node1
= new spec
.PersistentIndexTreeNode({
1459 root
.appendChild([node
, node1
]);
1461 expect([node
.get('index'), node1
.get('index')]).toEqual([0, 1]);
1465 // Move node1 to index:0
1466 root
.insertBefore(node1
, node
);
1468 // Indexes data values are switched
1469 expect([node1
.get('index'), node
.get('index')]).toEqual([0, 1]);
1471 // node1 must report that its index was modified from initial value 1
1472 expect(node1
.modified
).toEqual({
1476 // node must report that its index was modified from initial value 0
1477 expect(node
.modified
).toEqual({
1481 root1
.appendChild(node1
);
1483 Ext
.undefine('spec.PersistentIndexTreeNode');