UNPKG

extjs-gpl

Version:

GPL licensed version of Sencha Ext JS

1,404 lines (1,268 loc) 186 kB
/* global Ext, spyOn, expect, MockAjaxManager, jasmine */ describe("Ext.data.TreeStore", function() { var store, root, loadStore, dummyData, NodeModel = Ext.define(null, { extend: 'Ext.data.TreeModel', fields: ['name'], proxy: { type: 'ajax', url: 'foo.json', reader: { type: 'json' } } }), TaskModel = Ext.define(null, { extend: 'Ext.data.TreeModel', idProperty : 'id', fields: [ {name: 'id', type: 'int', allowNull: true}, {name: 'task', type: 'string'}, {name: 'duration', type: 'string'} ] }); function spyOnEvent(object, eventName, fn) { var obj = { fn: fn || Ext.emptyFn }, spy = spyOn(obj, "fn"); object.addListener(eventName, obj.fn); return spy; } function expandify(nodes) { if (Ext.isNumber(nodes[0])) { nodes = Ext.Array.map(nodes, function(id) { return { id: id, leaf: true }; }); } Ext.Array.forEach(nodes, function(node) { if (node.children || node.leaf === false) { node.expanded = true; if (node.children) { node.children = expandify(node.children); } else { node.children = []; } } else { node.leaf = true; } }); return nodes; } function makeStore(nodes, cfg) { store = new Ext.data.TreeStore(Ext.apply({ asynchronousLoad: false, root: { expanded: true, children: expandify(nodes) } }, cfg)); root = store.getRootNode(); } function expectOrder(parent, ids) { var childNodes = parent.childNodes, i, len; expect((childNodes || []).length).toBe(ids.length); if (childNodes) { for (i = 0, len = childNodes.length; i < len; ++i) { expect(childNodes[i].id).toBe(ids[i]); } } } beforeEach(function() { dummyData = { success: true, children: [{ id: 1, name: "aaa" },{ id: 2, name: "bbb", children: [{ id: 3, name: "ccc" },{ id: 4, name: "ddd", children: [{ id: 5, name: "eee", leaf: true }] }] },{ id: 6, name: "fff", children: [{id: 7, name: "ggg" }] }] }; MockAjaxManager.addMethods(); loadStore = function(store, options) { store.load(options); completeWithData(dummyData); }; }); afterEach(function() { store = Ext.destroy(store); MockAjaxManager.removeMethods(); }); function completeWithData(data) { Ext.Ajax.mockComplete({ status: 200, responseText: Ext.encode(data) }); } function completeWithFailure() { Ext.Ajax.mockComplete({ status: 200, responseText: Ext.encode({ success: false }) }); } function byId(id) { return store.getNodeById(id); } describe('NodeInterface#removeAll', function() { // Test https://sencha.jira.com/browse/EXTJS-20023 it('should remove all descendant nodes from node lookup map', function() { store = new Ext.data.TreeStore({ model: NodeModel, proxy: { type: 'memory' }, root: { id: 0, name: 'Root Node', autoLoad: true, children: dummyData.children } }); store.getRootNode().expand(true); expect(Ext.Object.getKeys(store.byIdMap).length).toBe(8); store.getRootNode().removeAll(); // All descendant nodes must have gone from the node map. // Only the root must remain. expect(Ext.Object.getKeys(store.byIdMap).length).toBe(1); expect(Ext.Object.getValues(store.byIdMap)[0]).toBe(store.getRootNode()); // All removed records should be represented in the removed records list. expect(store.getRemovedRecords().length).toBe(7); }); }); describe('reload of a TreeStore after a node load', function() { it('should pass the root\'s id', function() { var lastLoadedId; store = new Ext.data.TreeStore({ model: NodeModel, asynchronousLoad: false, root: { expanded: true, id: 'root-id' }, listeners: { beforeload: function(store, operation) { lastLoadedId = operation.getId(); } } }); expect(lastLoadedId).toBe('root-id'); completeWithData([{ id: '1', name: 'Node 1' }, { id: '2', name: 'Node 2' }]); store.getNodeById(1).expand(); // Expanding node id 1 will put id:'1' in the operation expect(lastLoadedId).toBe('1'); completeWithData([{ id: '1.1', name: 'Node 1.1' }, { id: '1.2', name: 'Node 1.2' }]); store.reload(); // Reloading will put id:'root-id' in the operation expect(lastLoadedId).toBe('root-id'); }); }); describe('Aqcuiring a Proxy', function() { it("should use the configured Model's Proxy by default", function() { var usedProxy; store = new Ext.data.TreeStore({ model: NodeModel, listeners: { beforeload: function(store, operation) { usedProxy = operation.getProxy(); return false; } } }); store.load(); // The store should use the proxy from the model expect(store.getProxy()).toBe(NodeModel.getProxy()); expect(usedProxy).toBe(NodeModel.getProxy()); }); it("should use its own Proxy Proxy if it is configured with one", function() { var storeProxy = new Ext.data.proxy.Ajax({ url: '/foo' }), usedProxy; store = new Ext.data.TreeStore({ model: NodeModel, proxy: storeProxy, listeners: { beforeload: function(store, operation) { usedProxy = operation.getProxy(); return false; } } }); store.load(); // The store should use the proxy it was configured with. expect(store.getProxy()).toBe(storeProxy); expect(usedProxy).toBe(storeProxy); }); }); describe('success: false in return packet', function() { // Set to bug condition to ensure event fires as expected. var wasSuccessful = true; it("should fire the load event with the success parameter false", function() { store = new Ext.data.TreeStore({ model: NodeModel, root: { expanded: true }, listeners: { load: function(store, records, successful, operation, node) { wasSuccessful = successful; } } }); completeWithFailure(); expect(wasSuccessful).toBe(false); }); }); describe("the model", function() { it("should be able to use a non TreeModel", function() { var Model = Ext.define(null, { extend: 'Ext.data.Model', fields: ['foo'] }); // Important that the proxy gets applied first here store = new Ext.data.TreeStore({ proxy: { type: 'ajax', url: 'fake' }, model: Model }); expect(store.getModel()).toBe(Model); expect(Model.prototype.isNode).toBe(true); }); describe("using an implicit model", function() { it("should use the model's memory proxy when no proxy is defined on the store", function() { store = new Ext.data.TreeStore({ fields: ['id', 'height', 'width'] }); expect(store.getProxy().isMemoryProxy).toBe(true); expect(store.getProxy()).toBe(store.getModel().getProxy()); }); it("should set the store's proxy on the model", function() { store = new Ext.data.TreeStore({ fields: ['id', 'height', 'width'], proxy: { type: 'ajax', url: 'foo' } }); expect(store.getProxy().isAjaxProxy).toBe(true); expect(store.getProxy().url).toBe('foo'); expect(store.getProxy()).toBe(store.getModel().getProxy()); }); it("should have the model set on the proxy & the reader", function() { store = new Ext.data.TreeStore({ fields: ['id', 'height', 'width'], proxy: { type: 'ajax', url: 'foo' } }); expect(store.getProxy().getModel()).toBe(store.getModel()); expect(store.getProxy().getReader().getModel()).toBe(store.getModel()); }); it("should extend Ext.data.Model", function() { store = new Ext.data.TreeStore({ fields: ['id', 'height', 'width'] }); expect(store.getModel().superclass.self).toBe(Ext.data.TreeModel); }); }); }); describe("sorting", function() { function expectStoreOrder(ids) { var len = ids.length, i; expect(store.getCount()).toBe(len); for (i = 0; i < len; ++i) { expect(store.getAt(i).id).toBe(ids[i]); } } describe("with local data", function() { describe("with folderSort: true", function() { it("should sort when setting folderSort dynamically", function() { store = new Ext.data.TreeStore({ model: NodeModel, root: { expanded: true, children: [{ id: 'l1', leaf: true }, { id: 'f1' }, { id: 'l2', leaf: true }, { id: 'f2' }] } }); store.setFolderSort(true); expectOrder(store.getRoot(), ['f1', 'f2', 'l1', 'l2']); }); it("should leave the original sort order if there are no other sorters", function() { store = new Ext.data.TreeStore({ model: NodeModel, folderSort: true, root: { expanded: true, children: [{ id: 'l3', leaf: true }, { id: 'l2', leaf: true }, { id: 'f3' }, { id: 'l1', leaf: true }, { id: 'f2' }, { id: 'f1' }] } }); expectOrder(store.getRoot(), ['f3', 'f2', 'f1', 'l3', 'l2', 'l1']); }); it("should do a deep sort", function() { store = new Ext.data.TreeStore({ model: NodeModel, folderSort: true, root: { expanded: true, children: [{ id: 'p1', children: [{ id: 'l1', leaf: true }, { id: 'f1' }] }, { id: 'p2', children: [{ id: 'l2', leaf: true }, { id: 'f2' }] }] } }); expectOrder(byId('p1'), ['f1', 'l1']); expectOrder(byId('p2'), ['f2', 'l2']); }); it("should sort folder/non folder groups by any additional sorters", function() { store = new Ext.data.TreeStore({ model: NodeModel, folderSort: true, sorters: ['id'], root: { expanded: true, children: [{ id: 'f4' }, { id: 'l3' }, { id: 'f1' }, { id: 'l1' }, { id: 'l2' }, { id: 'f3' }, { id: 'l4' }, { id: 'f2' }] } }); expectOrder(store.getRoot(), ['f1', 'f2', 'f3', 'f4', 'l1', 'l2', 'l3', 'l4']); }); }); describe("with folderSort: false", function() { it("should sort by existing sorters when setting folderSort: false", function() { store = new Ext.data.TreeStore({ model: NodeModel, folderSort: false, sorters: ['id'], root: { expanded: true, children: [{ id: 'a', leaf: true }, { id: 'b' }, { id: 'c', leaf: true }, { id: 'd' }] } }); store.setFolderSort(false); expectOrder(store.getRoot(), ['a', 'b', 'c', 'd']); }); it("should do a deep sort", function() { store = new Ext.data.TreeStore({ model: NodeModel, folderSort: false, sorters: ['id'], root: { expanded: true, children: [{ id: 'p1', expanded: true, children: [{ id: 'b', leaf: true }, { id: 'c', leaf: true }, { id: 'a', leaf: true }, { id: 'd', leaf: true }] }, { id: 'p2', expanded: true, children: [{ id: 'g', leaf: true }, { id: 'e', leaf: true }, { id: 'h', leaf: true }, { id: 'f', leaf: true }] }] } }); store.setFolderSort(false); expectOrder(byId('p1'), ['a', 'b', 'c', 'd']); expectOrder(byId('p2'), ['e', 'f', 'g', 'h']); }); }); }); describe("with remote data", function() { describe("with folderSort: true", function() { it("should sort when setting folderSort dynamically", function() { store = new Ext.data.TreeStore({ model: NodeModel, root: { expanded: true } }); completeWithData([{ id: 'l1', leaf: true }, { id: 'f1' }, { id: 'l2', leaf: true }, { id: 'f2' }]); store.setFolderSort(true); expectOrder(store.getRoot(), ['f1', 'f2', 'l1', 'l2']); }); it("should leave the original sort order if there are no other sorters", function() { store = new Ext.data.TreeStore({ model: NodeModel, folderSort: true, root: { expanded: true } }); completeWithData([{ id: 'l3', leaf: true }, { id: 'l2', leaf: true }, { id: 'f3' }, { id: 'l1', leaf: true }, { id: 'f2' }, { id: 'f1' }]); expectOrder(store.getRoot(), ['f3', 'f2', 'f1', 'l3', 'l2', 'l1']); }); it("should do a deep sort", function() { store = new Ext.data.TreeStore({ model: NodeModel, folderSort: true, root: { expanded: true } }); completeWithData([{ id: 'p1', children: [{ id: 'l1', leaf: true }, { id: 'f1' }] }, { id: 'p2', children: [{ id: 'l2', leaf: true }, { id: 'f2' }] }]); expectOrder(byId('p1'), ['f1', 'l1']); expectOrder(byId('p2'), ['f2', 'l2']); }); it("should sort folder/non folder groups by any additional sorters", function() { store = new Ext.data.TreeStore({ model: NodeModel, folderSort: true, sorters: ['id'], root: { expanded: true } }); completeWithData([{ id: 'f4' }, { id: 'l3' }, { id: 'f1' }, { id: 'l1' }, { id: 'l2' }, { id: 'f3' }, { id: 'l4' }, { id: 'f2' }]); expectOrder(store.getRoot(), ['f1', 'f2', 'f3', 'f4', 'l1', 'l2', 'l3', 'l4']); }); }); describe("with folderSort: false", function() { it("should sort by existing sorters when setting folderSort: false", function() { store = new Ext.data.TreeStore({ model: NodeModel, folderSort: false, sorters: ['id'], root: { expanded: true } }); completeWithData([{ id: 'a', leaf: true }, { id: 'b' }, { id: 'c', leaf: true }, { id: 'd' }]); store.setFolderSort(false); expectOrder(store.getRoot(), ['a', 'b', 'c', 'd']); }); it("should do a deep sort", function() { store = new Ext.data.TreeStore({ model: NodeModel, folderSort: false, sorters: ['id'], root: { expanded: true } }); completeWithData([{ id: 'p1', expanded: true, children: [{ id: 'b', leaf: true }, { id: 'c', leaf: true }, { id: 'a', leaf: true }, { id: 'd', leaf: true }] }, { id: 'p2', expanded: true, children: [{ id: 'g', leaf: true }, { id: 'e', leaf: true }, { id: 'h', leaf: true }, { id: 'f', leaf: true }] }]); store.setFolderSort(false); expectOrder(byId('p1'), ['a', 'b', 'c', 'd']); expectOrder(byId('p2'), ['e', 'f', 'g', 'h']); }); }); }); describe("adding/expanding nodes", function() { it("should sort nodes correctly on expand", function() { store = new Ext.data.TreeStore({ model: NodeModel, sorters: ['id'], root: { expanded: true, children: [{ id: 'a', children: [{ id: 'z' }, { id: 'y' }] }, { id: 'b', children: [{ id: 'x' }, { id: 'w' }] }, { id: 'c', children: [{ id: 'v' }, { id: 'u' }] }] } }); byId('a').expand(); expectOrder(byId('a'), ['y', 'z']); expectStoreOrder(['a', 'y', 'z', 'b', 'c']); byId('b').expand(); expectOrder(byId('b'), ['w', 'x']); expectStoreOrder(['a', 'y', 'z', 'b', 'w', 'x', 'c']); byId('c').expand(); expectOrder(byId('c'), ['u', 'v']); expectStoreOrder(['a', 'y', 'z', 'b', 'w', 'x', 'c', 'u', 'v']); }); it("should sort nodes correctly on add", function() { store = new Ext.data.TreeStore({ model: NodeModel, sorters: ['id'], root: { expanded: true, children: [{ id: 'a', expanded: true, children: [] }, { id: 'b', expanded: true, children: [] }, { id: 'c', expanded: true, children: [] }] } }); byId('a').appendChild([{ id: 'y' }, { id: 'z' }]); expectOrder(byId('a'), ['y', 'z']); expectStoreOrder(['a', 'y', 'z', 'b', 'c']); byId('b').appendChild([{ id: 'w' }, { id: 'x' }]); expectOrder(byId('b'), ['w', 'x']); expectStoreOrder(['a', 'y', 'z', 'b', 'w', 'x', 'c']); byId('c').appendChild([{ id: 'u' }, { id: 'v' }]); expectOrder(byId('c'), ['u', 'v']); expectStoreOrder(['a', 'y', 'z', 'b', 'w', 'x', 'c', 'u', 'v']); }); }); }); describe("getNodeById", function() { it("should return null if there is no matching id", function() { store = new Ext.data.TreeStore({ model: NodeModel, root: { expanded: true, text: 'Root' } }); expect(store.getNodeById('foo')).toBeNull(); }); it("should be able to return the root", function() { store = new Ext.data.TreeStore({ model: NodeModel, root: { expanded: true, id: 'root' } }); expect(store.getNodeById('root')).toBe(store.getRoot()); }); it("should be able to return a deep node", function() { store = new Ext.data.TreeStore({ model: NodeModel, root: { expanded: true, children: [{ expanded: true, children: [{ expanded: true, children: [{ expanded: true, children: [{ id: 'deep' }] }] }] }] } }); var idNode; store.getRoot().cascade(function(node) { if (node.id === 'deep') { idNode = node; } }); expect(store.getNodeById('deep')).toBe(idNode); }); it('should be usable during nodeappend event', function () { var ids = []; store = new Ext.data.TreeStore({ model: NodeModel, listeners: { nodeappend: function (parent, child, index) { ids.push(child.id); var treeStore = child.getTreeStore(); var c = treeStore.getNodeById(child.id); // easy to read output: expect(c && c.id).toBe(child.id); // nearly useless output on failure (but not infinite expansion): expect(c === child).toBe(true); } }, root: { expanded: true, id: 'root', children: [{ id: 'child', expanded: false, children: [{ id: 'leaf' }] }] } }); expect(ids.join(' ')).toBe('root child leaf'); }); it("should find loaded children of collapsed nodes", function() { store = new Ext.data.TreeStore({ model: NodeModel, root: { expanded: true, children: [{ expanded: false, children: [{ id: 'leaf' }] }] } }); expect(store.getNodeById('leaf')).toBe(store.getRoot().firstChild.firstChild); }); it("should find nodes that are filtered out", function() { store = new Ext.data.TreeStore({ model: NodeModel, root: { expanded: true, children: [{ text: 'A' }, { text: 'A' }, { text: 'A' }, { id: 'bNode', text: 'B' }] } }); expect(store.getCount()).toBe(4); store.filter('text', 'A'); expect(store.getCount()).toBe(3); expect(store.getNodeById('bNode')).toBe(store.getRoot().lastChild); }); }); describe("loading data", function() { describe("isLoaded", function() { it("should be false by default", function() { store = new Ext.data.TreeStore({ root: { text: 'Root' } }); expect(store.isLoaded()).toBe(false); }); it("should be true after a load", function() { store = new Ext.data.TreeStore({ root: { text: 'Root' } }); store.load(); expect(store.isLoaded()).toBe(true); }); }); describe("when loading asynchronously from a url", function() { describe("if the root node is expanded", function() { it("should load the TreeStore automatically", function() { spyOn(Ext.data.TreeStore.prototype, 'load').andCallThrough(); store = new Ext.data.TreeStore({ model: NodeModel, asynchronousLoad: true, root: { expanded: true, id: 0, name: 'Root Node' } }); expect(store.load.callCount).toBe(1); }); describe("with autoLoad: true", function() { it("should not load twice with a root defined", function() { spyOn(Ext.data.TreeStore.prototype, 'flushLoad').andCallThrough(); runs(function() { store = Ext.create('Ext.data.TreeStore', { model: NodeModel, autoLoad: true, asynchronousLoad: true, root: { expanded: true, id: 0, name: 'Root Node' } }); }); // autoLoad runs on a timer, can't use waitsFor here waits(10); runs(function() { expect(store.flushLoad.callCount).toBe(1); }); }); it("should not load twice without a root defined", function() { spyOn(Ext.data.TreeStore.prototype, 'flushLoad').andCallThrough(); runs(function() { store = Ext.create('Ext.data.TreeStore', { model: NodeModel, autoLoad: true, asynchronousLoad: true }); }); // autoLoad runs on a timer, can't use waitsFor here waits(10); runs(function() { expect(store.flushLoad.callCount).toBe(1); }); }); }); }); describe("if the root node is not expanded", function() { beforeEach(function() { store = new Ext.data.TreeStore({ model: NodeModel, autoLoad: false, asynchronousLoad: true, root: { expanded: false, id: 0, name: 'Root Node' } }); }); it("should not be loading before load is called", function() { expect(store.isLoading()).toBe(false); }); it("should be loading while the request is still in progress", function() { store.load(); store.flushLoad(); expect(store.isLoading()).toBe(true); }); it("should not be loading after the request has finished", function() { loadStore(store); expect(store.isLoading()).toBe(false); }); describe("if autoLoad is set to true", function() { beforeEach(function() { spyOn(Ext.data.TreeStore.prototype, 'load').andCallThrough(); store = new Ext.data.TreeStore({ model: NodeModel, autoLoad: true, asynchronousLoad: true, root: { expanded: false, id: 0, name: 'Root Node' } }); }); it("should load the TreeStore automatically", function() { expect(store.load).toHaveBeenCalled(); }); }); }); describe("when reloading a store that already contains records", function() { beforeEach(function() { store = new Ext.data.TreeStore({ model: NodeModel, autoLoad: false, asynchronousLoad: false, root: { expanded: false, id: 0, name: 'Root Node' } }); store.fillNode(store.getRootNode(), store.getProxy().getReader().readRecords(dummyData.children).getRecords()); }); describe("if records have been removed from the store", function() { beforeEach(function() { store.getNodeById(1).remove(); store.getNodeById(5).remove(); store.getNodeById(4).remove(); }); describe("if the node being loaded is the root node", function() { beforeEach(function() { loadStore(store); }); it("should reset the store's removed array", function() { expect(store.getRemovedRecords().length).toBe(0); }); }); describe("if the node being loaded is not the root node", function() { var removed; beforeEach(function() { loadStore(store, {node: store.getNodeById(2)}); }); it("should only remove records from the removed array that were previously descendants of the node being reloaded", function() { removed = store.getRemovedRecords(); expect(removed.length).toBe(1); expect(removed[0].getId()).toBe(1); }); }); describe("if clearRemovedOnLoad is false", function() { var removed; beforeEach(function() { store.clearRemovedOnLoad = false; loadStore(store); }); afterEach(function() { store.clearRemovedOnLoad = true; }); it("should not alter the store's removed array", function() { removed = store.getRemovedRecords(); expect(removed.length).toBe(3); expect(removed[0].getId()).toBe(1); expect(removed[1].getId()).toBe(5); expect(removed[2].getId()).toBe(4); }); }); }); }); describe("when the records in the response data have an index field", function() { beforeEach(function() { dummyData = { success: true, children: [{ id: 1, name: "aaa", index: 2 }, { id: 2, name: "bbb", index: 0, children: [{ id: 3, name: "ccc", index: 1 }, { id: 4, name: "ddd", index: 0 }], expanded: true }, { id: 5, name: "eee", index: 1 }] }; store = new Ext.data.TreeStore({ model: NodeModel, root: { expanded: true, id: 0, name: 'Root Node' } }); loadStore(store); }); it("should sort the root level nodes by index", function() { // use getRootNode (as opposed to new getter getRoot) to test backward compatibilty. expect(store.getRootNode().childNodes[0].getId()).toBe(2); expect(store.getRootNode().childNodes[1].getId()).toBe(5); expect(store.getRootNode().childNodes[2].getId()).toBe(1); }); it("should sort descendants by index", function() { expect(store.getNodeById(2).firstChild.getId()).toBe(4); expect(store.getNodeById(2).lastChild.getId()).toBe(3); }); it("should sort folders first, then in index order", function() { expect(store.getAt(0).getId()).toBe(2); expect(store.getAt(1).getId()).toBe(4); expect(store.getAt(2).getId()).toBe(3); expect(store.getAt(3).getId()).toBe(5); expect(store.getAt(4).getId()).toBe(1); }); }); }); describe("clearOnLoad", function(){ beforeEach(function(){ store = new Ext.data.TreeStore({ model: NodeModel, asynchronousLoad: false, root: { expanded: true, id: 0, name: 'Root Node' } }); completeWithData({ children: [] }); }); it("should remove existing nodes with clearOnLoad: true", function(){ dummyData = { children: [] }; var root = store.getRootNode(); root.appendChild({ id: 'node1', text: 'A' }); root.appendChild({ id: 'node2', text: 'B' }); loadStore(store); expect(store.getRootNode().childNodes.length).toBe(0); expect(store.getNodeById('node1')).toBeNull(); expect(store.getNodeById('node2')).toBeNull(); }); it("should leave existing nodes with clearOnLoad: false", function(){ store.clearOnLoad = false; dummyData = { children: [] }; var root = store.getRootNode(), childNodes = root.childNodes, node1, node2; root.appendChild({ id: 'node1', text: 'A' }); node1 = childNodes[0]; root.appendChild({ id: 'node2', text: 'B' }); node2 = childNodes[1]; loadStore(store); expect(childNodes.length).toBe(2); expect(store.getNodeById('node1')).toBe(node1); expect(store.getNodeById('node2')).toBe(node2); }); it("should ignore dupes with clearOnLoad: false", function(){ store.clearOnLoad = false; dummyData = { children: [{ id: 'node1', text: 'A' }, { id: 'node3', text: 'C' }] }; var root = store.getRootNode(); root.appendChild({ id: 'node1', text: 'A' }); root.appendChild({ id: 'node2', text: 'B' }); loadStore(store); expect(store.getRootNode().childNodes.length).toBe(3); }); }); }); describe('adding data', function () { // See EXTJS-13509. var root, child; afterEach(function () { Ext.destroy(store); root = child = null; }); describe('adding non-leaf nodes with children', function () { var root, child; function doIt(desc, method) { describe(desc + ' an existing node', function () { doAdd(method, false); doAdd(method, true); }); } function doAdd(method, expanded) { describe('expanded: ' + expanded.toString(), function () { it('should add the node and create its child nodes', function () { root[method]({ text: 'child', expanded: expanded, children: [{ text: 'detention', expanded: expanded, children: [{ text: 'ben', leaf: true }, { text: 'bill', leaf: true }] }] }); child = store.getNewRecords()[0]; expect(child.childNodes.length).toBe(1); expect(child.firstChild.childNodes.length).toBe(2); expect(store.getNewRecords().length).toBe(4); }); it('should mark the new nodes as "loaded"', function () { expect(child.get('loaded')).toBe(true); expect(child.firstChild.get('loaded')).toBe(true); }); }); } beforeEach(function () { store = new Ext.data.TreeStore({ root: { name: 'Root Node' } }); root = store.getRootNode(); }); doIt('appending to', 'appendChild'); doIt('inserting before', 'insertBefore'); }); describe('adding childless non-leaf nodes', function () { beforeEach(function () { spyOn(Ext.data.TreeStore.prototype, 'load').andCallThrough(); store = new Ext.data.TreeStore({ model: NodeModel, root: { name: 'Root Node' } }); root = store.getRootNode(); root.appendChild({ text: 'child2', expanded: false }); }); it('should not make a request for data when expanded', function () { root.firstChild.expand(); expect(store.load).not.toHaveBeenCalled(); }); }); }); describe("modifying records", function() { it("should fire the update event and pass the store, record, type & modified fields", function() {