UNPKG

eventric

Version:

Build JavaScript applications with Behaviour-driven Domain Design. Based on DDD, BDD, CQRS and EventSourcing.

334 lines (309 loc) 13.1 kB
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']); }); }); }); }); });