extjs-gpl
Version:
GPL licensed version of Sencha Ext JS
1,273 lines (1,037 loc) • 190 kB
JavaScript
/* global expect, Ext, jasmine */
describe("Ext.util.Collection", function() {
var collection, fakeScope = {};
function logEvents (col, log, property) {
property = property || 'id';
col.on({
beginupdate: function (sender) {
expect(sender === col).toBe(true);
log.push('beginupdate');
},
add: function (sender, details) {
expect(sender === col).toBe(true);
log.push('add ' + Ext.encode(Ext.Array.pluck(details.items, property)) +
' at ' + details.at);
if (details.keys) {
log[log.length - 1] += ' w/keys ' + Ext.encode(details.keys);
}
},
remove: function (sender, details) {
expect(sender === col).toBe(true);
log.push('remove ' + Ext.encode(Ext.Array.pluck(details.items, property)) +
' at ' + details.at);
if (details.keys) {
log[log.length - 1] += ' w/keys ' + Ext.encode(details.keys);
}
},
endupdate: function (sender) {
expect(sender === col).toBe(true);
log.push('endupdate');
}
});
}
describe('Moving items in a filtered Collection with sorters, but autoSort: false', function() {
var item1, item2, item3, item4, item5, collection;
beforeEach(function() {
collection = new Ext.util.Collection();
item1 = {id: 1};
item2 = {id: 2};
item3 = {id: 3};
item4 = {id: 4};
item5 = {id: 5};
collection.add([item4, item3, item2, item1]);
});
afterEach(function() {
collection.destroy();
});
it('should honour the new insertion point', function() {
collection.sort({property: 'id'});
expect(collection.getAt(0)).toBe(item1);
expect(collection.getAt(1)).toBe(item2);
expect(collection.getAt(2)).toBe(item3);
expect(collection.getAt(3)).toBe(item4);
// A filter which filters in all items
collection.filterBy(function() {
return true;
});
// Because of autoSort, this should sort back to sorted order
collection.insert(0, item4);
expect(collection.getAt(0)).toBe(item1);
expect(collection.getAt(1)).toBe(item2);
expect(collection.getAt(2)).toBe(item3);
expect(collection.getAt(3)).toBe(item4);
// From now on, we should NOT always be in sorted order
collection.setAutoSort(false);
// Should not sort, item 4 should be first
collection.insert(0, item4);
expect(collection.getAt(0)).toBe(item4);
expect(collection.getAt(1)).toBe(item1);
expect(collection.getAt(2)).toBe(item2);
expect(collection.getAt(3)).toBe(item3);
});
it('should honour the new insertion point if we have a source collection', function() {
var downstreamCollection = new Ext.util.Collection({
source: collection
});
downstreamCollection.sort({property: 'id'});
expect(downstreamCollection.getAt(0)).toBe(item1);
expect(downstreamCollection.getAt(1)).toBe(item2);
expect(downstreamCollection.getAt(2)).toBe(item3);
expect(downstreamCollection.getAt(3)).toBe(item4);
// A filter which filters in all items
downstreamCollection.filterBy(function() {
return true;
});
// Because of autoSort, this should sort back to sorted order
collection.insert(0, item4);
expect(downstreamCollection.getAt(0)).toBe(item1);
expect(downstreamCollection.getAt(1)).toBe(item2);
expect(downstreamCollection.getAt(2)).toBe(item3);
expect(downstreamCollection.getAt(3)).toBe(item4);
// From now on, we should NOT always be in sorted order
downstreamCollection.setAutoSort(false);
// Will still be sorted in the downstream Collection.
// autoSort only applies to immediate mutations
collection.add(item1);
expect(downstreamCollection.getAt(0)).toBe(item1);
expect(downstreamCollection.getAt(1)).toBe(item2);
expect(downstreamCollection.getAt(2)).toBe(item3);
expect(downstreamCollection.getAt(3)).toBe(item4);
// The refresh of upstream should still cause a sort.
collection.filterBy(function() {
return true;
});
expect(downstreamCollection.getAt(0)).toBe(item1);
expect(downstreamCollection.getAt(1)).toBe(item2);
expect(downstreamCollection.getAt(2)).toBe(item3);
expect(downstreamCollection.getAt(3)).toBe(item4);
// Inserted into a specific position in upstream Collection.
// Should just get appended into our collection
collection.insert(0, item5);
expect(downstreamCollection.getAt(0)).toBe(item5);
expect(downstreamCollection.getAt(1)).toBe(item1);
expect(downstreamCollection.getAt(2)).toBe(item2);
expect(downstreamCollection.getAt(3)).toBe(item3);
expect(downstreamCollection.getAt(4)).toBe(item4);
});
});
describe("constructor", function() {
it("should provide a default getKey implementation", function() {
collection = new Ext.util.Collection();
var item1 = {id: 1, data: 'first item'},
item2 = {id: 2, data: 'second item'};
collection.add(item1);
collection.add(item2);
expect(collection.get(1)).toBe(item1);
expect(collection.get(2)).toBe(item2);
});
it("should allow a custom getKey implementation", function() {
collection = new Ext.util.Collection({
keyFn: function(item) {
return item.myKey;
}
});
var item1 = {myKey: 'a', data: 'first item'},
item2 = {myKey: 'b', data: 'second item'};
collection.add(item1, item2);
expect(collection.get('a')).toBe(item1);
expect(collection.get('b')).toBe(item2);
});
it("should contain the source items when configured with a source", function() {
var source = new Ext.util.Collection();
source.add({id: 1}, {id: 2}, {id: 3});
collection = new Ext.util.Collection({
source: source
});
expect(collection.getCount()).toBe(3);
});
});
describe("iterators", function() {
var fn, callScope, item1, item2, item3;
beforeEach(function() {
collection = new Ext.util.Collection();
fn = jasmine.createSpy('fn');
item1 = {id: 1, name: 'first'};
item2 = {id: 2, name: 'second'};
item3 = {id: 3, name: 'third'};
collection.add([item1, item2, item3]);
});
describe("each", function() {
it("should call with the correct scope", function() {
collection.each(function() {
callScope = this;
}, fakeScope);
expect(callScope).toBe(fakeScope);
});
it("should call the correct number of times", function() {
collection.each(fn);
expect(fn.callCount).toBe(3);
});
it("should be called with each item", function() {
collection.each(fn);
expect(fn).toHaveBeenCalledWith(item1, 0, 3);
expect(fn).toHaveBeenCalledWith(item2, 1, 3);
expect(fn).toHaveBeenCalledWith(item3, 2, 3);
});
});
describe("eachKey", function() {
it("should be called with the correct scope", function() {
collection.eachKey(function() {
callScope = this;
}, fakeScope);
expect(callScope).toBe(fakeScope);
});
it("should call the correct number of times", function() {
collection.eachKey(fn);
expect(fn.callCount).toBe(3);
});
it("should be called with each key", function() {
collection.eachKey(fn);
expect(fn).toHaveBeenCalledWith(1, item1, 0, 3);
expect(fn).toHaveBeenCalledWith(2, item2, 1, 3);
expect(fn).toHaveBeenCalledWith(3, item3, 2, 3);
});
});
});
describe("adding items", function() {
var item1, item2, item3, item4;
beforeEach(function() {
collection = new Ext.util.Collection();
item1 = {id: 1};
item2 = {id: 2};
item3 = {id: 3};
item4 = {id: 4};
});
afterEach(function() {
item1 = item2 = item3 = item4 = null;
});
it('should move an item down by one index successfully', function() {
collection.add([item1, item2, item3, item4]);
collection.insert(1, item1);
expect(collection.getAt(0)).toBe(item2);
expect(collection.getAt(1)).toBe(item1);
expect(collection.getAt(2)).toBe(item3);
expect(collection.getAt(3)).toBe(item4);
});
it("should get the correct count when adding an array", function() {
collection.add([item1, item2]);
expect(collection.getCount()).toBe(2);
expect(collection.length).toBe(2);
expect(collection.getAt(0)).toBe(item1);
expect(collection.getAt(1)).toBe(item2);
});
it("should get the correct count when adding varargs", function() {
collection.add(item1, item2);
expect(collection.getCount()).toBe(2);
expect(collection.length).toBe(2);
expect(collection.getAt(0)).toBe(item1);
expect(collection.getAt(1)).toBe(item2);
});
it("should get the correct count when adding sequentially", function() {
collection.add(item1);
collection.add(item2);
expect(collection.getCount()).toBe(2);
expect(collection.length).toBe(2);
expect(collection.getAt(0)).toBe(item1);
expect(collection.getAt(1)).toBe(item2);
});
it("should fire the add event", function() {
var executed = false;
collection.on('add', function() {
executed = true;
});
collection.add(item1);
expect(executed).toBe(true);
});
describe("with replaceAll", function() {
it("should add when the collection is empty", function() {
collection.replaceAll(item1);
expect(collection.getCount()).toBe(1);
});
it("should remove all existing items", function() {
collection.add(item1, item2, item3);
collection.replaceAll(item4);
expect(collection.getCount()).toBe(1);
expect(collection.first()).toBe(item4);
});
it("should remove even when no items are added", function() {
collection.add(item1, item2, item3);
collection.setDecoder(function() {
return false;
});
collection.replaceAll(item4);
expect(collection.getCount()).toBe(0);
});
});
describe("when sorted", function() {
var spy, expectPos;
beforeEach(function() {
spy = jasmine.createSpy();
});
afterEach(function() {
expect(spy).not.toHaveBeenCalled();
expectPos = spy = null;
});
describe("a single item", function() {
describe("with no items", function() {
beforeEach(function() {
collection.getSorters().add('id');
collection.on('sort', spy);
});
it("should add the item", function() {
expectPos = function() {
expect(collection.length).toBe(1);
expect(collection.getAt(0)).toBe(item1);
expect(collection.indexOfKey(1)).toBe(0);
};
collection.on('add', expectPos);
collection.add(item1);
expectPos();
});
it("should be able to insert at index 0", function() {
collection.insert(0, item1);
expect(collection.getAt(0)).toBe(item1);
});
it("should truncate the position if it goes past range", function() {
collection.insert(10, item1);
expect(collection.getAt(0)).toBe(item1);
expect(collection.length).toBe(1);
});
});
describe("with items", function() {
var items = (function() {
var records = [];
for (var i = 0; i < 30; i++) {
records.push({
id: i,
order: i < 10 ? 'mac' : i < 20 ? 'and' : 'cheese'
});
}
return records;
})(), item1 = {id: 30, order: 'mac'}, item2 = {id: 31, order: 'and'}, item3 = {id: 32, order: 'cheese'};
beforeEach(function() {
collection.getSorters().add('order');
collection.add(items);
collection.on('sort', spy);
});
it("should put the item in the correct position", function() {
collection.add(item1, item2);
expectPos = function() {
expect(collection.length).toBe(33);
expect(collection.getAt(32)).toBe(item1);
expect(collection.getAt(10)).toBe(item2);
expect(collection.indexOfKey(30)).toBe(32);
expect(collection.indexOfKey(31)).toBe(10);
expect(collection.indexOfKey(32)).toBe(21);
};
collection.on('add', expectPos);
collection.add(item3);
expectPos();
});
describe("inserting at index", function() {
it("should be able to insert as the first item", function() {
collection.insert(0, item2);
expect(collection.getAt(0)).toBe(item2);
});
it("should be able to insert as the last item", function() {
collection.insert(30, item1);
expect(collection.getAt(30)).toBe(item1);
});
it("should be able to insert directly after the first item", function() {
collection.insert(1, item2);
expect(collection.getAt(1)).toBe(item2);
});
it("should be able to insert directly before the last item", function() {
collection.insert(29, item1);
expect(collection.getAt(29)).toBe(item1);
expect(collection.length).toBe(31);
});
it("should be able to insert in the middle of the collection", function() {
collection.insert(14, item3);
expect(collection.getAt(14)).toBe(item3);
});
it("should insert at last index of the appropriate sorting if index is out of range", function() {
collection.insert(0, item1);
collection.insert(14, item2);
collection.insert(25, item3);
expect(collection.getAt(10)).toBe(item2);
expect(collection.getAt(21)).toBe(item3);
expect(collection.getAt(32)).toBe(item1);
});
});
});
});
describe("multiple items", function() {
beforeEach(function() {
collection.getSorters().add('id');
collection.on('sort', spy);
});
describe("with no items", function() {
it("should insert the items", function() {
expectPos = function() {
expect(collection.length).toBe(3);
expect(collection.getAt(0)).toBe(item1);
expect(collection.getAt(1)).toBe(item2);
expect(collection.getAt(2)).toBe(item3);
expect(collection.indexOfKey(1)).toBe(0);
expect(collection.indexOfKey(2)).toBe(1);
expect(collection.indexOfKey(3)).toBe(2);
};
collection.on('add', expectPos);
collection.add([item1, item2, item3]);
expectPos();
});
it("should sort the added items", function() {
expectPos = function() {
expect(collection.length).toBe(3);
expect(collection.getAt(0)).toBe(item1);
expect(collection.getAt(1)).toBe(item2);
expect(collection.getAt(2)).toBe(item3);
};
collection.on('add', expectPos);
collection.add([item3, item1, item2]);
expectPos();
});
});
describe("with items", function() {
it("should insert the items into the correct position", function() {
collection.add(item3);
expectPos = function() {
expect(collection.length).toBe(3);
expect(collection.getAt(0)).toBe(item1);
expect(collection.getAt(1)).toBe(item2);
expect(collection.getAt(2)).toBe(item3);
expect(collection.indexOfKey(1)).toBe(0);
expect(collection.indexOfKey(2)).toBe(1);
expect(collection.indexOfKey(3)).toBe(2);
};
collection.on('add', expectPos);
collection.add(item1, item2);
expectPos();
});
it("should sort the added items", function() {
collection.add(item3);
expectPos = function() {
expect(collection.length).toBe(3);
expect(collection.getAt(0)).toBe(item1);
expect(collection.getAt(1)).toBe(item2);
expect(collection.getAt(2)).toBe(item3);
expect(collection.indexOfKey(1)).toBe(0);
expect(collection.indexOfKey(2)).toBe(1);
expect(collection.indexOfKey(3)).toBe(2);
};
collection.on('add', expectPos);
collection.add(item2, item1);
expectPos();
});
it("should insert items in a discontiguous range", function() {
collection.add(item1, item3);
var count = 0;
expectPos = function() {
expect(collection.length).toBe(4);
expect(collection.getAt(0)).toBe(item1);
expect(collection.getAt(1)).toBe(item2);
expect(collection.getAt(2)).toBe(item3);
expect(collection.getAt(3)).toBe(item4);
expect(collection.indexOfKey(1)).toBe(0);
expect(collection.indexOfKey(2)).toBe(1);
expect(collection.indexOfKey(3)).toBe(2);
expect(collection.indexOfKey(4)).toBe(3);
};
collection.on('add', function() {
if (count === 0) {
expect(collection.length).toBe(4);
expect(collection.getAt(0)).toBe(item1);
expect(collection.getAt(1)).toBe(item2);
expect(collection.getAt(2)).toBe(item3);
expect(collection.indexOfKey(1)).toBe(0);
expect(collection.indexOfKey(2)).toBe(1);
expect(collection.indexOfKey(3)).toBe(2);
} else {
expectPos();
}
++count;
});
collection.add(item4, item2);
expectPos();
});
});
});
});
});
describe("removing items", function() {
var item1 = {id: 1, name: 'one'},
item2 = {id: 2, name: 'two'},
item3 = {id: 3, name: 'three'},
item4 = {id: 4, name: 'four'},
item5 = {id: 5, name: 'five'},
item6 = {id: 6, name: 'six'},
item7 = {id: 7, name: 'seven'},
item8 = {id: 8, name: 'eight'},
item9 = {id: 9, name: 'nine'};
beforeEach(function() {
collection = new Ext.util.Collection();
collection.add([
item1,
item2,
item3,
item4,
item5,
item6,
item7,
item8,
item9
]);
});
describe("remove", function() {
it("should remove a single item", function() {
collection.remove(item1);
expect(collection.getCount()).toBe(8);
});
it("should return the removed item count", function(){
expect(collection.remove(item1)).toBe(1);
});
it("should the passed items array", function(){
collection.remove([item2, item3]);
expect(collection.getCount()).toBe(7);
});
it("should fire the remove event when passing items array", function () {
var source = [],
details = [];
collection.on('remove', function (sender, remove) {
source.push(sender);
details.push(remove);
});
collection.remove([item2, item3, item6]);
expect(source.length).toBe(2);
expect(source[0] === collection).toBe(true);
expect(source[1] === collection).toBe(true);
expect(details[0].at).toBe(5);
expect(details[0].items.length).toBe(1);
expect(details[0].items[0]).toBe(item6);
expect(details[0].keys.length).toBe(1);
expect(details[0].keys[0]).toBe(6);
expect(details[1].at).toBe(1);
expect(details[1].items.length).toBe(2);
expect(details[1].items[0]).toBe(item2);
expect(details[1].items[1]).toBe(item3);
expect(details[1].keys.length).toBe(2);
expect(details[1].keys[0]).toBe(2);
expect(details[1].keys[1]).toBe(3);
});
it("should return 0 if no item was found", function(){
expect(collection.remove({ id: 0 })).toBe(0);
});
it("should fire the remove event", function() {
var source, details;
collection.on('remove', function (sender, remove) {
source = sender;
details = remove;
});
collection.remove(item1);
expect(source).toBe(collection);
expect(details.at).toBe(0);
expect(details.items.length).toBe(1);
expect(details.items[0]).toBe(item1);
});
it("should only fire a single event if the items are in a large contiguous range", function() {
var spy = jasmine.createSpy(),
items = [],
i;
for (i = 0; i < 1000; ++i) {
items.push({
id: i + 1
});
}
collection.add(items);
collection.on('remove', spy);
collection.remove(collection.getRange());
expect(spy.callCount).toBe(1);
});
});
describe("removeAt", function() {
it("should remove a single item", function() {
collection.removeAt(1);
expect(collection.getCount()).toBe(8);
});
it("should return the removed item", function(){
expect(collection.removeAt(1)).toBe(item2);
});
it("should return false if no item was found", function(){
expect(collection.removeAt(9)).toBeFalsy();
});
describe("event", function() {
it("should fire the remove event", function() {
var source, details;
collection.on('remove', function (sender, remove) {
source = sender;
details = remove;
});
collection.removeAt(1);
expect(source).toBe(collection);
expect(details.at).toBe(1);
expect(details.items.length).toBe(1);
expect(details.items[0]).toBe(item2);
expect(details.keys.length).toBe(1);
expect(details.keys[0]).toBe(2);
});
it("should update the collection during a remove", function(){
var count, item;
collection.on('remove', function(){
count = collection.getCount();
item = collection.getByKey(1);
});
collection.removeAt(0);
expect(count).toBe(8);
expect(item).toBeUndefined();
});
});
describe("when filtered", function() {
it("should remove the correct item with an all inclusive filter", function() {
collection.getFilters().add(function() {
return true;
});
collection.removeAt(1);
expect(collection.getAt(0)).toBe(item1);
expect(collection.getAt(1)).toBe(item3);
expect(collection.getCount()).toBe(8);
});
});
});
describe("bulkRemove", function(){
it("should limit the length to that of the collection", function () {
collection.removeAt(4, 100);
expect(collection.getCount()).toBe(4);
});
it("should remove the correct items", function(){
collection.removeAt(3, 2);
expect(collection.getCount()).toBe(7);
expect(collection.getAt(2)).toBe(item3);
expect(collection.getAt(3)).toBe(item6);
});
});
describe("removeByKey", function() {
it("should remove a single item", function() {
collection.removeByKey(1);
expect(collection.getCount()).toBe(8);
});
it("should return the removed item", function(){
expect(collection.removeByKey(1)).toBe(item1);
});
it("should return false if no item was found", function(){
expect(collection.removeByKey(10)).toBeFalsy();
});
it("should fire the remove event", function() {
var source, details;
collection.on('remove', function (sender, remove) {
source = sender;
details = remove;
});
collection.removeByKey(2);
expect(source).toBe(collection);
expect(details.at).toBe(1);
expect(details.items.length).toBe(1);
expect(details.items[0]).toBe(item2);
expect(details.keys.length).toBe(1);
expect(details.keys[0]).toBe(2);
});
});
describe("removeAll", function(){
it("should remove all items", function(){
collection.removeAll();
expect(collection.getCount()).toBe(0);
});
it("should fire the remove event with no passed items", function(){
var called = 0,
source, details;
collection.on('remove', function (sender, remove) {
source = sender;
details = remove;
++called;
});
collection.removeAll();
expect(called).toBe(1);
expect(source).toBe(collection);
expect(details.at).toBe(0);
expect(details.items.length).toBe(9);
expect(details.items).toEqual([item1, item2, item3, item4, item5, item6,
item7, item8, item9]);
expect(details.keys.length).toBe(9);
expect(details.keys).toEqual([1,2,3,4,5,6,7,8,9]);
});
});
});
describe("clearing items", function() {
beforeEach(function() {
collection = new Ext.util.Collection();
collection.add([{id: 1}, {id: 2}]);
});
it("should remove all items", function() {
expect(collection.length).toBe(2);
collection.clear();
expect(collection.length).toBe(0);
});
it("should not fire the remove event", function() {
var called = 0;
collection.on('remove', function() {
++called;
});
collection.clear();
expect(called).toBe(0);
});
});
describe("determining insertion index in a sorted Collection", function() {
// Items to sort into name order
var item1 = {id: 2, name: 'Michael'},
item2 = {id: 3, name: 'Yanto'},
item3 = {id: 1, name: 'Bill'},
// Items to find insertion indices for
item4 = {id: 4, name: 'Albert'}, // Insert index 0 when ASC, 3 when DESC
item5 = {id: 5, name: 'Fred'}, // Insert index 1 when ASC, 2 when DESC
item6 = {id: 6, name: 'Robert'}, // Insert index 2 when ASC, 1 when DESC
item7 = {id: 7, name: 'Zebedee'};// Insert index 3 when ASC, 0 when DESC
beforeEach(function() {
collection = new Ext.util.Collection();
collection.add([item1, item2, item3]);
});
function getInsertIndex (item) {
collection.add(item);
var ret = collection.indexOf(item);
collection.remove(item);
return ret;
}
describe("Sorted ascending", function() {
it("should find correct insertion indices", function() {
collection.sort('name');
expect(getInsertIndex(item4)).toBe(0);
expect(getInsertIndex(item5)).toBe(1);
expect(getInsertIndex(item6)).toBe(2);
expect(getInsertIndex(item7)).toBe(3);
});
});
describe("Sorted descending", function() {
it("should find correct insertion indices", function() {
collection.sort('name', 'DESC');
expect(getInsertIndex(item4)).toBe(3);
expect(getInsertIndex(item5)).toBe(2);
expect(getInsertIndex(item6)).toBe(1);
expect(getInsertIndex(item7)).toBe(0);
});
});
});
describe("an existing Collection", function() {
var item1 = {id: 1, name: 'first'},
item2 = {id: 2, name: 'second'},
item3 = {id: 3, name: 'third'},
item4 = {id: 4, name: 'fourth'},
item5 = {id: 5, name: 'fifth'},
item6 = {id: 6, name: 'sixth'},
item7 = {id: 7, name: 'seventh'},
item8 = {id: 8, name: 'eighth'},
item9 = {id: 9, name: 'ninth'};
function fill () {
collection.clear();
collection.add([
item1, // 0 -9
item2, // 1 -8
item3, // 2 -7
item4, // 3 -6
item5, // 4 -5
item6, // 5 -4
item7, // 6 -3
item8, // 7 -2
item9 // 8 -1
]);
}
var generation;
beforeEach(function() {
collection = new Ext.util.Collection();
collection.add([item1, item2, item3]);
generation = collection.generation;
});
describe("updateKey", function(){
it("should do nothing if the old key doesn't exist for member item", function() {
collection.updateKey(item1, 'bar');
expect(collection.getByKey('bar')).toBeUndefined();
expect(collection.getByKey(item1.id)).toBe(item1);
expect(collection.generation).toBe(generation); // no changes made
});
it("should do nothing if the old key doesn't exist for non-member item", function() {
collection.updateKey(item4, 'bar');
expect(collection.getByKey('bar')).toBeUndefined();
expect(collection.getByKey(item4.id)).toBe(undefined);
expect(collection.generation).toBe(generation); // no changes made
});
it("should throw if old key is a different item", function() {
expect(function () {
collection.updateKey(item4, item1.id);
}).toThrow();
expect(collection.getByKey(item4.id)).toBe(undefined);
expect(collection.generation).toBe(generation); // no changes made
});
it("should throw if new key collides with a different item", function() {
// Replace item1 so we can change its key and not have any issues with
// an error for claiming newItem1 was the item by id=1. We just want to
// check for the collision on the new id.
var newItem1 = Ext.apply({}, item1);
collection.add(newItem1);
generation = collection.generation;
newItem1.id = item3.id;
expect(function () {
collection.updateKey(newItem1, item1.id);
}).toThrow();
expect(collection.getByKey(item3.id)).toBe(item3);
expect(collection.generation).toBe(generation); // no changes made
});
it("should update the key for the item", function () {
var newItem1 = Ext.apply({}, item1);
collection.clear();
collection.add(newItem1, item2, item3);
newItem1.id = 20;
collection.updateKey(newItem1, 1);
expect(collection.getByKey(1)).toBeUndefined();
expect(collection.getByKey(20)).toBe(newItem1);
// The index must no longer contain the old key
expect(collection.indexOfKey(1)).toBe(-1);
expect(collection.indexOfKey(20)).toBe(0);
});
});
describe("inserting items", function() {
it("should insert a new item", function() {
var count = collection.getCount();
collection.insert(0, item4);
expect(collection.getCount()).toBe(count + 1);
});
it("should fire the add event", function() {
var called = 0,
source, details;
collection.on('add', function (sender, add) {
++called;
source = sender;
details = add;
});
collection.insert(0, item4);
expect(called).toBe(1);
expect(source).toBe(collection);
expect(details.at).toBe(0);
expect(details.items.length).toBe(1);
expect(details.items[0]).toBe(item4);
expect(details.keys.length).toBe(1);
expect(details.keys[0]).toBe(4);
});
it("should insert the item at the correct location", function() {
expect(collection.items[0]).toBe(item1);
collection.insert(0, item4);
expect(collection.items[0]).toBe(item4);
});
describe("with a source", function() {
var child, newItem;
beforeEach(function() {
fill();
child = new Ext.util.Collection();
child.setSource(collection);
newItem = {
id: 100,
name: 'Foo'
};
});
afterEach(function() {
child.destroy();
newItem = child = null;
});
describe("inserting into the source", function() {
it("should have the correct position when inserting at the start", function() {
collection.insert(0, newItem);
expect(child.getAt(0)).toBe(newItem);
});
it("should have the correct position when inserting into the middle", function() {
collection.insert(4, newItem);
expect(child.getAt(4)).toBe(newItem);
});
it("should have the correct position when inserting at the end", function() {
collection.insert(100, newItem);
expect(collection.getAt(9)).toBe(newItem);
});
describe("with source sorted", function() {
it("should take the sorted position from the source", function() {
collection.getSorters().add(function(item1, item2) {
var n1 = item1.name,
n2 = item2.name;
if (n1 === n2) {
return 0;
}
return n1 < n2 ? -1 : 1;
});
newItem.name = 'a';
collection.insert(100, newItem);
expect(child.getAt(0)).toBe(newItem);
});
});
describe("with the child filtered", function() {
it("should have the correct position when inserting at the start", function() {
child.getFilters().add(function(item) {
return item.name === 'third' || item.name === 'seventh' || item.name === 'Foo';
});
collection.insert(0, newItem);
expect(child.getAt(0)).toBe(newItem);
});
it("should have the correct position when inserting into the middle", function() {
child.getFilters().add(function(item) {
return item.name === 'third' || item.name === 'seventh' || item.name === 'Foo';
});
collection.insert(5, newItem);
expect(child.getAt(1)).toBe(newItem);
});
it("should have the correct position when inserting at the end", function() {
child.getFilters().add(function(item) {
return item.name === 'third' || item.name === 'seventh' || item.name === 'Foo';
});
collection.insert(100, newItem);
expect(child.getAt(2)).toBe(newItem);
});
it("should have the correct position when the nearest item in the child is the first item in the source", function() {
child.getFilters().add(function(item) {
return item.name === 'first' || item.name === 'seventh' || item.name === 'Foo';
});
collection.insert(3, newItem);
expect(child.getAt(1)).toBe(newItem);
});
it("should have the correct position when there is no nearest item in the source", function() {
child.getFilters().add(function(item) {
return item.name === 'seventh' || item.name === 'Foo';
});
collection.insert(3, newItem);
expect(child.getAt(0)).toBe(newItem);
});
});
});
describe("inserting into the child", function() {
it("should have the correct position when inserting at the start", function() {
child.insert(0, newItem);
expect(collection.getAt(0)).toBe(newItem);
});
it("should have the correct position when inserting into the middle", function() {
child.insert(4, newItem);
expect(collection.getAt(4)).toBe(newItem);
});
it("should have the correct position when inserting at the end", function() {
child.insert(100, newItem);
expect(collection.getAt(9)).toBe(newItem);
});
describe("with the source sorted", function() {
it("should use the specified position", function() {
collection.sort('name');
var item = {id: 100, name: 'zzzz'};
child.insert(0, item);
expect(child.getAt(0)).toBe(item);
expect(collection.getAt(9)).toBe(item);
});
});
describe("when filtered", function() {
it("should adjust the position for the source collection", function() {
child.getFilters().add(function(item) {
return item.name !== 'first' && item.name !== 'second';
});
child.insert(0, newItem);
expect(collection.indexOf(newItem)).toBe(2);
});
});
});
it("should not cause an exception when modifying the item in the source onCollectionAdd & the child is sorted", function() {
var o = {
observerPriority: -1000,
onCollectionAdd: function(source, details) {
var item = details.items[0];
item.name = 'asdf';
expect(function() {
collection.itemChanged(item, ['name']);
}).not.toThrow();
}
};
child.getSorters().add('name');
collection.addObserver(o);
collection.add({
id: 1000,
name: 'q'
});
});
});
});
describe("replacing items", function() {
it("should replace the correct item", function() {
collection.splice(1, 1, [item4]);
expect(collection.getAt(1)).toBe(item4);
});
it("should not change the count", function() {
var count = collection.getCount();
collection.splice(1, 1, [item4]);
expect(collection.getCount()).toBe(count);
});
it("should fire the proper events", function() {
var log = [];
logEvents(collection, log, 'name');
collection.splice(1, 1, [item4]);
expect(log).toEqual([
'beginupdate',
'remove ["second"] at 1 w/keys [2]',
'add ["fourth"] at 1 w/keys [4]',
'endupdate'
]);
});
});
describe("cloning", function() {
it("should copy all items into the new Collection", function() {
var mc2 = collection.clone();
expect(mc2.getCount()).toBe(3);
expect(mc2.items[0]).toBe(item1);
expect(mc2.items[1]).toBe(item2);
expect(mc2.items[2]).toBe(item3);
});
it("should keep the getKey fn", function(){
var fn = function(o){
return o.id;
}, mc1 = new Ext.util.Collection({
keyFn: fn
});
var mc2 = mc1.clone();
expect(mc2.getKey).toBe(fn);
mc1 = mc2 = null;
});
});
describe("getting items", function() {
it("should get an item's key", function() {
expect(collection.getKey(item1)).toBe(1);
});
describe("first", function() {
it("should get the first item", function() {
expect(collection.first()).toBe(item1);
});
it("should return undefined if the collection is empty", function() {
collection = new Ext.util.Collection();
expect(collection.first()).toBeUndefined();
});
});
describe("last", function() {
it("should get the last item", function() {
expect(collection.last()).toBe(item3);
});
it("should return undefined if the collection is empty", function() {
collection = new Ext.util.Collection();
expect(collection.last()).toBeUndefined();
});
});
describe("get", function() {
it("should get by key", function() {
expect(collection.get(2)).toBe(item2);
});
it("should return undefined if the key doesn't exist", function() {
expect(collection.get(100)).toBeUndefined();
});
it("should get an newly added item", function() {
var item5 = {id: 'a', name: 'fifth item'};
collection.add(item5);
expect(collection.get('a')).toBe(item5);
});
});
describe("indexOf", function() {
it("should return the correct indexOf an item", function() {