UNPKG

extjs-gpl

Version:

GPL licensed version of Sencha Ext JS

1,273 lines (1,095 loc) 68.2 kB
/* global expect, Ext, MockAjaxManager, jasmine, spyOn */ describe("Ext.data.ChainedStore", function() { var fakeScope = {}, abeRec, aaronRec, edRec, tommyRec, abeRaw, aaronRaw, edRaw, tommyRaw, source, store, User; function addSourceData() { source.add(edRaw, abeRaw, aaronRaw, tommyRaw); edRec = source.getAt(0); abeRec = source.getAt(1); aaronRec = source.getAt(2); tommyRec = source.getAt(3); } function makeUser(email, data) { if (Ext.isObject(email)) { data = email; } else { data = data || {}; if (!data.email) { data.email = email; } } return new User(data); } function createSource(cfg) { cfg = cfg || {}; source = new Ext.data.Store(Ext.applyIf(cfg, { asynchronousLoad: false, model: 'spec.User' })); } function createStore(cfg) { store = new Ext.data.ChainedStore(Ext.apply({ source: source }, cfg)); } function completeWithData(data) { Ext.Ajax.mockComplete({ status: 200, responseText: Ext.JSON.encode(data) }); } function expectOrder(recs, s) { var len = recs.length, i; for (i = 0; i < len; ++i) { expect(s.getAt(i)).toBe(recs[i]); } } function spyOnEvent(object, eventName, fn) { var obj = { fn: fn || Ext.emptyFn }, spy = spyOn(obj, "fn"); object.addListener(eventName, obj.fn); return spy; } beforeEach(function() { Ext.data.Model.schema.setNamespace('spec'); MockAjaxManager.addMethods(); edRaw = {name: 'Ed Spencer', email: 'ed@sencha.com', evilness: 100, group: 'code', old: false, age: 25, valid: 'yes'}; abeRaw = {name: 'Abe Elias', email: 'abe@sencha.com', evilness: 70, group: 'admin', old: false, age: 20, valid: 'yes'}; aaronRaw = {name: 'Aaron Conran', email: 'aaron@sencha.com', evilness: 5, group: 'admin', old: true, age: 26, valid: 'yes'}; tommyRaw = {name: 'Tommy Maintz', email: 'tommy@sencha.com', evilness: -15, group: 'code', old: true, age: 70, valid: 'yes'}; User = Ext.define('spec.User', { extend: 'Ext.data.Model', idProperty: 'email', fields: [ {name: 'name', type: 'string'}, {name: 'email', type: 'string'}, {name: 'evilness', type: 'int'}, {name: 'group', type: 'string'}, {name: 'old', type: 'boolean'}, {name: 'valid', type: 'string'}, {name: 'age', type: 'int'} ] }); createSource(); addSourceData(); }); afterEach(function() { MockAjaxManager.removeMethods(); Ext.data.Model.schema.clear(); Ext.undefine('spec.User'); User = source = store = Ext.destroy(source, store); Ext.data.Model.schema.clear(true); }); describe("constructing", function() { it("should inherit the model from the backing store", function() { createStore(); expect(store.getModel()).toBe(User); }); it("should have the data from the backing store", function() { createStore(); var sourceData = source.getRange(), storeData = store.getRange(), len = sourceData.length, i; expect(storeData.length).toBe(sourceData.length); for (i = 0; i < len; ++i) { expect(storeData[i]).toBe(sourceData[i]); } }); it("should not fire a refresh or datachanged event", function() { var spy = jasmine.createSpy(); createStore({ listeners: { refresh: spy, datachanged: spy } }); expect(spy).not.toHaveBeenCalled(); }); it("should accept an id of a store as the source", function() { var idSource = new Ext.data.Store({ model: 'spec.User', storeId: 'sourceId' }); source = 'sourceId'; createStore(); source = null; expect(store.getSource()).toBe(idSource); idSource.destroy(); }); it("should accept a chained store as the source", function() { createStore(); var child = new Ext.data.ChainedStore({ source: store }); expect(child.getCount()).toBe(4); expect(child.getModel()).toBe(User); child.destroy(); }); }); it("should not join the records to the store", function() { createStore(); var joined = edRec.joined; expect(joined.length).toBe(1); expect(joined[0]).toBe(source); }); describe("beginUpdate/endUpdate", function() { var beginSpy, endSpy; beforeEach(function() { beginSpy = jasmine.createSpy(); endSpy = jasmine.createSpy(); createStore(); }); afterEach(function() { beginSpy = endSpy = null; }); function setup() { createStore(); store.on('beginupdate', beginSpy); store.on('endupdate', endSpy); } describe("calls to methods directly", function() { it("should fire beginupdate on the first call to beginUpdate", function() { setup(); store.beginUpdate(); expect(beginSpy.callCount).toBe(1); store.beginUpdate(); store.beginUpdate(); expect(beginSpy.callCount).toBe(1); }); it("should fire the endupdate on the last matching call to endUpdate", function() { setup(); store.beginUpdate(); store.beginUpdate(); store.beginUpdate(); store.endUpdate(); store.endUpdate(); expect(endSpy).not.toHaveBeenCalled(); store.endUpdate(); expect(endSpy.callCount).toBe(1); }); }); describe("in reaction to store changes", function() { beforeEach(function() { setup(); }); // TODO: this could be fleshed out further to include more functionality describe("add", function() { it("should fire begin/end for adding a single record", function() { source.add({}); expect(beginSpy.callCount).toBe(1); expect(endSpy.callCount).toBe(1); }); it("should fire begin/end for adding multiple records in contiguous range", function() { source.add([{}, {}, {}, {}]); expect(beginSpy.callCount).toBe(1); expect(endSpy.callCount).toBe(1); }); it("should fire begin/end for adding multiple records over a discontiguous range", function() { store.sort('age'); source.add([{ age: 1 }, { age: 1000 }]); expect(beginSpy.callCount).toBe(1); expect(endSpy.callCount).toBe(1); }); }); describe("remove", function() { it("should fire begin/end for removing a single record", function() { source.removeAt(0); expect(beginSpy.callCount).toBe(1); expect(endSpy.callCount).toBe(1); }); it("should fire begin/end for removing multiple records in contiguous range", function() { source.remove([edRec, abeRec]); expect(beginSpy.callCount).toBe(1); expect(endSpy.callCount).toBe(1); }); it("should fire begin/end for removing multiple records over a discontiguous range", function() { source.remove([edRec, tommyRec]); expect(beginSpy.callCount).toBe(1); expect(endSpy.callCount).toBe(1); }); }); describe("update", function() { it("should fire begin/end for a record update", function() { edRec.set('name', 'foo'); expect(beginSpy.callCount).toBe(1); expect(endSpy.callCount).toBe(1); }); }); }); }); describe("getting records", function() { beforeEach(function() { createStore(); addSourceData(); }); describe("first", function() { it("should return the first record", function() { expect(store.first()).toBe(edRec); }); it("should return the record if there is only 1", function() { store.remove([edRec, abeRec, tommyRec]); expect(store.first()).toBe(aaronRec); }); it("should return null with an empty store", function() { store.removeAll(); expect(store.first()).toBeNull(); }); it("should be affected by filters", function() { store.getFilters().add({ property: 'group', value: 'admin' }); expect(store.first()).toBe(abeRec); }); }); describe("last", function() { it("should return the last record", function() { expect(store.last()).toBe(tommyRec); }); it("should return the record if there is only 1", function() { store.remove([edRec, abeRec, tommyRec]); expect(store.last()).toBe(aaronRec); }); it("should return null with an empty store", function() { store.removeAll(); expect(store.last()).toBeNull(); }); it("should be affected by filters", function() { store.getFilters().add({ property: 'group', value: 'admin' }); expect(store.last()).toBe(aaronRec); }); }); describe("getAt", function() { it("should return the record at the specified index", function() { expect(store.getAt(1)).toBe(abeRec); }); it("should return null when the index is outside the store bounds", function() { expect(store.getAt(100)).toBe(null); }); it("should return null when the store is empty", function() { store.removeAll(); expect(store.getAt(0)).toBe(null); }); }); describe("getById", function() { it("should return the record with the matching id", function() { expect(store.getById('tommy@sencha.com')).toBe(tommyRec); }); it("should return null if a matching id is not found", function() { expect(store.getById('foo@sencha.com')).toBe(null); }); it("should return null when the store is empty", function() { store.removeAll(); expect(store.getById('ed@sencha.com')).toBe(null); }); it("should ignore filters", function() { store.filter('email', 'ed@sencha.com'); expect(store.getById('aaron@sencha.com')).toBe(aaronRec); }); }); describe("getByInternalId", function() { it("should return the record with the matching id", function() { expect(store.getByInternalId(tommyRec.internalId)).toBe(tommyRec); }); it("should return null if a matching id is not found", function() { expect(store.getByInternalId('foo@sencha.com')).toBe(null); }); it("should return null when the store is empty", function() { store.removeAll(); expect(store.getByInternalId('ed@sencha.com')).toBe(null); }); it("should ignore filters", function() { store.filter('email', 'ed@sencha.com'); expect(store.getByInternalId(aaronRec.internalId)).toBe(aaronRec); }); it("should work correctly if not called before filtering", function() { store.filter('email', 'ed@sencha.com'); expect(store.getByInternalId(aaronRec.internalId)).toBe(aaronRec); }); it("should work correctly if called before & after filtering", function() { expect(store.getByInternalId(aaronRec.internalId)).toBe(aaronRec); store.filter('email', 'ed@sencha.com'); expect(store.getByInternalId(aaronRec.internalId)).toBe(aaronRec); }); }); describe("getRange", function() { it("should default to the full store range", function() { expect(store.getRange()).toEqual([edRec, abeRec, aaronRec, tommyRec]); }); it("should return from the start index", function() { expect(store.getRange(2)).toEqual([aaronRec, tommyRec]); }); it("should use the end index, and include it", function() { expect(store.getRange(0, 2)).toEqual([edRec, abeRec, aaronRec]); }); it("should ignore an end index greater than the store range", function() { expect(store.getRange(1, 100)).toEqual([abeRec, aaronRec, tommyRec]); }); }); describe("query", function() { var coders, slackers; it("should return records with group: 'coder'", function() { coders = store.query('group', 'code'); expect(coders.length).toBe(2); expect(coders.contains(edRec)).toBe(true); expect(coders.contains(tommyRec)).toBe(true); expect(coders.contains(aaronRec)).toBe(false); expect(coders.contains(abeRec)).toBe(false); }); it("should return null if a matching id is not found", function() { slackers = store.query('group', 'slackers'); expect(slackers.length).toBe(0); }); it("should return null when the store is empty", function() { store.removeAll(); coders = store.query('group', 'code'); expect(coders.length).toBe(0); }); it("should ignore filters", function() { store.filter('email', 'ed@sencha.com'); expect(store.getCount()).toBe(1); coders = store.query('group', 'code'); expect(coders.length).toBe(2); expect(coders.contains(edRec)).toBe(true); expect(coders.contains(tommyRec)).toBe(true); expect(coders.contains(aaronRec)).toBe(false); expect(coders.contains(abeRec)).toBe(false); }); }); }); describe("sorting", function() { describe("initial values", function() { it("should default to having no sorters", function() { createStore(); expect(store.getSorters().getCount()).toBe(0); }); it("should not inherit sorters from the source store", function() { source.sort('age', 'DESC'); createStore(); expect(store.getSorters().getCount()).toBe(0); }); it("should have the data in order of the source store by default", function() { source.sort('age', 'DESC'); createStore(); expect(store.getAt(0)).toBe(source.getAt(0)); expect(store.getAt(1)).toBe(source.getAt(1)); expect(store.getAt(2)).toBe(source.getAt(2)); expect(store.getAt(3)).toBe(source.getAt(3)); }); }); describe("sorting the source", function() { it("should not change the sort order in the store", function() { createStore(); source.sort('name', 'DESC'); expectOrder([tommyRec, edRec, abeRec, aaronRec], source); expectOrder([edRec, abeRec, aaronRec, tommyRec], store); }); }); describe("sorting the store", function() { it("should not change the sort order in the source store", function() { createStore(); store.sort('name', 'DESC'); expectOrder([tommyRec, edRec, abeRec, aaronRec], store); expectOrder([edRec, abeRec, aaronRec, tommyRec], source); }); }); }); describe("filtering", function() { describe("filtering the source", function() { it("should also filter the store", function() { createStore(); source.filter('group', 'code'); expect(store.getCount()).toBe(2); expectOrder(source.getRange(), store); }); it("should not affect the store filter collection", function() { createStore(); source.filter('group', 'code'); expect(store.getFilters().getCount()).toBe(0); }); it("should also unfilter the store", function() { createStore(); source.filter('group', 'code'); source.getFilters().removeAll(); expect(store.getCount()).toBe(4); expectOrder(source.getRange(), store); }); it("should have a record present in the store when added to the source but filtered out", function() { createStore(); source.filter('group', 'code'); var rec = makeUser('foo@sencha.com', { group: 'admin' }); source.add(rec); source.getFilters().removeAll(); expect(store.indexOf(rec)).toBe(4); }); describe("events", function() { var spy; beforeEach(function() { spy = jasmine.createSpy(); createStore(); }); afterEach(function() { spy = null; }); it("should fire the refresh event on the store", function() { store.on('refresh', spy); source.filter('group', 'code'); expect(spy).toHaveBeenCalled(); expect(spy.callCount).toBe(1); }); it("should fire the datachanged event on the store", function() { store.on('datachanged', spy); source.filter('group', 'code'); expect(spy).toHaveBeenCalled(); expect(spy.callCount).toBe(1); }); it("should not fire the filterchange event", function() { store.on('filterchange', spy); source.filter('group', 'code'); expect(spy).not.toHaveBeenCalled(); }); describe("when the source is a chained store", function() { var child; beforeEach(function() { child = new Ext.data.ChainedStore({ source: store }); }); afterEach(function() { child.destroy(); child = null; }); it("should fire the refresh event on the store", function() { child.on('refresh', spy); store.filter('group', 'code'); expect(spy).toHaveBeenCalled(); expect(spy.callCount).toBe(1); }); it("should fire the datachanged event on the store", function() { child.on('datachanged', spy); store.filter('group', 'code'); expect(spy).toHaveBeenCalled(); expect(spy.callCount).toBe(1); }); it("should not fire the filterchange event", function() { child.on('filterchange', spy); store.filter('group', 'code'); expect(spy).not.toHaveBeenCalled(); }); }); }); }); describe("filtering the store", function() { it("should not filter the source", function() { createStore(); store.filter('group', 'code'); expect(store.getCount()).toBe(2); expect(source.getCount()).toBe(4); }); it("should not affect the source filter collection", function() { createStore(); store.filter('group', 'code'); expect(source.getFilters().getCount()).toBe(0); }); it("should filter based off source filters when the source is filtered", function() { createStore(); source.filter('group', 'code'); store.filter('name', 'Tommy'); expect(store.getCount()).toBe(1); expect(store.getAt(0)).toBe(tommyRec); }); it("should apply source filters over current filters", function() { createStore(); store.getFilters().add({ property: 'age', value: 70, operator: '<' }); expect(store.getCount()).toBe(3); source.filter('group', 'admin'); expect(store.getCount()).toBe(2); expectOrder([abeRec, aaronRec], store); }); describe("events", function() { it("should fire the refresh event", function() { var spy = jasmine.createSpy(); createStore(); store.on('refresh', spy); store.filter('group', 'code'); expect(spy).toHaveBeenCalled(); expect(spy.callCount).toBe(1); }); it("should fire the datachanged event", function() { var spy = jasmine.createSpy(); createStore(); store.on('datachanged', spy); store.filter('group', 'code'); expect(spy).toHaveBeenCalled(); expect(spy.callCount).toBe(1); }); it("should fire the filterchange event", function() { var spy = jasmine.createSpy(); createStore(); store.on('filterchange', spy); store.filter('group', 'code'); expect(spy).toHaveBeenCalled(); expect(spy.callCount).toBe(1); }); it('should fire the update event on both source and chained Stores', function() { store = new Ext.data.ArrayStore({ fields: ['f1'], data: [['f1value']] }); var chained = new Ext.data.ChainedStore({ source: store }), sourceFiredUpdate, chainedFiredUpdate, rec = store.getAt(0); store.on('update', function() { sourceFiredUpdate = true; }); chained.on('update', function(){ chainedFiredUpdate = true; }); // There's one record in each store expect(store.getCount()).toBe(1); expect(chained.getCount()).toBe(1); rec.set('f1', 'f1 updated'); // Should be no change expect(store.getCount()).toBe(1); expect(chained.getCount()).toBe(1); // Both stores fire the update event expect(sourceFiredUpdate).toBe(true); expect(chainedFiredUpdate).toBe(true); chained.destroy(); }); it('should NOT fire the update event on the chained Store if the record is filtered out of the source', function() { store = new Ext.data.ArrayStore({ fields: ['f1'], data: [['f1value']], filters: { property: 'f1', value: 'f1Value' } }); var chained = new Ext.data.ChainedStore({ source: store }), sourceFiredUpdate, chainedFiredUpdate, rec = store.getAt(0); store.on('update', function() { sourceFiredUpdate = true; }); chained.on('update', function() { chainedFiredUpdate = true; }); // There's one record in each store expect(store.getCount()).toBe(1); expect(chained.getCount()).toBe(1); // Will filter the record out of source because "f1 updated" won't match "f1value" rec.set('f1', 'f1 updated'); // The only record is filtered out expect(store.getCount()).toBe(0); expect(chained.getCount()).toBe(0); // Source should have fired the update event expect(sourceFiredUpdate).toBe(true); // Chained store no longer contains the filtered record, // so should not have fired the update event expect(chainedFiredUpdate).toBeFalsy(); chained.destroy(); }); }); }); }); describe("loading", function() { describe("via load", function() { it("should populate the store", function() { source.removeAll(); createStore(); source.load(); completeWithData([abeRaw, tommyRaw, edRaw, aaronRaw]); expectOrder(source.getRange(), store); }); it("should clear any existing data", function() { createStore(); source.load(); completeWithData([{ id: 'foo@sencha.com' }]); expect(store.getCount()).toBe(1); expect(store.getAt(0)).toBe(source.getAt(0)); }); describe("events", function() { it("should not fire the add, remove or clear events", function() { source.removeAll(); createStore(); var spy = jasmine.createSpy(); store.on('add', spy); store.on('remove', spy); store.on('clear', spy); source.load(); completeWithData([abeRaw, tommyRaw, edRaw, aaronRaw]); expect(spy).not.toHaveBeenCalled(); }); it("should relay the beforeload event", function() { var readSpy = spyOn(User.getProxy(), 'read').andCallThrough(); source.removeAll(); createStore(); var spy = jasmine.createSpy(); store.on('beforeload', spy); source.load(); completeWithData([abeRaw, tommyRaw, edRaw, aaronRaw]); expect(spy).toHaveBeenCalled(); expect(spy.mostRecentCall.args[0]).toBe(store); expect(spy.mostRecentCall.args[1]).toBe(readSpy.mostRecentCall.args[0]); }); it("should relay the load event", function() { var readSpy = spyOn(User.getProxy(), 'read').andCallThrough(); source.removeAll(); createStore(); var spy = jasmine.createSpy(); store.on('load', spy); source.load(); completeWithData([abeRaw, tommyRaw, edRaw, aaronRaw]); expect(spy).toHaveBeenCalled(); expect(spy.mostRecentCall.args[0]).toBe(store); expect(spy.mostRecentCall.args[1]).toEqual([source.getAt(0), source.getAt(1), source.getAt(2), source.getAt(3)]); expect(spy.mostRecentCall.args[2]).toBe(true); expect(spy.mostRecentCall.args[3]).toBe(readSpy.mostRecentCall.args[0]); }); it("should fire the refresh and datachanged event", function() { createStore(); var dataChangedSpy = jasmine.createSpy(), refreshSpy = jasmine.createSpy(); store.on('refresh', refreshSpy); store.on('datachanged', dataChangedSpy); source.load(); completeWithData([abeRaw, tommyRaw, edRaw, aaronRaw]); expect(refreshSpy).toHaveBeenCalled(); expect(refreshSpy.mostRecentCall.args[0]).toBe(store); expect(dataChangedSpy).toHaveBeenCalled(); expect(dataChangedSpy.mostRecentCall.args[0]).toBe(store); }); }); }); describe("via loadData", function() { it("should populate the store", function() { source.removeAll(); createStore(); source.loadData([edRaw, tommyRaw, aaronRaw, abeRaw]); expectOrder(source.getRange(), store); }); it("should clear any existing data", function() { createStore(); source.loadData([{ id: 'foo@sencha.com' }]); expect(store.getCount()).toBe(1); expect(store.getAt(0)).toBe(source.getAt(0)); }); it("should not fire the add event", function() { source.removeAll(); createStore(); var spy = jasmine.createSpy(); store.on('add', spy); source.loadData([edRaw, tommyRaw, aaronRaw, abeRaw]); expect(spy).not.toHaveBeenCalled(); }); it("should not fire the remove event", function() { createStore(); var spy = jasmine.createSpy(); store.on('remove', spy); source.loadData([edRaw, tommyRaw, aaronRaw, abeRaw]); expect(spy).not.toHaveBeenCalled(); }); it("should fire the refresh and datachanged event", function() { createStore(); var dataChangedSpy = jasmine.createSpy(), refreshSpy = jasmine.createSpy(); store.on('refresh', refreshSpy); store.on('datachanged', dataChangedSpy); source.loadData([edRaw, tommyRaw, aaronRaw, abeRaw]); expect(refreshSpy).toHaveBeenCalled(); expect(refreshSpy.mostRecentCall.args[0]).toBe(store); expect(dataChangedSpy).toHaveBeenCalled(); expect(dataChangedSpy.mostRecentCall.args[0]).toBe(store); }); }); describe("via loadRawData", function() { it("should populate the store", function() { source.removeAll(); createStore(); source.loadRawData([edRaw, tommyRaw, aaronRaw, abeRaw]); expectOrder(source.getRange(), store); }); it("should clear any existing data", function() { createStore(); source.loadRawData([{ id: 'foo@sencha.com' }]); expect(store.getCount()).toBe(1); expect(store.getAt(0)).toBe(source.getAt(0)); }); it("should not fire the add event", function() { source.removeAll(); createStore(); var spy = jasmine.createSpy(); store.on('add', spy); source.loadRawData([edRaw, tommyRaw, aaronRaw, abeRaw]); expect(spy).not.toHaveBeenCalled(); }); it("should not fire the remove event", function() { createStore(); var spy = jasmine.createSpy(); store.on('remove', spy); source.loadRawData([edRaw, tommyRaw, aaronRaw, abeRaw]); expect(spy).not.toHaveBeenCalled(); }); it("should fire the refresh and datachanged event", function() { createStore(); var dataChangedSpy = jasmine.createSpy(), refreshSpy = jasmine.createSpy(); store.on('refresh', refreshSpy); store.on('datachanged', dataChangedSpy); source.loadRawData([edRaw, tommyRaw, aaronRaw, abeRaw]); expect(refreshSpy).toHaveBeenCalled(); expect(refreshSpy.mostRecentCall.args[0]).toBe(store); expect(dataChangedSpy).toHaveBeenCalled(); expect(dataChangedSpy.mostRecentCall.args[0]).toBe(store); }); }); describe("with sorters", function() { it("should apply sorters from the store", function() { source.removeAll(); createStore(); store.sort('name', 'DESC'); source.load(); completeWithData([abeRaw, edRaw, tommyRaw, aaronRaw]); expect(store.getAt(0).id).toBe('tommy@sencha.com'); expect(store.getAt(1).id).toBe('ed@sencha.com'); expect(store.getAt(2).id).toBe('abe@sencha.com'); expect(store.getAt(3).id).toBe('aaron@sencha.com'); }); }); describe("filters", function() { it("should apply filters from the store", function() { source.removeAll(); createStore(); store.getFilters().add({ property: 'group', value: 'code' }); source.load(); completeWithData([abeRaw, edRaw, tommyRaw, aaronRaw]); expect(store.getCount()).toBe(2); expect(store.getAt(0).id).toBe('ed@sencha.com'); expect(store.getAt(1).id).toBe('tommy@sencha.com'); }); }); }); describe("adding", function() { beforeEach(function() { createStore(); }); describe("adding to the source", function() { it("should also add to the store", function() { var rec = source.add({ id: 'new@sencha.com' })[0]; expect(store.getAt(4)).toBe(rec); }); describe("events", function() { it("should fire the add/datachanged event on the store", function() { var addSpy = jasmine.createSpy(), datachangedSpy = jasmine.createSpy(), rec, args; store.on('add', addSpy); store.on('datachanged', datachangedSpy); rec = source.add({ id: 'new@sencha.com' })[0]; expect(addSpy).toHaveBeenCalled(); args = addSpy.mostRecentCall.args; expect(args[0]).toBe(store); expect(args[1]).toEqual([rec]); expect(args[2]).toBe(4); expect(datachangedSpy).toHaveBeenCalled(); expect(datachangedSpy.mostRecentCall.args[0]).toBe(store); }); it("should fire add on the source, then the store", function() { var order = []; source.on('add', function() { order.push('source'); }); store.on('add', function() { order.push('store'); }); source.add({ id: 'foo@sencha.com' }); expect(order).toEqual(['source', 'store']); }); }); describe("with sorting", function() { describe("with the source sorted", function() { it("should use the position from the source", function() { source.sort('email'); var rec = source.add({ email: 'aaaa@sencha.com' })[0]; expect(source.getAt(0)).toBe(rec); expect(store.getAt(0)).toBe(rec); }); }); describe("with the store sorted", function() { it("should add to the end of the source and insert into the sorted position in the store", function() { store.sort('email'); var rec = source.add({ email: 'bbb@sencha.com' })[0]; expect(source.getAt(4)).toBe(rec); expect(store.getAt(2)).toBe(rec); }); }); describe("with both sorted", function() { it("should insert into the correct sorted position", function() { store.sort('email'); source.sort('email', 'desc'); var rec = source.add({ email: 'aazzon@sencha.com' })[0]; expect(source.getAt(3)).toBe(rec); expect(store.getAt(1)).toBe(rec); }); }); }); describe("with filtering", function() { it("should filter out non-matching records", function() { store.filter('group', 'admin'); var rec = source.add({ email: 'new@sencha.com', group: 'code' })[0]; expect(store.indexOf(rec)).toBe(-1); }); it("should include the filtered out record when filters are cleared", function() { store.filter('group', 'admin'); var rec = source.add({ email: 'new@sencha.com', group: 'code' })[0]; store.getFilters().removeAll(); expect(store.getAt(4)).toBe(rec); }); }); }); describe("adding to the store", function() { it("should also add the record to the source", function() { var rec = store.add({ id: 'new@sencha.com' })[0]; expect(source.getAt(4)).toBe(rec); }); describe("events", function() { it("should fire the add/datachanged event on the source", function() { var addSpy = jasmine.createSpy(), datachangedSpy = jasmine.createSpy(); source.on('add', addSpy); source.on('datachanged', datachangedSpy); var rec = store.add({ id: 'new@sencha.com' })[0], args; expect(addSpy).toHaveBeenCalled(); args = addSpy.mostRecentCall.args; expect(args[0]).toBe(source); expect(args[1]).toEqual([rec]); expect(args[2]).toBe(4); expect(datachangedSpy).toHaveBeenCalled(); expect(datachangedSpy.mostRecentCall.args[0]).toBe(source); }); it("should fire add on the source, then the store", function() { var order = []; source.on('add', function() { order.push('source'); }); store.on('add', function() { order.push('store'); }); store.add({ id: 'foo@sencha.com' }); expect(order).toEqual(['source', 'store']); }); }); describe("with sorting", function() { describe("with the source sorted", function() { it("should append to the store and add to the sorted position in the source", function() { source.sort('email'); var rec = store.add({ email: 'aaaa@sencha.com' })[0]; expect(source.getAt(0)).toBe(rec); expect(store.getAt(4)).toBe(rec); }); }); describe("with the store sorted", function() { it("should append to the source and add to the sorted position in the store", function() { store.sort('email'); var rec = source.add({ email: 'aaaa@sencha.com' })[0]; expect(store.getAt(0)).toBe(rec); }); }); describe("with both sorted", function() { it("should insert into the correct sorted position", function() { store.sort('email'); source.sort('email', 'desc'); var rec = source.add({ email: 'aazzon@sencha.com' })[0]; expect(source.getAt(3)).toBe(rec); expect(store.getAt(1)).toBe(rec); }); }); }); }); }); describe("inserting", function() { beforeEach(function() { createStore(); }); describe("inserting in the source", function() { it("should also add to the store", function() { var rec = source.insert(0, { id: 'new@sencha.com' })[0]; expect(source.getAt(0)).toBe(rec); expect(store.getAt(0)).toBe(rec); }); describe("events", function() { it("should fire the add/datachanged event on the store", function() { var addSpy = jasmine.createSpy(), datachangedSpy = jasmine.createSpy(), rec, args; store.on('add', addSpy); store.on('datachanged', datachangedSpy); rec = source.insert(0, { id: 'new@sencha.com' })[0]; expect(addSpy).toHaveBeenCalled(); args = addSpy.mostRecentCall.args; expect(args[0]).toBe(store); expect(args[1]).toEqual([rec]); expect(args[2]).toBe(0); expect(datachangedSpy).toHaveBeenCalled(); expect(datachangedSpy.mostRecentCall.args[0]).toBe(store); }); it("should fire add on the source, then the store", function() { var order = []; source.on('add', function() { order.push('source'); }); store.on('add', function() { order.push('store'); }); source.insert(0, { id: 'foo@sencha.com' }); expect(order).toEqual(['source', 'store']); }); }); describe("with sorting", function() { describe("with the source sorted", function() { it("should use the position from the source", function() { source.sort('email'); var rec = source.insert(2, { email: 'aaaa@sencha.com' })[0]; expect(source.getAt(0)).toBe(rec); expect(store.getAt(0)).toBe(rec); }); }); describe("with the store sorted", function() { it("should insert into the specified position in the source and the sorted position in the store", function() { store.sort('email'); var rec = source.insert(3, { email: 'aaaa@sencha.com' })[0]; expect(source.getAt(3)).toBe(rec); expect(store.getAt(0)).toBe(rec); }); }); describe("with both sorted", function() { it("should insert into the sorted position in both stores", function() { store.sort('email'); source.sort('email', 'desc'); var rec = source.insert(3, { email: 'aazzon@sencha.com' })[0]; expect(source.getAt(3)).toBe(rec); expect(store.getAt(1)).toBe(rec); }); }); }); describe("with filtering", function() { it("should filter out non-matching records", function() { store.filter('group', 'admin'); var rec = source.insert(0, { email: 'new@sencha.com', group: 'code' })[0]; expect(store.indexOf(rec)).toBe(-1); }); it("should include the filtered out record when filters are cleared", function() { store.filter('group', 'admin'); var rec = source.insert(0, { email: 'new@sencha.com', group: 'code' })[0]; store.getFilters().removeAll(); expect(source.getAt(0)).toBe(rec); }); it("should position the item correctly when filtered out", function() { store.filter('group', 'admin'); var rec = source.insert(2, { email: 'new@sencha.com', group: 'code' })[0]; store.getFilters().removeAll(); expect(store.getAt(2)).toBe(rec); }); }); }); describe("inserting in the store", function() { it("should also add the record to the source", function() { var rec = store.insert(0, { id: 'new@sencha.com' })[0]; expect(source.getAt(0)).toBe(rec); }); describe("events", function() { it("should fire the add/datachanged event on the source", function() { var addSpy = jasmine.createSpy(), datachangedSpy = jasmine.createSpy(); source.on('add', addSpy); source.on('datachanged', datachangedSpy); var rec = store.insert(2, {