UNPKG

extjs-gpl

Version:

GPL licensed version of Sencha Ext JS

1,273 lines (1,097 loc) 334 kB
/* global Ext, spyOn, expect, jasmine, MockAjaxManager */ describe("Ext.data.Store", function() { var fakeScope = {}, abeRaw, aaronRaw, edRaw, tommyRaw, abeRec, aaronRec, edRec, tommyRec, store, User, data, spy; function customSort(v) { return v * -1; } function spyOnEvent(object, eventName, fn) { var obj = { fn: fn || Ext.emptyFn }, spy = spyOn(obj, "fn"); object.addListener(eventName, obj.fn); return spy; } function addStoreData() { store.add(edRaw, abeRaw, aaronRaw, tommyRaw); assignRecs(); } function assignRecs() { edRec = store.getAt(0); abeRec = store.getAt(1); aaronRec = store.getAt(2); tommyRec = store.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 createStore(cfg, withData) { cfg = cfg || {}; store = new Ext.data.Store(Ext.applyIf(cfg, { asynchronousLoad: false, model: User, data: withData ? [edRaw, abeRaw, aaronRaw, tommyRaw] : null })); if (withData) { assignRecs(); } data = store.data; } function completeWithData(data) { Ext.Ajax.mockComplete({ status: 200, responseText: Ext.JSON.encode(data) }); } function complete(status, text) { Ext.Ajax.mockComplete({ status: status, responseText: '' }); } beforeEach(function() { MockAjaxManager.addMethods(); 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', sortType: customSort }, { name: 'validField', validators: 'presence' } ] }); 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'}; }); afterEach(function() { MockAjaxManager.removeMethods(); Ext.undefine('spec.User'); Ext.data.Model.schema.clear(); store = spy = User = data = Ext.destroy(store); edRaw = edRec = abeRaw = abeRec = aaronRaw = aaronRec = tommyRaw = tommyRec = null; }); describe("initializing", function() { describe("store manager", function() { it("should register if a storeId is passed", function() { createStore({ storeId: 'foo' }); expect(Ext.data.StoreManager.get('foo')).toBe(store); }); }); describe("proxy", function() { describe("configured on the store", function() { it("should create from a string", function() { createStore({ proxy: 'jsonp' }); expect(store.getProxy() instanceof Ext.data.proxy.JsonP).toBe(true); }); it("should create from a config", function() { createStore({ proxy: { type: 'ajax', url: 'foo' } }); var proxy = store.getProxy(); expect(proxy instanceof Ext.data.proxy.Ajax); expect(proxy.getUrl()).toBe('foo'); }); it("should accept an instance", function() { var proxy = new Ext.data.proxy.Memory(); createStore({ proxy: proxy }); expect(store.getProxy()).toBe(proxy); }); }); describe("configured on the model", function() { it("should use the proxy from the model", function() { Ext.define('spec.ProxyWithModel', { extend: 'Ext.data.Model', fields: [], proxy: { type: 'ajax' } }); createStore({ model: 'spec.ProxyWithModel' }); expect(store.getProxy()).toBe(spec.ProxyWithModel.getProxy()); Ext.undefine('spec.ProxyWithModel'); }); }); describe("configured on both", function() { it("should favour the store proxy", function() { Ext.define('spec.ProxyWithModel', { extend: 'Ext.data.Model', fields: [], proxy: { type: 'ajax' } }); var proxy = new Ext.data.proxy.Ajax(); createStore({ model: 'spec.ProxyWithModel', proxy: proxy }); expect(store.getProxy()).toBe(proxy); Ext.undefine('spec.ProxyWithModel'); }); }); describe("memory with data", function() { it("should load the data instantly", function() { createStore({ proxy: { type: 'memory' }, data: [edRaw, abeRaw] }); expect(store.getCount()).toBe(2); }); }); 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.Store({ 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.Store({ 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.Store({ 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.Store({ fields: ['id', 'height', 'width'] }); expect(store.getModel().superclass.self).toBe(Ext.data.Model); }); }); }); describe("autoLoad", function() { it("should not auto load by default", function() { spyOn(Ext.data.Store.prototype, 'flushLoad').andReturn(); createStore({ asynchronousLoad: true }); waits(50); runs(function() { expect(store.flushLoad).not.toHaveBeenCalled(); }); }); describe("autoLoad: true", function() { it("should load the store", function() { spyOn(Ext.data.Store.prototype, 'flushLoad').andCallThrough(); createStore({ asynchronousLoad: true, autoLoad: true }); waitsFor(function() { return store.flushLoad.callCount > 0; }, 'Load never called'); runs(function() { expect(store.flushLoad.callCount).toBe(1); }); }); it("should pass the options if autoLoad is an object", function() { var p = { foo: 'bar' }, o = { params: p }, loadParams; createStore({ autoLoad: o, asynchronousLoad: false, listeners: { beforeload: function(s, operation) { loadParams = operation.getParams(); } } }); // Capture parameter from load options to verify waitsFor(function() { return loadParams.foo === 'bar'; }); }); }); }); describe("fields", function() { it("should create a model with the configured fields", function() { createStore({ fields: ['id', 'height', 'width'] }); var Model = store.getModel(), fields = Model.getFields(); expect(Model.prototype.isModel).toBe(true); expect(fields[0].getName()).toBe('id'); expect(fields[1].getName()).toBe('height'); expect(fields[2].getName()).toBe('width'); }); it("should not be created with a class name", function() { createStore({ fields: ['id', 'height', 'width'] }); var Model = store.getModel(); expect(Model.$className).toBe(null); }); }); describe("data", function() { describe("with no proxy", function() { it("should add any inline data", function() { createStore({ data: [edRaw, abeRaw] }); expect(store.first().id).toBe('ed@sencha.com'); expect(store.last().id).toBe('abe@sencha.com'); }); it("should not fire any events", function() { var spy = jasmine.createSpy(); createStore({ listeners: { clear: spy, add: spy, load: spy, datachanged: spy, refresh: spy }, data: [edRaw, abeRaw, tommyRaw] }); expect(spy).not.toHaveBeenCalled(); }); }); describe("with a proxy", function() { describe("with a memory proxy", function() { it("should load the data and call proxy.read", function() { var proxy = new Ext.data.proxy.Memory(); spyOn(proxy, 'read').andCallThrough(); createStore({ proxy: proxy, data: [abeRaw, tommyRaw] }); expect(store.first().id).toBe('abe@sencha.com'); expect(store.last().id).toBe('tommy@sencha.com'); expect(proxy.read.callCount).toBe(1); }); it("should not fire any events", function() { var spy = jasmine.createSpy(); var proxy = new Ext.data.proxy.Memory(); createStore({ proxy: proxy, data: [abeRaw, tommyRaw], listeners: { clear: spy, add: spy, load: spy, datachanged: spy, refresh: spy } }); expect(spy).not.toHaveBeenCalled(); }); }); describe("with a server proxy", function() { it("should load the data and not call proxy.read", function() { var proxy = new Ext.data.proxy.Ajax(); spyOn(proxy, 'read').andCallThrough(); createStore({ proxy: proxy, data: [aaronRaw, edRaw] }); expect(store.first().id).toBe('aaron@sencha.com'); expect(store.last().id).toBe('ed@sencha.com'); expect(proxy.read).not.toHaveBeenCalled(); }); it("should not fire any events", function() { var spy = jasmine.createSpy(); var proxy = new Ext.data.proxy.Ajax(); createStore({ proxy: proxy, data: [aaronRaw, edRaw], listeners: { clear: spy, add: spy, load: spy, datachanged: spy, refresh: spy } }); expect(spy).not.toHaveBeenCalled(); }); }); }); }); describe('buffered stores', function () { it('should create a BufferedStore if given buffered:true', function () { createStore({ buffered: true }); expect(store.isBufferedStore).toBe(true); expect(store instanceof Ext.data.BufferedStore).toBe(true); }); it('should create a BufferedStore if given type:buffered', function () { // Silence console warning about store created with no model spyOn(Ext.log, 'warn'); store = Ext.Factory.store({ type: 'buffered' }); expect(store.isBufferedStore).toBe(true); expect(store instanceof Ext.data.BufferedStore).toBe(true); }); }); }); describe("beginUpdate/endUpdate", function() { var beginSpy, endSpy; beforeEach(function() { beginSpy = jasmine.createSpy(); endSpy = jasmine.createSpy(); createStore(); }); afterEach(function() { beginSpy = endSpy = null; }); function setup() { createStore(); addStoreData(); 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() { store.add({}); expect(beginSpy.callCount).toBe(1); expect(endSpy.callCount).toBe(1); }); it("should fire begin/end for adding multiple records in contiguous range", function() { store.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'); store.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() { store.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() { store.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() { store.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(); addStoreData(); }); 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("finding", function() { beforeEach(function() { createStore(); addStoreData(); }); describe("find", function() { // Only minimal tests here, since it just calls through to the collection it("should find by the field", function() { expect(store.find('email', 'tommy@sencha.com')).toBe(3); }); it("should find the first matching index", function() { expect(store.find('group', 'admin')).toBe(1); }); it("should return -1 if value is empty", function() { expect(store.find('id', null)).toBe(-1); expect(store.find('id', '')).toBe(-1); expect(store.find('id', undefined)).toBe(-1); expect(store.find('id', [])).toBe(-1); expect(store.find('id', 'foo')).toBe(-1); }); it("should match the start of strings as a default", function() { expect(store.find('email', 'to')).toBe(3); }); }); // Only minimal tests here, since it just calls through to the collection describe("findRecord", function() { it("should return the record instance", function() { expect(store.findRecord('name', 'Ed Spencer')).toBe(edRec); }); it("should find the first matching record", function() { expect(store.findRecord('group', 'code')).toBe(edRec); }); it("should return null when not found", function() { expect(store.findRecord('name', 'Derp')).toBeNull(); }); }); // Only minimal tests here, since it just calls through to the collection describe("finding exact", function() { it("should find the first exact matching record", function() { expect(store.findExact('name', 'Aaron Conran')).toBe(2); }); it("should return -1 if there is no match", function() { expect(store.findExact('name', 'Bed Spencer')).toBe(-1); }); it("should honor the start index", function() { expect(store.findExact('group', 'admin', 1)).toBe(1); }); it("should not do any type coercion", function() { expect(store.findExact('evilness', '70')).toBe(-1); }); }); // Only minimal tests here, since it just calls through to the collection describe("findBy", function() { it("should find by the matching FN", function() { var index = store.findBy(function(rec) { return rec.get('email') === 'abe@sencha.com'; }); expect(index).toBe(1); }); }); // Only minimal tests here, since it just calls through to the collection describe("collect", function() { it("should collect values in order", function() { expect(store.collect('age')).toEqual([25, 20, 26, 70]); }); it("should ignore filtered out values", function() { store.filter('group', 'code'); expect(store.collect('age')).toEqual([25, 70]); }); it("should bypass the filter if we pass the bypass param", function() { store.filter('group', 'code'); expect(store.collect('age', true, true)).toEqual([25, 20, 26, 70]); }); }); }); describe("iterating", function() { var spy; beforeEach(function() { createStore(); addStoreData(); spy = jasmine.createSpy(); }); describe("each", function() { it("should iterate over each record", function() { store.each(spy); expect(spy.callCount).toBe(4); }); it("should pass the record, index & total length", function() { store.each(spy); var args = spy.calls[0].args; expect(args[0]).toBe(edRec); expect(args[1]).toBe(0); expect(args[2]).toBe(4); args = spy.calls[1].args; expect(args[0]).toBe(abeRec); expect(args[1]).toBe(1); expect(args[2]).toBe(4); args = spy.calls[2].args; expect(args[0]).toBe(aaronRec); expect(args[1]).toBe(2); expect(args[2]).toBe(4); args = spy.calls[3].args; expect(args[0]).toBe(tommyRec); expect(args[1]).toBe(3); expect(args[2]).toBe(4); }); it("should stop iterating if false is returned", function() { var count = 0; store.each(function(rec, idx) { if (idx > 1) { return false; } ++count; }); expect(count).toBe(2); }); it("should default the scope to the record", function() { store.each(spy); expect(spy.mostRecentCall.object).toBe(store.last()); }); it("should use the passed scope", function() { store.each(spy, fakeScope); expect(spy.mostRecentCall.object).toBe(fakeScope); }); it("should be safe to remove records", function() { var all = store.getRange(), recs = []; store.each(function(rec, idx) { recs.push(rec); if(rec.getId().charAt(0) === 'a') { store.remove(rec); } }); expect(store.getRemovedRecords().length).toBe(2); expect(store.getCount()).toBe(2); expect(recs).toEqual(all); }); }); }); describe("index", function() { beforeEach(function() { createStore(); addStoreData(); }); describe("indexOf", function() { it("should return the index of a record that exists in the store", function() { expect(store.indexOf(abeRec)).toBe(1); }); it("should return -1 when the record does not exist in the store", function() { expect(store.indexOf(makeUser('foo@sencha.com'))).toBe(-1); }); it("should return -1 when the store is empty", function() { store.removeAll(); expect(store.indexOf(edRec)).toBe(-1); }); it("should return -1 when the passed record is null", function() { expect(store.indexOf(null)).toBe(-1); }); }); describe("indexOfId", function() { it("should return the record with matching index", function() { expect(store.indexOfId('aaron@sencha.com')).toBe(2); }); it("should return -1 when the id does not exist in the store", function() { expect(store.indexOfId('foo@sencha.com')).toBe(-1); }); it("should return -1 when the store is empty", function() { store.removeAll(); expect(store.indexOfId('ed@sencha.com')).toBe(-1); }); }); }); describe("counting", function() { describe("getCount", function() { beforeEach(function() { createStore(); }); it("should return 0 when the store is empty", function() { expect(store.getCount()).toBe(0); }); it("should return the number of records currently in the store", function() { addStoreData(); expect(store.getCount()).toBe(4); }); }); describe("getTotalCount", function() { it("should default to 0", function() { createStore(); expect(store.getTotalCount()).toBe(0); }); it("should set a value returned from a proxy read", function() { createStore({ proxy: { type: 'memory', data: { total: 1234 }, reader: 'json' } }); store.load(); expect(store.getTotalCount()).toBe(1234); }); }); }); describe("adding records", function() { describe("add", function() { beforeEach(function() { createStore(); }); describe("position", function() { it("should add to the end of the store", function() { addStoreData(); var rec = makeUser('foo@sencha.com'); store.add(rec); expect(store.getAt(4)).toBe(rec); }); }); describe("arg values", function() { it("should add a model instance", function() { var rec = makeUser('foo@sencha.com'); store.add(rec); expect(store.first()).toBe(rec); }); it("should create a model from an object config", function() { store.add({ email: 'foo@sencha.com', name: 'Foo' }); var rec = store.first(); expect(rec.isModel).toBe(true); expect(rec.get('name')).toBe('Foo'); }); }); describe("adding multiple", function() { it("should add an array of records", function() { store.add([{ email: 'personA@sencha.com', name: 'Person A' }, { email: 'personB@sencha.com', name: 'Person B' }]); expect(store.first().get('name')).toBe('Person A'); expect(store.last().get('name')).toBe('Person B'); }); it("should add multiple arguments", function() { store.add({ email: 'personA@sencha.com', name: 'Person A' }, { email: 'personB@sencha.com', name: 'Person B' }); expect(store.first().get('name')).toBe('Person A'); expect(store.last().get('name')).toBe('Person B'); }); }); describe("return value", function() { it("should return an array when adding a single item", function() { var rec = makeUser('foo@sencha.com'); expect(store.add(rec)).toEqual([rec]); }); it("should return an array when adding an array, should not mutate the array", function() { var rec = makeUser('foo@sencha.com'), arr = [rec], result = store.add(arr); expect(result).toEqual([rec]); expect(result).not.toBe(arr); }); it("should return an array when adding multiple args", function() { var rec1 = makeUser('user1@sencha.com'), rec2 = makeUser('user2@sencha.com'); expect(store.add(rec1, rec2)).toEqual([rec1, rec2]); }); it("should return an empty array if nothing was passed", function() { expect(store.add()).toEqual([]); }); it("should return an empty array if an empty array was passed", function() { expect(store.add([])).toEqual([]); }); }); describe("events", function() { var spy, rec1, rec2; beforeEach(function() { addStoreData(); spy = jasmine.createSpy(); rec1 = makeUser('user1@sencha.com'); rec2 = makeUser('user2@sencha.com'); }); describe("a single item", function() { it("should fire the add event, passing the store, the records & the added index", function() { store.on('add', spy); store.add(rec1); var args = spy.mostRecentCall.args; expect(spy.callCount).toBe(1); expect(args[0]).toBe(store); expect(args[1]).toEqual([rec1]); expect(args[2]).toBe(4); }); it("should fire the datachanged event", function() { store.on('datachanged', spy); store.add(rec1, rec2); var args = spy.mostRecentCall.args; expect(spy.callCount).toBe(1); expect(args[0]).toBe(store); }); }); describe("multiple items", function() { describe("contiguous range", function() { it("should fire the add event, passing the store, the records & the added index", function() { store.on('add', spy); store.add(rec1, rec2); var args = spy.mostRecentCall.args; expect(spy.callCount).toBe(1); expect(args[0]).toBe(store); expect(args[1]).toEqual([rec1, rec2]); expect(args[2]).toBe(4); }); it("should fire the datachanged event", function() { store.on('datachanged', spy); store.add(rec1, rec2); var args = spy.mostRecentCall.args; expect(spy.callCount).toBe(1); expect(args[0]).toBe(store); }); }); // This is only possible if the store is sorted, since adding multiple items may // require them to be split into different "add" groups describe("discontiguous range", function() { var recs; beforeEach(function() { store.removeAll(); store.sort('email'); store.add( makeUser('e@sencha.com'), makeUser('j@sencha.com'), makeUser('o@sencha.com'), makeUser('t@sencha.com') ); recs = [ makeUser('a@sencha.com'), makeUser('b@sencha.com'), makeUser('f@sencha.com'), makeUser('g@sencha.com'), makeUser('h@sencha.com'), makeUser('l@sencha.com'), makeUser('p@sencha.com'), makeUser('q@sencha.com'), makeUser('r@sencha.com'), makeUser('s@sencha.com') ]; }); it("should fire the add event, passing the store, the records & the added index for each chunk", function() { store.on('add', spy); store.add( recs[6], recs[1], recs[9], recs[4], recs[3], recs[7], recs[5], recs[2], recs[8], recs[0] ); expect(spy.callCount).toBe(4); var args = spy.calls[0].args; expect(args[0]).toBe(store); expect(args[1]).toEqual([recs[0], recs[1]]); expect(args[2]).toBe(0); args = spy.calls[1].args; expect(args[0]).toBe(store); expect(args[1]).toEqual([recs[2], recs[3], recs[4]]); expect(args[2]).toBe(3); args = spy.calls[2].args; expect(args[0]).toBe(store); expect(args[1]).toEqual([recs[5]]); expect(args[2]).toBe(7); args = spy.calls[3].args; expect(args[0]).toBe(store); expect(args[1]).toEqual([recs[6], recs[7], recs[8], recs[9]]); expect(args[2]).toBe(9); }); it("should fire the datachanged event", function() { store.on('datachanged', spy); store.add( recs[6], recs[1], recs[9], recs[4], recs[3], recs[7], recs[5], recs[2], recs[8], recs[0] ); var args = spy.mostRecentCall.args; expect(spy.callCount).toBe(1); expect(args[0]).toBe(store); }); }); }); describe("invalid cases", function() { it("should not call the event when the record is null", function() { store.on({ add: spy, datachanged: spy }); store.add(null); expect(spy).not.toHaveBeenCalled(); }); it("should not call the event when the array is empty", function() { store.on({ add: spy, datachanged: spy }); store.add([]); expect(spy).not.toHaveBeenCalled(); }); }); }); }); describe("insert", function() { beforeEach(function() { createStore(); }); describe("position", function() { it("should add at the specified position", function() { addStoreData(); var rec = makeUser('foo@sencha.com'); store.insert(2, rec); expect(store.getAt(2)).toBe(rec); }); it("should add to the end if the index is larger than the bounds", function() { var rec = makeUser('foo@sencha.com'); store.insert(100, rec); expect(store.first()).toBe(rec); }); }); describe("arg values", function() { it("should add a model instance", function() { var rec = makeUser('foo@sencha.com'); store.insert(0, rec); expect(store.first()).toBe(rec); }); it("should create a model from an object config", function() { store.insert(0, { email: 'foo@sencha.com', name: 'Foo' }); var rec = store.first(); expect(rec.isModel).toBe(true); expect(rec.get('name')).toBe('Foo'); }); }); describe("adding multiple", function() { it("should add an array of records", function() { store.insert(0, [{ email: 'personA@sencha.com', name: 'Person A' }, { email: 'personB@sencha.com', name: 'Person B' }]); expect(store.first().get('name')).toBe('Person A'); expect(store.last().get('name')).toBe('Person B'); }); }); describe("return value", function() { it("should return an array when adding a single item", function() { var rec = makeUser('foo@sencha.com');