eventric
Version:
Build JavaScript applications with Behaviour-driven Domain Design. Based on DDD, BDD, CQRS and EventSourcing.
334 lines (309 loc) • 13.1 kB
JavaScript
describe('Remote Projection Feature', function() {
var exampleContext;
exampleContext = null;
beforeEach(function() {
var Example;
exampleContext = eventric.context('Example');
exampleContext.defineDomainEvents({
ExampleCreated: function() {},
ExampleUpdated: function() {}
});
exampleContext.addCommandHandlers({
CreateExample: function(params, callback) {
return this.$repository('Example').create().then((function(_this) {
return function(exampleId) {
return _this.$repository('Example').save(exampleId);
};
})(this)).then(function(exampleId) {
return callback(null, exampleId);
});
},
UpdateExample: function(params, callback) {
return this.$repository('Example').findById(params.id).then((function(_this) {
return function(example) {
example.update();
return _this.$repository('Example').save(params.id);
};
})(this)).then(function() {
return callback();
});
}
});
Example = (function() {
function Example() {}
Example.prototype.create = function(callback) {
this.$emitDomainEvent('ExampleCreated');
return callback();
};
Example.prototype.update = function() {
return this.$emitDomainEvent('ExampleUpdated');
};
return Example;
})();
exampleContext.addAggregate('Example', Example);
return exampleContext.initialize().then(function() {
return exampleContext.enableWaitingMode();
});
});
return describe('given we created and initialized some example context', function() {
describe('when we add a projection to the remote', function() {
var exampleRemote, projectionId;
projectionId = null;
exampleRemote = null;
beforeEach(function() {
var ExampleProjection;
exampleRemote = eventric.remote('Example');
ExampleProjection = (function() {
function ExampleProjection() {}
ExampleProjection.prototype.initialize = function(params, done) {
return done();
};
ExampleProjection.prototype.handleExampleCreated = function(domainEvent) {
return this.created = true;
};
ExampleProjection.prototype.handleToCheckCorrectFunctionCall = function(domainEvent) {};
return ExampleProjection;
})();
exampleRemote.addProjection('ExampleProjection', ExampleProjection);
return exampleRemote.initializeProjectionInstance('ExampleProjection').then(function(_projectionId) {
return projectionId = _projectionId;
});
});
it('then the projection should update its state as expected', function() {
return exampleRemote.command('CreateExample').then(function() {
var exampleProjection;
exampleProjection = exampleRemote.getProjectionInstance(projectionId);
return expect(exampleProjection.created).to.be["true"];
});
});
return it('then we should be able to remove it', function() {
sandbox.spy(exampleRemote, 'unsubscribeFromDomainEvent');
exampleRemote.destroyProjectionInstance(projectionId);
expect(exampleRemote.getProjectionInstance(projectionId)).to.be.undefined;
return expect(exampleRemote.unsubscribeFromDomainEvent).to.have.been.called;
});
});
describe('when we initialize a projection as object on the remote', function() {
var exampleRemote, projectionId;
projectionId = null;
exampleRemote = null;
beforeEach(function() {
exampleRemote = eventric.remote('Example');
return exampleRemote.initializeProjection({
initialize: function(params, done) {
return done();
},
handleExampleCreated: function(domainEvent) {
return this.created = true;
},
handleToCheckCorrectFunctionCall: function(domainEvent) {}
}).then(function(_projectionId) {
return projectionId = _projectionId;
});
});
return it('then the projection should update its state as expected', function() {
return exampleRemote.command('CreateExample').then(function() {
var exampleProjection;
exampleProjection = exampleRemote.getProjectionInstance(projectionId);
return expect(exampleProjection.created).to.be["true"];
});
});
});
describe('when we add a remote projection to the remote which subscribes to a specific aggregate', function() {
var exampleRemote, projectionId;
exampleRemote = null;
projectionId = null;
beforeEach(function() {
var ExampleProjection;
exampleRemote = eventric.remote('Example');
ExampleProjection = (function() {
function ExampleProjection() {}
ExampleProjection.prototype.initialize = function(params, done) {
this.$subscribeHandlersWithAggregateId(params.aggregateId);
return done();
};
ExampleProjection.prototype.handleExampleUpdated = function(domainEvent) {
return this.updated = true;
};
return ExampleProjection;
})();
return exampleRemote.addProjection('ExampleProjection', ExampleProjection);
});
it('then should update the remote projection as expected', function() {
var testExampleId;
testExampleId = null;
return exampleRemote.command('CreateExample').then(function(exampleId) {
testExampleId = exampleId;
return exampleRemote.initializeProjectionInstance('ExampleProjection', {
aggregateId: exampleId
});
}).then(function(_projectionId) {
projectionId = _projectionId;
return exampleRemote.command('CreateExample');
}).then(function(exampleId) {
return exampleRemote.command('UpdateExample', {
id: exampleId
});
}).then(function() {
var exampleProjection;
exampleProjection = exampleRemote.getProjectionInstance(projectionId);
expect(exampleProjection.updated).not.to.be["true"];
return exampleRemote.command('UpdateExample', {
id: testExampleId
});
}).then(function() {
var exampleProjection;
exampleProjection = exampleRemote.getProjectionInstance(projectionId);
return expect(exampleProjection.updated).to.be["true"];
});
});
it('then should publish an event whenever a remote projection is updated', function(done) {
var testExampleId;
testExampleId = null;
return exampleRemote.command('CreateExample').then(function(exampleId) {
testExampleId = exampleId;
return exampleRemote.initializeProjectionInstance('ExampleProjection', {
aggregateId: exampleId
});
}).then(function(projectionId) {
var exampleProjection;
exampleProjection = exampleRemote.getProjectionInstance(projectionId);
exampleRemote.subscribe('projection:ExampleProjection:changed', function() {
return done();
});
return exampleRemote.command('UpdateExample', {
id: testExampleId
});
});
});
return it('then we should be able to remove it', function() {
return exampleRemote.initializeProjectionInstance('ExampleProjection', {
aggregateId: '123'
}).then(function(projectionId) {
sandbox.spy(exampleRemote, 'unsubscribeFromDomainEvent');
exampleRemote.destroyProjectionInstance(projectionId);
expect(exampleRemote.getProjectionInstance(projectionId)).to.be.undefined;
return expect(exampleRemote.unsubscribeFromDomainEvent).to.have.been.called;
});
});
});
describe('when we add a remote projection and already have domain events for it', function() {
var exampleRemote;
exampleRemote = null;
beforeEach(function() {
var ExampleProjection;
exampleRemote = eventric.remote('Example');
ExampleProjection = (function() {
function ExampleProjection() {
this.exampleCount = 0;
}
ExampleProjection.prototype.handleExampleCreated = function() {
return this.exampleCount++;
};
return ExampleProjection;
})();
return exampleRemote.addProjection('ExampleProjection', ExampleProjection);
});
return it('then it should apply the already existing domain events immediately to the projection', function() {
return exampleContext.command('CreateExample').then(function(id) {
return exampleRemote.initializeProjectionInstance('ExampleProjection');
}).then(function(projectionId) {
var projection;
projection = exampleRemote.getProjectionInstance(projectionId);
return expect(projection.exampleCount).to.equal(1);
});
});
});
describe('when we add a remote projection for a specific aggregate id and have domain events for it', function() {
var exampleRemote;
exampleRemote = null;
beforeEach(function() {
var ExampleProjection;
exampleRemote = eventric.remote('Example');
ExampleProjection = (function() {
function ExampleProjection() {
this.updated = false;
}
ExampleProjection.prototype.initialize = function(params, done) {
this.$subscribeHandlersWithAggregateId(params.aggregateId);
return done();
};
ExampleProjection.prototype.handleExampleUpdated = function() {
return this.updated = true;
};
return ExampleProjection;
})();
return exampleRemote.addProjection('ExampleProjection', ExampleProjection);
});
it('then it should apply the already existing domain events immediately to the projection', function() {
return exampleContext.command('CreateExample').then(function(exampleId) {
return exampleContext.command('UpdateExample', {
id: exampleId
});
}).then(function(exampleId) {
return exampleRemote.initializeProjectionInstance('ExampleProjection', {
aggregateId: exampleId
});
}).then(function(projectionId) {
var projection;
projection = exampleRemote.getProjectionInstance(projectionId);
return expect(projection.updated).to.be["true"];
});
});
return it('then it should only apply the already existing domain events for the specific aggregate', function() {
var firstExampleId;
firstExampleId = null;
return exampleContext.command('CreateExample').then(function(_firstExampleId) {
firstExampleId = _firstExampleId;
return exampleContext.command('CreateExample');
}).then(function(secondExampleId) {
return exampleContext.command('UpdateExample', {
id: secondExampleId
});
}).then(function() {
return exampleRemote.initializeProjectionInstance('ExampleProjection', {
aggregateId: firstExampleId
});
}).then(function(projectionId) {
var projection;
projection = exampleRemote.getProjectionInstance(projectionId);
return expect(projection.updated).to.be["false"];
});
});
});
return describe('when we add a remote projection and already have multiple domain events for it', function() {
var exampleRemote;
exampleRemote = null;
beforeEach(function() {
var ExampleProjection;
exampleRemote = eventric.remote('Example');
ExampleProjection = (function() {
function ExampleProjection() {
this.events = [];
}
ExampleProjection.prototype.handleExampleCreated = function(domainEvent) {
return this.events.push(domainEvent.name);
};
ExampleProjection.prototype.handleExampleUpdated = function(domainEvent) {
return this.events.push(domainEvent.name);
};
return ExampleProjection;
})();
return exampleRemote.addProjection('ExampleProjection', ExampleProjection);
});
return it('then it should apply the already existing domain events in the correct order', function() {
return exampleContext.command('CreateExample').then(function(id) {
return exampleContext.command('UpdateExample', {
id: id
});
}).then(function(id) {
return exampleRemote.initializeProjectionInstance('ExampleProjection');
}).then(function(projectionId) {
var projection;
projection = exampleRemote.getProjectionInstance(projectionId);
return expect(projection.events).to.deep.equal(['ExampleCreated', 'ExampleUpdated']);
});
});
});
});
});