collection tests

This commit is contained in:
antelle 2019-10-27 10:35:36 +01:00
parent 0fce37cc73
commit 50976b2d09
3 changed files with 382 additions and 3 deletions

View File

@ -15,7 +15,7 @@ function emitSet(target, value, prevValue) {
emitter.emit('add', value, target);
updates.added.push(value);
}
emitter.emit('change', updates, this);
emitter.emit('change', updates, target);
}
}
@ -25,7 +25,7 @@ function emitRemoved(target, removed) {
for (const item of removed) {
emitter.emit('remove', item, target);
}
emitter.emit('change', { added: [], removed }, this);
emitter.emit('change', { added: [], removed }, target);
}
}
@ -127,6 +127,7 @@ class Collection {
this[SymbolEvents].emit('remove', item, this);
this[SymbolEvents].emit('change', { added: [], removed: [item] }, this);
}
return item;
}
shift() {
@ -137,6 +138,7 @@ class Collection {
this[SymbolEvents].emit('remove', item, this);
this[SymbolEvents].emit('change', { added: [], removed: [item] }, this);
}
return item;
}
unshift(...items) {
@ -197,7 +199,7 @@ class Collection {
}
sort() {
this[SymbolArray].sort(this.comparator);
return this[SymbolArray].sort(this.comparator);
}
fill() {

View File

@ -0,0 +1,373 @@
import { expect } from 'chai';
import { Model } from 'framework/model';
import { Collection } from 'framework/collection';
describe('Collection', () => {
class TestModel extends Model {
constructor(id) {
super();
this.id = id;
}
}
TestModel.defineModelProperties({ id: 'bar' });
class TestCollection extends Collection {
static model = TestModel;
}
it('should create a collection without models', () => {
const collection = new TestCollection();
expect(collection).to.be.ok;
expect(collection.length).to.eql(0);
});
it('should create a collection with models', () => {
const collection = new TestCollection([new TestModel('1'), new TestModel('2')]);
expect(collection).to.be.ok;
expect(collection.length).to.eql(2);
expect(collection[0]).to.be.ok;
expect(collection[0].id).to.eql('1');
expect(collection[1]).to.be.ok;
expect(collection[1].id).to.eql('2');
expect(collection[2]).to.be.undefined;
});
it('should check types when adding new items', () => {
const collection = new TestCollection();
expect(() => {
collection.push({ id: 'bar' });
}).to.throw();
});
it('should serialize a collection to JSON', () => {
const collection = new TestCollection([new TestModel('1'), new TestModel('2')]);
expect(JSON.stringify(collection)).to.eql('[{"id":"1"},{"id":"2"}]');
});
it('should add models with push', () => {
const collection = new TestCollection();
const callsChange = [];
const callsAdd = [];
collection.on('change', (...args) => callsChange.push(args));
collection.on('add', (...args) => callsAdd.push(args));
expect(JSON.stringify(collection)).to.eql('[]');
const model1 = new TestModel(1);
collection.push(model1);
expect(callsChange).to.eql([[{ added: [model1], removed: [] }, collection]]);
expect(callsAdd).to.eql([[model1, collection]]);
expect(collection.length).to.eql(1);
expect(JSON.stringify(collection)).to.eql('[{"id":1}]');
callsChange.length = 0;
callsAdd.length = 0;
const modelA = new TestModel('a');
const modelB = new TestModel('b');
collection.push(modelA, modelB);
expect(callsChange).to.eql([[{ added: [modelA, modelB], removed: [] }, collection]]);
expect(callsAdd).to.eql([[modelA, collection], [modelB, collection]]);
expect(collection.length).to.eql(3);
expect(JSON.stringify(collection)).to.eql('[{"id":1},{"id":"a"},{"id":"b"}]');
});
it('should add models with unshift', () => {
const collection = new TestCollection([new TestModel(1)]);
const callsChange = [];
const callsAdd = [];
collection.on('change', (...args) => callsChange.push(args));
collection.on('add', (...args) => callsAdd.push(args));
expect(JSON.stringify(collection)).to.eql('[{"id":1}]');
const model2 = new TestModel(2);
collection.unshift(model2);
expect(callsChange).to.eql([[{ added: [model2], removed: [] }, collection]]);
expect(callsAdd).to.eql([[model2, collection]]);
expect(collection.length).to.eql(2);
expect(JSON.stringify(collection)).to.eql('[{"id":2},{"id":1}]');
callsChange.length = 0;
callsAdd.length = 0;
const modelA = new TestModel('a');
const modelB = new TestModel('b');
collection.unshift(modelA, modelB);
expect(callsChange).to.eql([[{ added: [modelA, modelB], removed: [] }, collection]]);
expect(callsAdd).to.eql([[modelA, collection], [modelB, collection]]);
expect(collection.length).to.eql(4);
expect(JSON.stringify(collection)).to.eql('[{"id":"a"},{"id":"b"},{"id":2},{"id":1}]');
});
it('should remove models with pop', () => {
const model1 = new TestModel(1);
const model2 = new TestModel(2);
const collection = new TestCollection([model1, model2]);
const callsChange = [];
const callsRemove = [];
collection.on('change', (...args) => callsChange.push(args));
collection.on('remove', (...args) => callsRemove.push(args));
expect(JSON.stringify(collection)).to.eql('[{"id":1},{"id":2}]');
const popped1 = collection.pop();
expect(popped1).to.eql(model2);
expect(callsChange).to.eql([[{ added: [], removed: [model2] }, collection]]);
expect(callsRemove).to.eql([[model2, collection]]);
expect(collection.length).to.eql(1);
expect(JSON.stringify(collection)).to.eql('[{"id":1}]');
callsChange.length = 0;
callsRemove.length = 0;
const popped2 = collection.pop();
expect(popped2).to.eql(model1);
expect(callsChange).to.eql([[{ added: [], removed: [model1] }, collection]]);
expect(callsRemove).to.eql([[model1, collection]]);
expect(JSON.stringify(collection)).to.eql('[]');
callsChange.length = 0;
callsRemove.length = 0;
const popped3 = collection.pop();
expect(popped3).to.be.undefined;
expect(callsChange).to.eql([]);
expect(callsRemove).to.eql([]);
expect(JSON.stringify(collection)).to.eql('[]');
});
it('should remove models with shift', () => {
const model1 = new TestModel(1);
const model2 = new TestModel(2);
const collection = new TestCollection([model1, model2]);
const callsChange = [];
const callsRemove = [];
collection.on('change', (...args) => callsChange.push(args));
collection.on('remove', (...args) => callsRemove.push(args));
expect(JSON.stringify(collection)).to.eql('[{"id":1},{"id":2}]');
const shifted1 = collection.shift();
expect(shifted1).to.eql(model1);
expect(callsChange).to.eql([[{ added: [], removed: [model1] }, collection]]);
expect(callsRemove).to.eql([[model1, collection]]);
expect(collection.length).to.eql(1);
expect(JSON.stringify(collection)).to.eql('[{"id":2}]');
callsChange.length = 0;
callsRemove.length = 0;
const shifted2 = collection.shift();
expect(shifted2).to.eql(model2);
expect(callsChange).to.eql([[{ added: [], removed: [model2] }, collection]]);
expect(callsRemove).to.eql([[model2, collection]]);
expect(collection.length).to.eql(0);
expect(JSON.stringify(collection)).to.eql('[]');
callsChange.length = 0;
callsRemove.length = 0;
const shifted3 = collection.shift();
expect(shifted3).to.be.undefined;
expect(callsChange).to.eql([]);
expect(callsRemove).to.eql([]);
expect(collection.length).to.eql(0);
expect(JSON.stringify(collection)).to.eql('[]');
});
it('should remove models by setting length', () => {
const model1 = new TestModel(1);
const model2 = new TestModel(2);
const model3 = new TestModel(3);
const collection = new TestCollection([model1, model2, model3]);
const callsChange = [];
const callsRemove = [];
collection.on('change', (...args) => callsChange.push(args));
collection.on('remove', (...args) => callsRemove.push(args));
expect(JSON.stringify(collection)).to.eql('[{"id":1},{"id":2},{"id":3}]');
collection.length = 1;
expect(callsChange).to.eql([[{ added: [], removed: [model2, model3] }, collection]]);
expect(callsRemove).to.eql([[model2, collection], [model3, collection]]);
expect(collection.length).to.eql(1);
expect(JSON.stringify(collection)).to.eql('[{"id":1}]');
callsChange.length = 0;
callsRemove.length = 0;
collection.length = 1;
expect(callsChange).to.eql([]);
expect(callsRemove).to.eql([]);
expect(collection.length).to.eql(1);
expect(JSON.stringify(collection)).to.eql('[{"id":1}]');
collection.length = 0;
expect(callsChange).to.eql([[{ added: [], removed: [model1] }, collection]]);
expect(callsRemove).to.eql([[model1, collection]]);
expect(collection.length).to.eql(0);
expect(JSON.stringify(collection)).to.eql('[]');
});
it('should set custom properties', () => {
const collection = new TestCollection();
const calls = [];
collection.on('change', (...args) => calls.push(args));
collection.on('add', (...args) => calls.push(args));
collection.on('remove', (...args) => calls.push(args));
collection.prop = 'val';
expect(collection.prop).to.eql('val');
expect(collection.length).to.eql(0);
expect(JSON.stringify(collection)).to.eql('[]');
expect(calls).to.eql([]);
});
it('should check types when setting items', () => {
const collection = new TestCollection();
expect(() => {
collection[0] = { id: 'bar' };
}).to.throw();
});
it('should set new items', () => {
const collection = new TestCollection();
const callsChange = [];
const callsAdd = [];
const callsRemove = [];
collection.on('change', (...args) => callsChange.push(args));
collection.on('add', (...args) => callsAdd.push(args));
collection.on('remove', (...args) => callsRemove.push(args));
const model = new TestModel(1);
collection[0] = model;
expect(collection.length).to.eql(1);
expect(JSON.stringify(collection)).to.eql('[{"id":1}]');
expect(callsChange).to.eql([[{ added: [model], removed: [] }, collection]]);
expect(callsAdd).to.eql([[model, collection]]);
expect(callsRemove).to.eql([]);
});
it('should set existing items', () => {
const model1 = new TestModel(1);
const model2 = new TestModel(2);
const collection = new TestCollection([model1, model2]);
const callsChange = [];
const callsAdd = [];
const callsRemove = [];
collection.on('change', (...args) => callsChange.push(args));
collection.on('add', (...args) => callsAdd.push(args));
collection.on('remove', (...args) => callsRemove.push(args));
expect(JSON.stringify(collection)).to.eql('[{"id":1},{"id":2}]');
const model3 = new TestModel(3);
collection[1] = model3;
expect(collection.length).to.eql(2);
expect(JSON.stringify(collection)).to.eql('[{"id":1},{"id":3}]');
expect(callsChange).to.eql([[{ added: [model3], removed: [model2] }, collection]]);
expect(callsAdd).to.eql([[model3, collection]]);
expect(callsRemove).to.eql([[model2, collection]]);
});
it('should get items by id', () => {
const model1 = new TestModel(1);
const model2 = new TestModel(2);
const collection = new TestCollection([model1, model2]);
expect(collection.get(1)).to.eql(model1);
expect(collection.get(2)).to.eql(model2);
expect(collection.get(3)).to.be.undefined;
});
it('should remove items', () => {
const model1 = new TestModel(1);
const model2 = new TestModel(2);
const collection = new TestCollection([model1, model2]);
const callsChange = [];
const callsRemove = [];
collection.on('change', (...args) => callsChange.push(args));
collection.on('remove', (...args) => callsRemove.push(args));
collection.remove(1);
expect(JSON.stringify(collection)).to.eql('[{"id":2}]');
expect(callsChange).to.eql([[{ added: [], removed: [model1] }, collection]]);
expect(callsRemove).to.eql([[model1, collection]]);
callsChange.length = 0;
callsRemove.length = 0;
collection.remove(model2);
expect(JSON.stringify(collection)).to.eql('[]');
expect(callsChange).to.eql([[{ added: [], removed: [model2] }, collection]]);
expect(callsRemove).to.eql([[model2, collection]]);
});
it('should sort items by comparator', () => {
const model1 = new TestModel(1);
const model2 = new TestModel(2);
const collection = new TestCollection([model1, model2]);
expect(JSON.stringify(collection)).to.eql('[{"id":1},{"id":2}]');
collection.comparator = (x, y) => x.id - y.id;
collection.sort();
expect(JSON.stringify(collection)).to.eql('[{"id":1},{"id":2}]');
collection.comparator = (x, y) => y.id - x.id;
collection.sort();
expect(JSON.stringify(collection)).to.eql('[{"id":2},{"id":1}]');
});
it('should splice items', () => {
const model1 = new TestModel(1);
const model2 = new TestModel(2);
const model3 = new TestModel(3);
const collection = new TestCollection([model1, model2, model3]);
const callsChange = [];
const callsAdd = [];
const callsRemove = [];
collection.on('change', (...args) => callsChange.push(args));
collection.on('add', (...args) => callsAdd.push(args));
collection.on('remove', (...args) => callsRemove.push(args));
expect(JSON.stringify(collection)).to.eql('[{"id":1},{"id":2},{"id":3}]');
const model4 = new TestModel(4);
const model5 = new TestModel(5);
const model6 = new TestModel(6);
collection.splice(1, 1, model4, model5, model6);
expect(collection.length).to.eql(5);
expect(JSON.stringify(collection)).to.eql('[{"id":1},{"id":4},{"id":5},{"id":6},{"id":3}]');
expect(callsChange).to.eql([
[{ added: [model4, model5, model6], removed: [model2] }, collection]
]);
expect(callsAdd).to.eql([[model4, collection], [model5, collection], [model6, collection]]);
expect(callsRemove).to.eql([[model2, collection]]);
});
});

View File

@ -11,6 +11,7 @@ const rootDir = path.join(__dirname, '..');
module.exports = {
mode: 'development',
devtool: 'source-map',
entry: path.resolve(__dirname, 'index.js'),
output: {
path: path.resolve(__dirname, 'dist'),
@ -22,5 +23,8 @@ module.exports = {
...appConfig.resolve.alias,
test: path.resolve(rootDir, 'test')
}
},
module: {
rules: appConfig.module.rules
}
};