From 73c87889129af3548a83c543a98d6fbd73acdf00 Mon Sep 17 00:00:00 2001 From: Valentin Andruschenko Date: Mon, 23 Apr 2018 21:51:45 +0300 Subject: [PATCH] Issue #49: high-level API tests --- src/modules/EventuateClient.js | 4 - test/AggregateRepositoryEncryption-spec.js | 328 +++++++++++++++++++++ test/Encryption-spec.js | 2 +- test/EventuateClientEncryption-spec.js | 2 +- test/lib/helpers.js | 4 +- test/subscribeEncrypted-spec.js | 3 +- 6 files changed, 333 insertions(+), 10 deletions(-) create mode 100644 test/AggregateRepositoryEncryption-spec.js diff --git a/src/modules/EventuateClient.js b/src/modules/EventuateClient.js index 9299799..80e4d14 100644 --- a/src/modules/EventuateClient.js +++ b/src/modules/EventuateClient.js @@ -106,9 +106,7 @@ export default class EventuateClient { if (encryptionKeyId && this.encryption) { // Encrypt event data; - console.log('events:', util.inspect(events)); events = this.encryptEvens(encryptionKeyId, events); - console.log('encrypted events:', events); } const jsonData = { entityTypeName, events }; @@ -199,9 +197,7 @@ export default class EventuateClient { let events = this.prepareEvents(_events); if (encryptionKeyId && this.encryption) { // Encrypt event data; - console.log('events:', util.inspect(events)); events = this.encryptEvens(encryptionKeyId, events); - console.log('encrypted events:', events); } const jsonData = { entityId, diff --git a/test/AggregateRepositoryEncryption-spec.js b/test/AggregateRepositoryEncryption-spec.js new file mode 100644 index 0000000..cc657cf --- /dev/null +++ b/test/AggregateRepositoryEncryption-spec.js @@ -0,0 +1,328 @@ +'use strict'; +const { expect } = require('chai'); +const helpers = require('./lib/helpers'); +const { AggregateRepository, EventuateSubscriptionManager } = require('../dist'); +const { Executor: ExecutorClass, HandlersManager, createEventuateClient } = helpers; +const executor = new ExecutorClass(); +const Encryption = require('../dist/modules/Encryption'); + +const { entityTypeName, anotherEntityTypeName, MyEntityWasCreatedEvent, MyEntityWasUpdatedEvent } = require('./lib/eventConfig'); + +const EntityClass = require('./lib/EntityClass'); +const { CreatedEntityCommand, UpdateEntityCommand, FailureCommand } = EntityClass; +const encryptionKeyId = 'id'; +const keySecret = 'secret'; +const encryptionKeyStore = { [encryptionKeyId]: keySecret }; +const encryption = new Encryption(encryptionKeyStore); + +const eventuateClient = createEventuateClient(encryption); +const aggregateRepository = new AggregateRepository({ eventuateClient, EntityClass }); +const subscriptionManager = new EventuateSubscriptionManager({ eventuateClient }); + +const timeout = 20000; + +let createdTimestamp; +let updateTimestamp; + +let entityId; +let myEntityWasCreatedEventId; +let myEntityWasUpdatedEventId; +let version; + +describe('AggregateRepository', function () { + this.timeout(timeout); + + it('function createEntity() should return entityAndEventInfo object', done => { + createdTimestamp = new Date().getTime(); + const command = { + commandType: CreatedEntityCommand, + createdTimestamp + }; + + aggregateRepository.createEntity({ EntityClass, command, options: { encryptionKeyId } }) + .then(createdEntityAndEventInfo => { + helpers.expectCommandResult(createdEntityAndEventInfo); + entityId = createdEntityAndEventInfo.entityIdTypeAndVersion.entityId; + myEntityWasCreatedEventId = createdEntityAndEventInfo.eventIds[0]; + done(); + }) + .catch(done); + }); + + it('function createEntity() should try to run FailureCommand and get error', done => { + const command = { commandType: FailureCommand }; + + aggregateRepository.createEntity({ EntityClass, command, options: { encryptionKeyId } }) + .then(() => { + done(new Error('Command FailureCommand should return error')); + }) + .catch(err => { + console.log(err); + done(); + }); + }); + + it('function updateEntity() should update entity and return entityAndEventInfo object', done => { + expect(entityId).to.be.ok; + + updateTimestamp = new Date().getTime(); + const command = { + commandType: UpdateEntityCommand, + updateTimestamp + }; + + aggregateRepository.updateEntity({ EntityClass, entityId, command, options: { encryptionKeyId } }) + .then(updatedEntityAndEventInfo => { + helpers.expectCommandResult(updatedEntityAndEventInfo); + myEntityWasUpdatedEventId = updatedEntityAndEventInfo.eventIds[0]; + done(); + }) + .catch(done); + }); + + it('function updateEntity() should try to update not existing entity and return error with code 404', done => { + const command = { + commandType: UpdateEntityCommand, + updateTimestamp + }; + + aggregateRepository.updateEntity({ EntityClass, entityId: '0000000000000001', command, options: { encryptionKeyId } }) + .then(() => { + done(new Error('Should return error!')); + }) + .catch((err) => { + expect(err).to.be.an('Object'); + expect(err).to.haveOwnProperty('code'); + expect(err.code).to.equal(404); + expect(err).to.haveOwnProperty('message'); + expect(err.message).to.be.a('String'); + done(); + }); + }); + + it('function updateEntity() should try to run FailureCommand and get error', done => { + expect(entityId).to.be.ok; + const command = { commandType: FailureCommand }; + + aggregateRepository.updateEntity({ entityId, EntityClass, command, options: { encryptionKeyId } }) + .then(() => done(new Error('Command FailureCommand should return error'))) + .catch(err => { + console.log(err); + done(); + }); + }); + + it('function loadEvents() should load events', done => { + expect(entityId).to.be.ok; + const entity = new EntityClass(); + + aggregateRepository.loadEvents({ entityTypeName, entityId, options: { encryptionKeyId } }) + .then(loadedEvents => { + helpers.expectLoadedEvents(loadedEvents); + + expect(loadedEvents.length).to.equal(2); + expect(loadedEvents[0].eventData.timestamp).to.equal(createdTimestamp); + expect(loadedEvents[1].eventData.timestamp).to.equal(updateTimestamp); + + version = loadedEvents[0].id; + + done(); + + describe('Test getApplyMethod() method', function () { + it('should return a function', () => { + + loadedEvents.forEach(event => { + const type = event.eventType.split('.').pop(); + const applyMethod = aggregateRepository.getApplyMethod(entity, type); + expect(applyMethod).to.be.a('Function'); + }); + + //check default applyEvent() method + const type = 'UnknownEventType'; + const applyMethod = aggregateRepository.getApplyMethod(entity, type); + expect(applyMethod).to.be.a('Function'); + }); + + }); + + describe('Test getProcessCommandMethod() method', function () { + it('should return a function', () => { + + let processCommandMethod = aggregateRepository.getProcessCommandMethod(entity, CreatedEntityCommand); + expect(processCommandMethod).to.be.a('Function'); + + processCommandMethod = aggregateRepository.getProcessCommandMethod(entity, UpdateEntityCommand); + expect(processCommandMethod).to.be.a('Function'); + //check default processCommand() method + processCommandMethod = aggregateRepository.getProcessCommandMethod(entity, 'unknownCommand'); + expect(processCommandMethod).to.be.a('Function'); + }); + }); + }) + .catch(done); + }); + + it('Method find() should return updated Aggregate instance', done => { + aggregateRepository.find({ EntityClass, entityId, options: { encryptionKeyId } }) + .then(entity => { + expect(entity).to.be.instanceOf(EntityClass); + expect(entity.timestamp).to.equal(updateTimestamp); + done(); + }) + .catch(done) + }); + + it('Method find() should return updated Aggregate instance for a version', done => { + expect(version).to.be.ok; + aggregateRepository.find({ EntityClass, entityId, options: { version, encryptionKeyId } }) + .then(entity => { + expect(entity).to.be.instanceOf(EntityClass); + expect(entity.timestamp).to.equal(createdTimestamp); + done(); + }) + .catch(done) + }); + + it('Method find() should return "false" for not existing entityId', done => { + const entityId = new Date().getTime().toString(); + aggregateRepository.find({ EntityClass, entityId, options: { encryptionKeyId } }) + .then(entity => { + expect(entity).to.be.equal(false); + done(); + }) + .catch(done); + }); +}); + +describe('EventuateSubscriptionManager', function () { + this.timeout(timeout); + + it('should subscribe two subscribers and receive events', done => { + const handlersManager = new HandlersManager({ done }); + + const handleMyEntityWasCreatedEvent = helpers.createEventHandler((event) => { + console.log('handleMyEntityWasCreatedEvent()'); + expect(event.eventType).to.equal(MyEntityWasCreatedEvent); + + if (myEntityWasCreatedEventId === event.eventId) { + handlersManager.setCompleted('handleMyEntityWasCreatedEvent'); + } + }); + + const handleMyEntityWasUpdatedEvent = helpers.createEventHandler((event) => { + console.log('handleMyEntityWasUpdatedEvent()'); + expect(event.eventType).to.equal(MyEntityWasUpdatedEvent); + + if (myEntityWasUpdatedEventId === event.eventId) { + handlersManager.setCompleted('handleMyEntityWasUpdatedEvent'); + } else { + console.log('Old event'); + } + }); + + handlersManager.setHandlers([ 'handleMyEntityWasCreatedEvent', 'handleMyEntityWasUpdatedEvent' ]); + + const entityCreatedEventHandlers = { + [entityTypeName]: { + [MyEntityWasCreatedEvent]: handleMyEntityWasCreatedEvent + } + }; + + const entityUpdatedEventHandlers = { + [entityTypeName]: { + [MyEntityWasUpdatedEvent]: handleMyEntityWasUpdatedEvent + } + }; + + subscriptionManager.subscribe({ + subscriberId: 'test-AggregateRepository-subscriber1', + eventHandlers: entityCreatedEventHandlers, + executor + }); + + subscriptionManager.subscribe({ + subscriberId: 'test-AggregateRepository-subscriber2', + eventHandlers: entityUpdatedEventHandlers, + executor + }); + }); + + it('should create entity with 10 events and subscribe', done => { + let processedEventsNumber1 = 0; + let processedEventsNumber2 = 0; + const expectedEventsNumber = 10; + let myEntityWasCreatedEventIds = []; + + const handlersManager = new HandlersManager({ done }); + const handleMyEntityWasCreatedEvent1 = helpers.createEventHandler((event) => { + + expect(event.eventType).to.equal(MyEntityWasCreatedEvent); + + if (myEntityWasCreatedEventIds.indexOf(event.eventId) >= 0) { + processedEventsNumber1++; + if (processedEventsNumber1 === expectedEventsNumber) { + console.log(`handleMyEntityWasCreatedEvent1() processed ${processedEventsNumber1} events`); + handlersManager.setCompleted('handleMyEntityWasCreatedEvent1'); + } + } else { + console.log('Old event') + } + }); + + const handleMyEntityWasCreatedEvent2 = helpers.createEventHandler((event) => { + + expect(event.eventType).to.equal(MyEntityWasCreatedEvent); + + if (myEntityWasCreatedEventIds.indexOf(event.eventId) >= 0) { + processedEventsNumber2++; + if (processedEventsNumber2 === expectedEventsNumber) { + console.log(`handleMyEntityWasCreatedEvent2() processed ${processedEventsNumber2} events`); + handlersManager.setCompleted('handleMyEntityWasCreatedEvent2'); + } + } else { + console.log('Old event') + } + }); + + handlersManager.setHandlers([ 'handleMyEntityWasCreatedEvent1', 'handleMyEntityWasCreatedEvent2' ]); + + const entityCreatedEventHandlers1 = { + [anotherEntityTypeName]: { + [MyEntityWasCreatedEvent]: handleMyEntityWasCreatedEvent1 + } + }; + + subscriptionManager.subscribe({ + subscriberId: 'test-SubscriptionManager-subscriber1', + eventHandlers: entityCreatedEventHandlers1, + executor + }); + + const entityCreatedEventHandlers2 = { + [anotherEntityTypeName]: { + [MyEntityWasCreatedEvent]: handleMyEntityWasCreatedEvent2 + } + }; + + subscriptionManager.subscribe({ + subscriberId: 'test-SubscriptionManager-subscriber2', + eventHandlers: entityCreatedEventHandlers2, + executor + }); + + const events = helpers.makeEventsArr({ size: expectedEventsNumber, entityType: anotherEntityTypeName, eventType: MyEntityWasCreatedEvent }); + + setTimeout(() => { + eventuateClient.create(anotherEntityTypeName, events, { encryptionKeyId }) + .then(createdEntityAndEventInfo => { + console.log('Entity created'); + console.log(createdEntityAndEventInfo); + + myEntityWasCreatedEventIds = myEntityWasCreatedEventIds.concat(createdEntityAndEventInfo.eventIds); + console.log('myEntityWasCreatedEventIds:', myEntityWasCreatedEventIds); + helpers.expectCommandResult(createdEntityAndEventInfo); + }) + .catch(done); + }, 2000); + }); +}); diff --git a/test/Encryption-spec.js b/test/Encryption-spec.js index 3398b2e..70187ad 100644 --- a/test/Encryption-spec.js +++ b/test/Encryption-spec.js @@ -1,6 +1,6 @@ 'use strict'; const { expect } = require('chai'); -const Encryption = require('../src/modules/Encryption'); +const Encryption = require('../dist/modules/Encryption'); const keyId = 'id'; const keySecret = 'secret'; diff --git a/test/EventuateClientEncryption-spec.js b/test/EventuateClientEncryption-spec.js index b8bcb5c..e5f83fb 100644 --- a/test/EventuateClientEncryption-spec.js +++ b/test/EventuateClientEncryption-spec.js @@ -2,7 +2,7 @@ const expect = require('chai').expect; const helpers = require('./lib/helpers'); const uuid = require('uuid'); -const Encryption = require('../src/modules/Encryption'); +const Encryption = require('../dist/modules/Encryption'); const encryptionKeyId = 'id'; const keySecret = 'secret'; diff --git a/test/lib/helpers.js b/test/lib/helpers.js index 4273812..380b6cc 100644 --- a/test/lib/helpers.js +++ b/test/lib/helpers.js @@ -1,10 +1,10 @@ 'use strict'; const expect = require('chai').expect; -const EventuateClient = require('../../src'); +const EventuateClient = require('../../dist'); const uuid = require('uuid'); const specialChars = require('../../dist/modules/specialChars'); -const EventuateClientConfiguration = require('../../src').EventuateClientConfiguration; +const EventuateClientConfiguration = require('../../dist').EventuateClientConfiguration; module.exports.removeEventsArrProperty = (eventsArr, propertyName) => { return eventsArr.map(item => { diff --git a/test/subscribeEncrypted-spec.js b/test/subscribeEncrypted-spec.js index df8f63a..bceec7b 100644 --- a/test/subscribeEncrypted-spec.js +++ b/test/subscribeEncrypted-spec.js @@ -1,8 +1,7 @@ 'use strict'; -const expect = require('chai').expect; const util = require('util'); const helpers = require('./lib/helpers'); -const Encryption = require('../src/modules/Encryption'); +const Encryption = require('../dist/modules/Encryption'); const encryptionKeyId = 'id'; const keySecret = 'secret';