Events implemented and tested, without buffering
This commit is contained in:
parent
92d7d61926
commit
a3d7e541d3
210
packages/xo-collection/collection.event.spec.js
Normal file
210
packages/xo-collection/collection.event.spec.js
Normal file
@ -0,0 +1,210 @@
|
||||
var chai = require('chai');
|
||||
var expect = chai.expect;
|
||||
var dirtyChai = require('dirty-chai');
|
||||
chai.use(dirtyChai);
|
||||
var leche = require('leche');
|
||||
var sinon = require('sinon');
|
||||
|
||||
var Collection = require('./collection');
|
||||
|
||||
var col = new Collection.Collection();
|
||||
|
||||
describe('collection events', function () {
|
||||
|
||||
// ============================================================
|
||||
|
||||
var data1 = {
|
||||
'primitive value': ['foo1', 1],
|
||||
'array value': ['bar1', [1,2]],
|
||||
'object value': ['baz1', {a:1, b:2}]
|
||||
};
|
||||
|
||||
var addSpy;
|
||||
var updateSpy;
|
||||
var removeSpy;
|
||||
|
||||
beforeEach(function () {
|
||||
|
||||
addSpy = sinon.spy();
|
||||
updateSpy = sinon.spy();
|
||||
removeSpy = sinon.spy();
|
||||
col.on('add', addSpy);
|
||||
col.on('update', updateSpy);
|
||||
col.on('remove', removeSpy);
|
||||
|
||||
});
|
||||
|
||||
afterEach(function () {
|
||||
|
||||
col.removeAllListeners();
|
||||
|
||||
});
|
||||
|
||||
// Collection is empty =======================================================
|
||||
|
||||
describe('add', function () {
|
||||
|
||||
leche.withData(data1, function (key, value) {
|
||||
|
||||
it('Emits an add event transporting the key and value', function () {
|
||||
expect(addSpy.called).to.be.false();
|
||||
expect(updateSpy.called).to.be.false();
|
||||
expect(removeSpy.called).to.be.false();
|
||||
|
||||
expect(col.add(key, value)).to.eql(col);
|
||||
expect(addSpy.called).to.be.true();
|
||||
expect(addSpy.calledWith({key: value})).to.be.true();
|
||||
|
||||
expect(updateSpy.called).to.be.false();
|
||||
expect(removeSpy.called).to.be.false();
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
var updateData1 = {
|
||||
'primitive value': ['foo1', 3],
|
||||
'array value': ['bar1', [3,4]],
|
||||
'object value': ['baz1', {c:2, d:4}]
|
||||
};
|
||||
|
||||
// Collection contains data1 =================================================
|
||||
|
||||
describe('update', function () {
|
||||
|
||||
leche.withData(updateData1, function (key, value) {
|
||||
|
||||
it('Emits an update event transporting the key and value', function () {
|
||||
expect(addSpy.called).to.be.false();
|
||||
expect(updateSpy.called).to.be.false();
|
||||
expect(removeSpy.called).to.be.false();
|
||||
|
||||
expect(col.update(key, value)).to.eql(col);
|
||||
expect(updateSpy.called).to.be.true();
|
||||
expect(updateSpy.calledWith({key: value})).to.be.true();
|
||||
|
||||
expect(addSpy.called).to.be.false();
|
||||
expect(removeSpy.called).to.be.false();
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
var data2 = {
|
||||
'primitive value': ['foo2', 1],
|
||||
'array value': ['bar2', [1,2]],
|
||||
'object value': ['baz2', {a:1, b:2}]
|
||||
};
|
||||
|
||||
// Collection contains data1 updated =========================================
|
||||
|
||||
describe('set', function () {
|
||||
|
||||
leche.withData(data1, function (key, value) {
|
||||
|
||||
it('Emits an update event for pre-existing keys', function () {
|
||||
expect(addSpy.called).to.be.false();
|
||||
expect(updateSpy.called).to.be.false();
|
||||
expect(removeSpy.called).to.be.false();
|
||||
|
||||
expect(col.update(key, value)).to.eql(col);
|
||||
expect(updateSpy.called).to.be.true();
|
||||
expect(updateSpy.calledWith({key: value})).to.be.true();
|
||||
|
||||
expect(addSpy.called).to.be.false();
|
||||
expect(removeSpy.called).to.be.false();
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
// Collection contains data1 =============================================
|
||||
|
||||
leche.withData(data2, function (key, value) {
|
||||
|
||||
it('Emits an add event for unexisting keys', function () {
|
||||
expect(addSpy.called).to.be.false();
|
||||
expect(updateSpy.called).to.be.false();
|
||||
expect(removeSpy.called).to.be.false();
|
||||
|
||||
expect(col.add(key, value)).to.eql(col);
|
||||
expect(addSpy.called).to.be.true();
|
||||
expect(addSpy.calledWith({key: value})).to.be.true();
|
||||
|
||||
expect(updateSpy.called).to.be.false();
|
||||
expect(removeSpy.called).to.be.false();
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
// Collection contains data1 & data 2 ========================================
|
||||
|
||||
describe('remove', function () {
|
||||
|
||||
leche.withData(data1, function (key, value) {
|
||||
|
||||
it('Emits an remove event transporting the key and removed value', function () {
|
||||
expect(addSpy.called).to.be.false();
|
||||
expect(updateSpy.called).to.be.false();
|
||||
expect(removeSpy.called).to.be.false();
|
||||
|
||||
expect(col.remove(key)).to.eql(col);
|
||||
expect(removeSpy.called).to.be.true();
|
||||
expect(removeSpy.calledWith({key: value})).to.be.true();
|
||||
|
||||
expect(addSpy.called).to.be.false();
|
||||
expect(updateSpy.called).to.be.false();
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
// Collection contains data 2 ================================================
|
||||
|
||||
describe('clear', function () {
|
||||
|
||||
var clearedData;
|
||||
|
||||
it('Emits a remove event', function() {
|
||||
expect(addSpy.called).to.be.false();
|
||||
expect(updateSpy.called).to.be.false();
|
||||
expect(removeSpy.called).to.be.false();
|
||||
|
||||
expect(col.clear()).to.eq(col);
|
||||
expect(removeSpy.calledOnce).to.be.true();
|
||||
|
||||
clearedData = removeSpy.lastCall.args[0];
|
||||
|
||||
expect(addSpy.called).to.be.false();
|
||||
expect(updateSpy.called).to.be.false();
|
||||
});
|
||||
|
||||
it('Emits no event if collection is empty', function() {
|
||||
expect(addSpy.called).to.be.false();
|
||||
expect(updateSpy.called).to.be.false();
|
||||
expect(removeSpy.called).to.be.false();
|
||||
|
||||
expect(col.clear()).to.eq(col);
|
||||
|
||||
expect(addSpy.called).to.be.false();
|
||||
expect(updateSpy.called).to.be.false();
|
||||
expect(removeSpy.called).to.be.false();
|
||||
});
|
||||
|
||||
leche.withData(data2, function (key, value) {
|
||||
|
||||
it('Emits a remove event with all cleared data', function () {
|
||||
|
||||
expect(clearedData[key]).to.eq(value);
|
||||
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
});
|
@ -1,4 +1,6 @@
|
||||
import makeError from 'make-error';
|
||||
import events from 'events';
|
||||
import _forEach from 'lodash.foreach';
|
||||
|
||||
const AlreadyBuffering = makeError('AlreadyBuffering');
|
||||
const NotBuffering = makeError('NotBuffering');
|
||||
@ -6,10 +8,12 @@ const IllegalAdd = makeError('IllegalAdd');
|
||||
const DuplicateEntry = makeError('DuplicateEntry');
|
||||
const NoSuchEntry = makeError('NoSuchEntry');
|
||||
|
||||
class Collection {
|
||||
class Collection extends events.EventEmitter {
|
||||
|
||||
constructor () {
|
||||
|
||||
super();
|
||||
|
||||
this._map = {};
|
||||
this._buffering = false;
|
||||
this._size = 0;
|
||||
@ -18,11 +22,7 @@ class Collection {
|
||||
|
||||
_initBuffer () {
|
||||
|
||||
this._buffer = {
|
||||
remove: [],
|
||||
add: [],
|
||||
update: []
|
||||
};
|
||||
this._buffer = {};
|
||||
|
||||
}
|
||||
|
||||
@ -50,25 +50,11 @@ class Collection {
|
||||
|
||||
}
|
||||
|
||||
_touch (key, action) {
|
||||
_touch (action, key, value) {
|
||||
|
||||
// TODO Buffers changes or emits an event
|
||||
// TODO enable buffering
|
||||
|
||||
}
|
||||
|
||||
_set (key, value) {
|
||||
|
||||
this._map[key] = value;
|
||||
this._touch(key, 'update');
|
||||
return this;
|
||||
|
||||
}
|
||||
|
||||
_unset (key) {
|
||||
|
||||
delete this._map[key];
|
||||
this._touch(key, 'remove');
|
||||
return this;
|
||||
this.emit(action, {key: value});
|
||||
|
||||
}
|
||||
|
||||
@ -127,9 +113,13 @@ class Collection {
|
||||
const [key, value] = this.resolveEntry.apply(this, arguments);
|
||||
|
||||
this._assertHasNot(key);
|
||||
this._size++;
|
||||
|
||||
return this._set(key, value);
|
||||
this._map[key] = value;
|
||||
|
||||
this._size++;
|
||||
this._touch('add', key, value);
|
||||
|
||||
return this;
|
||||
|
||||
}
|
||||
|
||||
@ -137,11 +127,15 @@ class Collection {
|
||||
|
||||
const [key, value] = this.resolveEntry.apply(this, arguments);
|
||||
|
||||
if (!this.has(key)) {
|
||||
const action = this.has(key) ? 'update' : 'add';
|
||||
this._map[key] = value;
|
||||
if ('add' === action) {
|
||||
this._size++;
|
||||
}
|
||||
|
||||
return this._set(key, value);
|
||||
this._touch(action, key, value);
|
||||
|
||||
return this;
|
||||
|
||||
}
|
||||
|
||||
@ -158,7 +152,10 @@ class Collection {
|
||||
|
||||
this._assertHas(key);
|
||||
|
||||
return this._set(key, value);
|
||||
this._map[key] = value;
|
||||
this._touch('update', key, value);
|
||||
|
||||
return this;
|
||||
|
||||
}
|
||||
|
||||
@ -167,9 +164,27 @@ class Collection {
|
||||
const [key] = this.resolveEntry(keyOrObjectWithId, null);
|
||||
|
||||
this._assertHas(key);
|
||||
|
||||
const oldValue = this.get(key);
|
||||
delete this._map[key];
|
||||
this._size--;
|
||||
|
||||
return this._unset(key);
|
||||
this._touch('remove', key, oldValue);
|
||||
|
||||
return this;
|
||||
|
||||
}
|
||||
|
||||
clear () {
|
||||
|
||||
if (this._size > 0) {
|
||||
this.emit('remove', this._map);
|
||||
}
|
||||
|
||||
this._map = {};
|
||||
this._size = 0;
|
||||
|
||||
return this;
|
||||
|
||||
}
|
||||
|
||||
|
@ -4,17 +4,15 @@ var dirtyChai = require('dirty-chai');
|
||||
chai.use(dirtyChai);
|
||||
var leche = require('leche');
|
||||
|
||||
console.log(expect);
|
||||
|
||||
var Collection = require('./collection');
|
||||
|
||||
var col = new Collection.Collection();
|
||||
|
||||
describe('collection', function () {
|
||||
|
||||
// ============================================================
|
||||
// Collection is empty =======================================================
|
||||
|
||||
var fixtureValues1 = {
|
||||
var data1 = {
|
||||
'primitive value': ['foo1', 1],
|
||||
'array value': ['bar1', [1,2]],
|
||||
'object value': ['baz1', {a:1, b:2}]
|
||||
@ -22,7 +20,7 @@ describe('collection', function () {
|
||||
|
||||
describe('add', function () {
|
||||
|
||||
leche.withData(fixtureValues1, function (key, value) {
|
||||
leche.withData(data1, function (key, value) {
|
||||
|
||||
it('Adds a new entry to the collection', function () {
|
||||
expect(col.add(key, value)).to.eql(col);
|
||||
@ -30,7 +28,7 @@ describe('collection', function () {
|
||||
|
||||
});
|
||||
|
||||
leche.withData(fixtureValues1, function (key, value) {
|
||||
leche.withData(data1, function (key, value) {
|
||||
|
||||
it('We cannot add on a pre-existing key', function () {
|
||||
expect(function () {
|
||||
@ -42,9 +40,9 @@ describe('collection', function () {
|
||||
|
||||
});
|
||||
|
||||
// ============================================================
|
||||
// Collection contains data 1 ================================================
|
||||
|
||||
var fixtureValues2 = {
|
||||
var data2 = {
|
||||
'primitive value': ['foo2', 1],
|
||||
'array value': ['bar2', [1,2]],
|
||||
'object value': ['baz2', {a:1, b:2}]
|
||||
@ -52,7 +50,7 @@ describe('collection', function () {
|
||||
|
||||
describe('set', function () {
|
||||
|
||||
leche.withData(fixtureValues2, function (key, value) {
|
||||
leche.withData(data2, function (key, value) {
|
||||
|
||||
it('Sets an entry of the collection...', function () {
|
||||
expect(col.set(key, value)).to.eql(col);
|
||||
@ -60,7 +58,7 @@ describe('collection', function () {
|
||||
|
||||
});
|
||||
|
||||
leche.withData(fixtureValues2, function (key, value) {
|
||||
leche.withData(data2, function (key, value) {
|
||||
|
||||
it('...would it already exists or not', function () {
|
||||
expect(col.set(key, value)).to.eql(col);
|
||||
@ -70,15 +68,15 @@ describe('collection', function () {
|
||||
|
||||
});
|
||||
|
||||
// ============================================================
|
||||
// Collection contains data 1 & 2 ============================================
|
||||
|
||||
var fixtureUnexisting = {
|
||||
var unexistingData = {
|
||||
'Unexisting key/entry': ['wat', 'any']
|
||||
};
|
||||
|
||||
describe('get', function () {
|
||||
|
||||
leche.withData(fixtureValues1, function (key, value) {
|
||||
leche.withData(data1, function (key, value) {
|
||||
|
||||
it('Returns the value of an entry of the collection...', function () {
|
||||
expect(col.get(key)).to.eql(value);
|
||||
@ -86,7 +84,7 @@ describe('collection', function () {
|
||||
|
||||
});
|
||||
|
||||
leche.withData(fixtureValues2, function (key, value) {
|
||||
leche.withData(data2, function (key, value) {
|
||||
|
||||
it('Returns the value of an entry of the collection...', function () {
|
||||
expect(col.get(key)).to.eql(value);
|
||||
@ -94,7 +92,7 @@ describe('collection', function () {
|
||||
|
||||
});
|
||||
|
||||
leche.withData(fixtureUnexisting, function (key) {
|
||||
leche.withData(unexistingData, function (key) {
|
||||
|
||||
it('...or throws if it does not exist', function () {
|
||||
expect(function () {
|
||||
@ -106,9 +104,9 @@ describe('collection', function () {
|
||||
|
||||
});
|
||||
|
||||
// ============================================================
|
||||
// Collection contains data 1 & 2 ============================================
|
||||
|
||||
var fixtureUpdates = {
|
||||
var updateData2 = {
|
||||
'primitive value': ['foo2', 3],
|
||||
'array value': ['bar2', [3,4]],
|
||||
'object value': ['baz2', {c:3, d:4}]
|
||||
@ -116,7 +114,7 @@ describe('collection', function () {
|
||||
|
||||
describe('update', function () {
|
||||
|
||||
leche.withData(fixtureUpdates, function (key, value) {
|
||||
leche.withData(updateData2, function (key, value) {
|
||||
|
||||
it('updates the given entries...', function () {
|
||||
expect(col.update(key, value)).to.eql(col);
|
||||
@ -124,7 +122,7 @@ describe('collection', function () {
|
||||
|
||||
});
|
||||
|
||||
leche.withData(fixtureUpdates, function (key, value) {
|
||||
leche.withData(updateData2, function (key, value) {
|
||||
|
||||
it('...so we can see the values we get have changed accordingly', function () {
|
||||
expect(col.get(key)).to.eql(value);
|
||||
@ -132,7 +130,7 @@ describe('collection', function () {
|
||||
|
||||
});
|
||||
|
||||
leche.withData(fixtureUnexisting, function (key, value) {
|
||||
leche.withData(unexistingData, function (key, value) {
|
||||
|
||||
it('If the entry does not exist, updating throws', function () {
|
||||
expect(function () {
|
||||
@ -144,11 +142,11 @@ describe('collection', function () {
|
||||
|
||||
});
|
||||
|
||||
// ============================================================
|
||||
// Collection contains data 1 & 2 updated ====================================
|
||||
|
||||
describe('remove', function () {
|
||||
|
||||
leche.withData(fixtureValues2, function (key) {
|
||||
leche.withData(data2, function (key) {
|
||||
|
||||
it('removes the given entries...', function () {
|
||||
expect(col.remove(key)).to.eql(col);
|
||||
@ -156,7 +154,7 @@ describe('collection', function () {
|
||||
|
||||
});
|
||||
|
||||
leche.withData(fixtureValues2, function (key) {
|
||||
leche.withData(data2, function (key) {
|
||||
|
||||
it('...so trying to get them again throws...', function () {
|
||||
expect(function () {
|
||||
@ -166,7 +164,7 @@ describe('collection', function () {
|
||||
|
||||
});
|
||||
|
||||
leche.withData(fixtureValues2, function (key) {
|
||||
leche.withData(data2, function (key) {
|
||||
|
||||
it('...and trying to remove them again also throws', function () {
|
||||
expect(function () {
|
||||
@ -178,11 +176,11 @@ describe('collection', function () {
|
||||
|
||||
});
|
||||
|
||||
// ============================================================
|
||||
// Collection contains data 1 ================================================
|
||||
|
||||
describe('has', function () {
|
||||
|
||||
leche.withData(fixtureValues1, function (key) {
|
||||
leche.withData(data1, function (key) {
|
||||
|
||||
it('Tells us if an entry exists...', function () {
|
||||
expect(col.has(key)).to.be.true();
|
||||
@ -190,7 +188,7 @@ describe('collection', function () {
|
||||
|
||||
});
|
||||
|
||||
leche.withData(fixtureValues2, function (key) {
|
||||
leche.withData(data2, function (key) {
|
||||
|
||||
it('...or not', function () {
|
||||
expect(col.has(key)).to.be.false();
|
||||
@ -200,21 +198,21 @@ describe('collection', function () {
|
||||
|
||||
});
|
||||
|
||||
// ============================================================
|
||||
// Collection contains data 1 ================================================
|
||||
|
||||
describe('size', function () {
|
||||
|
||||
it('Reveals the number of existing entries', function () {
|
||||
expect(col.size).to.eq(Object.keys(fixtureValues1).length);
|
||||
expect(col.size).to.eq(Object.keys(data1).length);
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
// ============================================================
|
||||
// Collection contains data 1 ================================================
|
||||
|
||||
describe('all', function () {
|
||||
|
||||
leche.withData(fixtureValues1, function (key, value) {
|
||||
leche.withData(data1, function (key, value) {
|
||||
|
||||
it('Gives access to the internal collection...', function () {
|
||||
expect(col.all).to.have.ownProperty(key);
|
||||
@ -223,7 +221,7 @@ describe('collection', function () {
|
||||
|
||||
});
|
||||
|
||||
leche.withData(fixtureValues2, function (key) {
|
||||
leche.withData(data2, function (key) {
|
||||
|
||||
it('Gives access to the internal collection...', function () {
|
||||
expect(col.all).to.not.have.ownProperty(key);
|
||||
@ -238,4 +236,17 @@ describe('collection', function () {
|
||||
|
||||
});
|
||||
|
||||
// Collection contains data 1 ================================================
|
||||
|
||||
describe('clear', function () {
|
||||
|
||||
it('wipes out all the collection', function () {
|
||||
expect(col.clear()).to.eq(col);
|
||||
|
||||
expect(col.size).to.eq(0);
|
||||
expect(col.all).to.eql({});
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
});
|
@ -4,6 +4,7 @@
|
||||
"description": "A generice batch collection attempt",
|
||||
"main": "collection.js",
|
||||
"dependencies": {
|
||||
"lodash.foreach": "^3.0.2",
|
||||
"make-error": "^0.3.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
@ -11,7 +12,8 @@
|
||||
"chai": "^2.2.0",
|
||||
"dirty-chai": "^1.2.0",
|
||||
"leche": "^2.1.1",
|
||||
"mocha": "^2.2.1"
|
||||
"mocha": "^2.2.1",
|
||||
"sinon": "^1.14.1"
|
||||
},
|
||||
"scripts": {
|
||||
"test": "mocha --require babel/register *.spec.js"
|
||||
|
Loading…
Reference in New Issue
Block a user