@leansdk/leanrc
Version:
LeanRC is a MVC framework for creating graceful applications
426 lines (424 loc) • 16.8 kB
text/coffeescript
{ expect, assert } = require 'chai'
sinon = require 'sinon'
LeanRC = require.main.require 'lib'
{
APPLICATION_MEDIATOR
NilT
FuncG
FacadeInterface, NotificationInterface
Facade
SimpleCommand
Notification
Proxy
Mediator
Utils: { co }
} = LeanRC::
describe 'Facade', ->
describe '.getInstance', ->
it 'should get new or existing instance of Facade', ->
expect ->
facade = Facade.getInstance 'TEST1'
assert facade instanceof Facade, 'The `facade` is not an instance of Facade'
facade1 = Facade.getInstance 'TEST1'
assert facade is facade1, 'Instances of facade not equal'
facade.remove()
.to.not.throw Error
describe '#initializeNotifier', ->
it 'should initialize notifier', ->
facade = Facade.getInstance 'TEST2'
ipsMultitonKey = Symbol.for '~multitonKey'
expect facade[ipsMultitonKey]
.to.equal 'TEST2'
facade.remove()
describe '#registerCommand', ->
it 'should register new command', ->
expect ->
facade = Facade.getInstance 'TEST3'
class TestCommand extends SimpleCommand
facade.registerCommand 'TEST_COMMAND', TestCommand
assert facade.hasCommand 'TEST_COMMAND'
facade.remove()
return
.to.not.throw Error
describe '#lazyRegisterCommand', ->
facade = null
INSTANCE_NAME = 'TEST999'
after ->
facade?.remove()
it 'should register new command lazily', ->
co ->
spy = sinon.spy()
class Test extends LeanRC
class TestCommand extends SimpleCommand
Test
execute: FuncG(NotificationInterface, NilT),
default: spy
class Application extends Test::CoreObject
Test
facade = Test::Facade.getInstance INSTANCE_NAME
facade.registerMediator Test::Mediator.new APPLICATION_MEDIATOR, Application.new()
vsNotificationName = 'TEST_COMMAND2'
facade.lazyRegisterCommand vsNotificationName, 'TestCommand'
assert facade.hasCommand vsNotificationName
facade.sendNotification vsNotificationName
assert spy.called
yield return
describe '#removeCommand', ->
it 'should remove command if present', ->
expect ->
facade = Facade.getInstance 'TEST4'
class TestCommand extends SimpleCommand
facade.registerCommand 'TEST_COMMAND', TestCommand
assert facade.hasCommand 'TEST_COMMAND'
facade.removeCommand 'TEST_COMMAND'
assert not facade.hasCommand 'TEST_COMMAND'
facade.remove()
return
.to.not.throw Error
describe '#hasCommand', ->
it 'should register new command', ->
expect ->
facade = Facade.getInstance 'TEST5'
class TestCommand extends SimpleCommand
facade.registerCommand 'TEST_COMMAND', TestCommand
assert facade.hasCommand 'TEST_COMMAND'
assert not facade.hasCommand 'TEST_COMMAND_ABSENT'
facade.remove()
return
.to.not.throw Error
describe '#registerProxy', ->
facade = null
INSTANCE_NAME = 'TEST6'
after ->
facade?.remove()
it 'should create new proxy and regiter it', ->
co ->
facade = Facade.getInstance INSTANCE_NAME
onRegister = sinon.spy ->
class TestProxy extends Proxy
onRegister: Function,
default: onRegister
proxyData = { data: 'data' }
testProxy = TestProxy.new 'TEST_PROXY', proxyData
facade.registerProxy testProxy
assert onRegister.called, 'Proxy is not registered'
onRegister.reset()
hasProxy = facade.hasProxy 'TEST_PROXY'
assert hasProxy, 'Proxy is not registered'
yield return
describe '#lazyRegisterProxy', ->
facade = null
INSTANCE_NAME = 'TEST66'
after ->
facade?.remove()
it 'should create new proxy and register it when needed', ->
co ->
onRegister = sinon.spy ->
class Test extends LeanRC
class TestProxy extends Proxy
Test
onRegister: Function,
default: onRegister
class Application extends Test::CoreObject
Test
facade = Facade.getInstance INSTANCE_NAME
facade.registerMediator Test::Mediator.new Test::APPLICATION_MEDIATOR, Application.new()
proxyData = { data: 'data' }
facade.lazyRegisterProxy 'TEST_PROXY', 'TestProxy', proxyData
assert.isFalse onRegister.called, 'Proxy is already registered'
onRegister.reset()
hasProxy = facade.hasProxy 'TEST_PROXY'
assert hasProxy, 'Proxy is not registered'
testProxy = facade.retrieveProxy 'TEST_PROXY'
assert.instanceOf testProxy, TestProxy
assert onRegister.called, 'Proxy is not registered'
onRegister.reset()
yield return
describe '#retrieveProxy', ->
it 'should retrieve registred proxy', ->
expect ->
facade = Facade.getInstance 'TEST7'
class TestProxy extends Proxy
proxyData = { data: 'data' }
testProxy = TestProxy.new 'TEST_PROXY', proxyData
facade.registerProxy testProxy
retrievedProxy = facade.retrieveProxy 'TEST_PROXY'
assert retrievedProxy is testProxy, 'Proxy cannot be retrieved'
retrievedAbsentProxy = facade.retrieveProxy 'TEST_PROXY_ABSENT'
hasNoAbsentProxy = not retrievedAbsentProxy?
assert hasNoAbsentProxy, 'Absent proxy can be retrieved'
facade.remove()
.to.not.throw Error
describe '#removeProxy', ->
it 'should create new proxy and regiter it, after that remove it', ->
expect ->
facade = Facade.getInstance 'TEST8'
onRemove = sinon.spy ->
class TestProxy extends Proxy
onRemove: Function,
default: onRemove
proxyData = { data: 'data' }
testProxy = TestProxy.new 'TEST_PROXY2', proxyData
facade.registerProxy testProxy
hasProxy = facade.hasProxy 'TEST_PROXY2'
assert hasProxy, 'Proxy is not registered'
facade.removeProxy 'TEST_PROXY2'
assert onRemove.called, 'Proxy is still registered'
hasNoProxy = not facade.hasProxy 'TEST_PROXY2'
assert hasNoProxy, 'Proxy is still registered'
facade.remove()
.to.not.throw Error
describe '#hasProxy', ->
it 'should retrieve registred proxy', ->
expect ->
facade = Facade.getInstance 'TEST9'
class TestProxy extends Proxy
proxyData = { data: 'data' }
testProxy = TestProxy.new 'TEST_PROXY', proxyData
facade.registerProxy testProxy
hasProxy = facade.hasProxy 'TEST_PROXY'
assert hasProxy, 'Proxy is absent'
hasNoAbsentProxy = not facade.hasProxy 'TEST_PROXY_ABSENT'
assert hasNoAbsentProxy, 'Absent proxy is accessible'
facade.remove()
.to.not.throw Error
describe '#registerMediator', ->
it 'should register new mediator', ->
expect ->
facade = Facade.getInstance 'TEST10'
onRegister = sinon.spy ->
handleNotification = sinon.spy ->
viewComponent = {}
class TestMediator extends Mediator
listNotificationInterests: FuncG([], Array),
default: -> [ 'TEST_LIST' ]
handleNotification: FuncG(NotificationInterface),
default: handleNotification
onRegister: Function,
default: onRegister
mediator = TestMediator.new 'TEST_MEDIATOR', viewComponent
facade.registerMediator mediator
assert onRegister.called, 'Mediator is not registered'
onRegister.reset()
facade.notifyObservers Notification.new 'TEST_LIST'
assert handleNotification.called, 'Mediator cannot subscribe interests'
facade.remove()
.to.not.throw Error
describe '#retrieveMediator', ->
it 'should retrieve registred mediator', ->
expect ->
facade = Facade.getInstance 'TEST11'
viewComponent = {}
class TestMediator extends Mediator
mediator = TestMediator.new 'TEST_MEDIATOR', viewComponent
facade.registerMediator mediator
retrievedMediator = facade.retrieveMediator 'TEST_MEDIATOR'
assert retrievedMediator is mediator, 'Cannot retrieve mediator'
retrievedAbsentMediator = facade.retrieveMediator 'TEST_MEDIATOR_ABSENT'
assert not retrievedAbsentMediator?, 'Retrieve absent mediator'
facade.remove()
.to.not.throw Error
describe '#removeMediator', ->
it 'should remove mediator', ->
expect ->
facade = Facade.getInstance 'TEST12'
onRemove = sinon.spy ->
viewComponent = {}
class TestMediator extends Mediator
onRemove: Function,
default: onRemove
mediator = TestMediator.new 'TEST_MEDIATOR', viewComponent
facade.registerMediator mediator
facade.removeMediator 'TEST_MEDIATOR'
assert onRemove.called, 'Mediator onRemove hook not called'
hasMediator = facade.hasMediator 'TEST_MEDIATOR'
assert not hasMediator, 'Mediator didn\'t removed'
facade.remove()
.to.not.throw Error
describe '#hasMediator', ->
it 'should retrieve registred proxy', ->
expect ->
facade = Facade.getInstance 'TEST13'
class TestMediator extends Mediator
viewComponent = {}
mediator = TestMediator.new 'TEST_MEDIATOR', viewComponent
facade.registerMediator mediator
hasMediator = facade.hasMediator 'TEST_MEDIATOR'
assert hasMediator, 'Proxy is absent'
hasNoAbsentsMediator = not facade.hasMediator 'TEST_MEDIATOR_ABSENT'
assert hasNoAbsentsMediator, 'Absent proxy is accessible'
facade.remove()
.to.not.throw Error
describe '#notifyObservers', ->
it 'should call notification for all observers', ->
expect ->
facade = Facade.getInstance 'TEST14'
handleNotification = sinon.spy ->
viewComponent = {}
class TestMediator extends Mediator
listNotificationInterests: FuncG([], Array),
default: -> [ 'TEST_LIST' ]
handleNotification: FuncG(NotificationInterface),
default: handleNotification
mediator = TestMediator.new 'TEST_MEDIATOR', viewComponent
facade.registerMediator mediator
facade.notifyObservers Notification.new 'TEST_LIST'
assert handleNotification.called, 'Mediator cannot subscribe interests'
facade.remove()
.to.not.throw Error
describe '#sendNotification', ->
it 'should send single notification', ->
expect ->
facade = Facade.getInstance 'TEST15'
handleNotification = sinon.spy ->
viewComponent = {}
class TestMediator extends Mediator
listNotificationInterests: FuncG([], Array),
default: -> [ 'TEST_LIST' ]
handleNotification: FuncG(NotificationInterface),
default: handleNotification
mediator = TestMediator.new 'TEST_MEDIATOR', viewComponent
facade.registerMediator mediator
facade.sendNotification 'TEST_LIST'
assert handleNotification.called, 'Mediator cannot subscribe interests'
facade.remove()
.to.not.throw Error
describe '#remove', ->
it 'should remove facade', ->
expect ->
KEY = 'TEST16'
facade = Facade.getInstance KEY
instanceMapSymbol = Symbol.for '~instanceMap'
assert.equal facade, Facade[instanceMapSymbol][KEY]
facade.remove()
assert.isUndefined Facade[instanceMapSymbol][KEY]
facade.remove()
.to.not.throw Error
describe '.replicateObject', ->
application = null
KEY = 'TEST17'
after -> application?.finish?()
it 'should create replica for facade', ->
co ->
class Test extends LeanRC
Test.initialize()
class ApplicationFacade extends LeanRC::Facade
Test
cphInstanceMap = ['~instanceMap'].pointer
startup: Function,
default: (application) ->
LeanRC::STARTUP, Test::PrepareViewCommand
LeanRC::STARTUP, application
finish: Function,
default: ->
getInstance: FuncG(String, FacadeInterface),
default: (asKey)->
vhInstanceMap = Test::Facade[cphInstanceMap]
unless vhInstanceMap[asKey]?
vhInstanceMap[asKey] = ApplicationFacade.new asKey
vhInstanceMap[asKey]
ApplicationFacade.initialize()
class ApplicationMediator extends LeanRC::Mediator
Test
ApplicationMediator.initialize()
class TestApplication extends LeanRC::Application
Test
NAME: String, { get: -> KEY }
TestApplication.initialize()
class PrepareViewCommand extends SimpleCommand
Test
execute: FuncG(NotificationInterface, NilT),
default: (aoNotification)->
voApplication = aoNotification.getBody()
.registerMediator ApplicationMediator.new LeanRC::APPLICATION_MEDIATOR, voApplication
PrepareViewCommand.initialize()
application = TestApplication.new()
application.start()
replica = yield ApplicationFacade.replicateObject application.facade
assert.deepEqual replica,
type: 'instance'
class: 'ApplicationFacade'
multitonKey: KEY
application: 'TestApplication'
yield return
describe '.restoreObject', ->
application = null
KEY = 'TEST18'
after -> application?.finish?()
it 'should create replica for facade', ->
co ->
class Test extends LeanRC
Test.initialize()
class ApplicationFacade extends LeanRC::Facade
Test
cphInstanceMap = ['~instanceMap'].pointer
startup: Function,
default: (application) ->
LeanRC::STARTUP, Test::PrepareViewCommand
LeanRC::STARTUP, application
finish: Function,
default: ->
getInstance: FuncG(String, FacadeInterface),
default: (asKey)->
vhInstanceMap = Test::Facade[cphInstanceMap]
unless vhInstanceMap[asKey]?
vhInstanceMap[asKey] = ApplicationFacade.new asKey
vhInstanceMap[asKey]
ApplicationFacade.initialize()
class ApplicationMediator extends LeanRC::Mediator
Test
ApplicationMediator.initialize()
class TestApplication extends LeanRC::Application
Test
NAME: String, { get: -> KEY }
TestApplication.initialize()
class PrepareViewCommand extends SimpleCommand
Test
execute: FuncG(NotificationInterface, NilT),
default: (aoNotification)->
voApplication = aoNotification.getBody()
.registerMediator ApplicationMediator.new LeanRC::APPLICATION_MEDIATOR, voApplication
PrepareViewCommand.initialize()
application = TestApplication.new()
restoredFacade = yield ApplicationFacade.restoreObject Test,
type: 'instance'
class: 'ApplicationFacade'
multitonKey: KEY
application: 'TestApplication'
assert.deepEqual application.facade, restoredFacade
yield return