extjs-gpl
Version:
GPL licensed version of Sencha Ext JS
1,273 lines (1,097 loc) • 334 kB
JavaScript
/* 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');