eventric-testing
Version:
Testing helpers for eventric.js
153 lines (113 loc) • 5.62 kB
text/coffeescript
equal = require 'deep-equal'
fakePromise = require './fake_promise'
inmemoryRemote = require 'eventric-remote-inmemory'
# TODO: Find a better way to solve the dependency to these eventric internal components
DomainEvent = require 'eventric/src/domain_event'
class RemoteFactory
setupFakeRemoteContext: (eventric, contextName, domainEvents = {}) ->
if not eventric
throw new Error 'eventric instance missing'
fakeRemoteContext = eventric.remoteContext contextName
fakeRemoteContext._context = eventric.context contextName
fakeRemoteContext._mostCurrentEmitOperation = fakePromise.resolve()
fakeRemoteContext._domainEvents = []
fakeRemoteContext._subscriberIds = []
fakeRemoteContext._commandStubs = []
fakeRemoteContext._context.defineDomainEvents domainEvents
fakeRemoteContext.setClient inmemoryRemote.client
fakeRemoteContext.$emitDomainEvent = (domainEventName, aggregateId, domainEventPayload) ->
domainEvent = @_createDomainEvent domainEventName, aggregateId, domainEventPayload
@_domainEvents.push domainEvent
endpoint = inmemoryRemote.endpoint
@_mostCurrentEmitOperation = @_mostCurrentEmitOperation.then ->
contextEventPublish = endpoint.publish contextName, domainEvent
contextAndNameEventPublish = endpoint.publish contextName, domainEvent.name, domainEvent
if domainEvent.aggregate
fullEventNamePublish = endpoint.publish contextName, domainEvent.name, domainEvent.aggregate.id, domainEvent
Promise.all([contextEventPublish, contextAndNameEventPublish, fullEventNamePublish])
else
Promise.all([contextEventPublish, contextAndNameEventPublish])
fakeRemoteContext.$waitForEmitDomainEvent = ->
fakeRemoteContext._mostCurrentEmitOperation
fakeRemoteContext._createDomainEvent = (domainEventName, aggregateId, domainEventConstructorParams) ->
DomainEventPayloadConstructor = fakeRemoteContext._context.getDomainEventPayloadConstructor domainEventName
if !DomainEventPayloadConstructor
throw new Error "Tried to create domain event '#{domainEventName}' which is not defined"
payload = {}
DomainEventPayloadConstructor.apply payload, [domainEventConstructorParams]
new DomainEvent
id: eventric.generateUuid()
name: domainEventName
aggregate:
id: aggregateId
name: 'EventricTesting'
context: @_context.name
payload: payload
fakeRemoteContext.findDomainEventsByName = (names) ->
names = [names] unless names instanceof Array
fakePromise.resolve @_domainEvents.filter (x) ->
names.indexOf(x.name) > -1
fakeRemoteContext.findDomainEventsByNameAndAggregateId = (names, aggregateIds) ->
names = [names] unless names instanceof Array
aggregateIds = [aggregateIds] unless aggregateIds instanceof Array
fakePromise.resolve @_domainEvents.filter (x) ->
names.indexOf(x.name) > -1 and x.aggregate and aggregateIds.indexOf(x.aggregate.id) > -1
originalSubscribeToAllDomainEvents = fakeRemoteContext.subscribeToAllDomainEvents
fakeRemoteContext.subscribeToAllDomainEvents = ->
originalSubscribeToAllDomainEvents.apply @, arguments
.then (subscriberId) =>
@_subscriberIds.push subscriberId
subscriberId
originalSubscribeToDomainEvent = fakeRemoteContext.subscribeToDomainEvent
fakeRemoteContext.subscribeToDomainEvent = ->
originalSubscribeToDomainEvent.apply @, arguments
.then (subscriberId) =>
@_subscriberIds.push subscriberId
subscriberId
originalSubscribeToDomainEventWithAggregateId = fakeRemoteContext.subscribeToDomainEventWithAggregateId
fakeRemoteContext.subscribeToDomainEventWithAggregateId = ->
originalSubscribeToDomainEventWithAggregateId.apply @, arguments
.then (subscriberId) =>
@_subscriberIds.push subscriberId
subscriberId
fakeRemoteContext.$destroy = ->
@_domainEvents = []
@_commandStubs = []
return @_mostCurrentEmitOperation.then =>
@_mostCurrentEmitOperation = fakePromise.resolve()
subscriptionRemovals = []
for subscriberId in @_subscriberIds
subscriptionRemovals.push fakeRemoteContext.unsubscribeFromDomainEvent subscriberId
@_subscriberIds = []
Promise.all subscriptionRemovals
fakeRemoteContext.$onCommand = (command, payload) ->
commandStub =
command: command
payload: payload
domainEvents: []
yieldsDomainEvent: (eventName, aggregateId, payload) ->
@domainEvents.push
eventName: eventName
aggregateId: aggregateId
payload: payload
@
@_commandStubs.push commandStub
commandStub
fakeRemoteContext.command = (command, payload) ->
filteredCommandStubs = @_commandStubs.filter (commandStub) ->
return command is commandStub.command and equal payload, commandStub.payload
unless filteredCommandStubs.length
return Promise.resolve()
emitDomainEventAsync = (domainEvent) =>
setTimeout =>
@$emitDomainEvent domainEvent.eventName,
domainEvent.aggregateId,
domainEvent.payload
for filteredCommandStub in filteredCommandStubs
for domainEvent in filteredCommandStub.domainEvents
emitDomainEventAsync domainEvent
return Promise.resolve()
fakeRemoteContext.query = ->
return Promise.resolve()
return fakeRemoteContext
module.exports = new RemoteFactory