Commit 40aa21bf authored by Aron Carroll's avatar Aron Carroll

Add unit tests for the CrossFrameBridge module

parent 2f25ec88
...@@ -88,6 +88,9 @@ class CrossFrameBridge ...@@ -88,6 +88,9 @@ class CrossFrameBridge
return return
on: (method, callback) -> on: (method, callback) ->
if @channelListeners[method]
throw new Error("Listener '#{method}' already bound in CrossFrameBridge")
@channelListeners[method] = callback @channelListeners[method] = callback
for l in @links for l in @links
l.channel.bind method, callback l.channel.bind method, callback
......
...@@ -7,47 +7,245 @@ describe 'CrossFrameBridge', -> ...@@ -7,47 +7,245 @@ describe 'CrossFrameBridge', ->
createChannel = null createChannel = null
beforeEach module('h') beforeEach module('h')
beforeEach module (CrossFrameBridge) -> beforeEach inject (CrossFrameBridge) ->
createBridge = (options) -> createBridge = (options) ->
new CrossFrameBridge(options) new CrossFrameBridge(options)
createChannel -> createChannel = ->
call: sandbox.stub() call: sandbox.stub()
bind: sandbox.stub() bind: sandbox.stub()
unbind: sandbox.stub() unbind: sandbox.stub()
notify: sandbox.stub() notify: sandbox.stub()
destroy: sandbox.stub()
sandbox.stub(Channel, 'build')
afterEach -> afterEach ->
sandbox.restore() sandbox.restore()
describe '.createChannel', -> describe '.createChannel', ->
it 'creates a new channel with the provided options' it 'creates a new channel with the provided options', ->
it 'adds the channel to the .links property' Channel.build.returns(createChannel())
it 'registers any channelListeners on the channel' bridge = createBridge()
it 'returns the newly created channel' bridge.createChannel('WINDOW', 'ORIGIN', 'TOKEN')
assert.called(Channel.build)
assert.calledWith(Channel.build, {
window: 'WINDOW'
origin: 'ORIGIN'
scope: 'crossFrameBridgeTOKEN'
onReady: sinon.match.func
})
it 'adds the channel to the .links property', ->
channel = createChannel()
Channel.build.returns(channel)
bridge = createBridge()
bridge.createChannel('WINDOW', 'ORIGIN', 'TOKEN')
assert.include(bridge.links, {channel: channel, window: 'WINDOW'})
it 'registers any existing listeners on the channel', ->
channel = createChannel()
Channel.build.returns(channel)
bridge = createBridge()
bridge.on('message1', sinon.spy())
bridge.on('message2', sinon.spy())
bridge.createChannel('WINDOW', 'ORIGIN', 'TOKEN')
assert.called(channel.bind)
assert.calledWith(channel.bind, 'message1', sinon.match.func)
assert.calledWith(channel.bind, 'message2', sinon.match.func)
it 'returns the newly created channel', ->
channel = createChannel()
Channel.build.returns(channel)
bridge = createBridge()
ret = bridge.createChannel('WINDOW', 'ORIGIN', 'TOKEN')
assert.equal(ret, channel)
describe '.call', -> describe '.call', ->
it 'forwards the call to every created channel' it 'forwards the call to every created channel', ->
it 'provides a timeout of 1000ms' channel = createChannel()
it 'calls options.callback when all channels return successfully' Channel.build.returns(channel)
it 'calls options.callback with an error when one or more channels fail'
it 'destroys the channel when a call fails' bridge = createBridge()
it 'removes the channel from the .links array when a call fails' bridge.createChannel('WINDOW', 'ORIGIN', 'TOKEN')
it 'treats a timeout as a success with no result' bridge.call({method: 'method1', params: 'params1'})
it 'returns a promise object'
assert.called(channel.call)
message = channel.call.lastCall.args[0]
assert.equal(message.method, 'method1')
assert.equal(message.params, 'params1')
it 'provides a timeout', ->
channel = createChannel()
Channel.build.returns(channel)
bridge = createBridge()
bridge.createChannel('WINDOW', 'ORIGIN', 'TOKEN')
bridge.call({method: 'method1', params: 'params1'})
message = channel.call.lastCall.args[0]
assert.isNumber(message.timeout)
it 'calls options.callback when all channels return successfully', ->
channel = createChannel()
channel.call.yieldsTo('success', 'result')
Channel.build.returns(channel)
callback = sandbox.stub()
bridge = createBridge()
bridge.createChannel('WINDOW', 'ORIGIN', 'TOKEN')
bridge.call({method: 'method1', params: 'params1', callback: callback})
assert.called(callback)
assert.calledWith(callback, null, ['result'])
it 'calls options.callback with an error when one or more channels fail', ->
err = new Error('Uh oh')
channel = createChannel()
channel.call.yieldsTo('error', err, 'A reason for the error')
Channel.build.returns(channel)
callback = sandbox.stub()
bridge = createBridge()
bridge.createChannel('WINDOW', 'ORIGIN', 'TOKEN')
bridge.call({method: 'method1', params: 'params1', callback: callback})
assert.called(callback)
assert.calledWith(callback, err)
it 'destroys the channel when a call fails', ->
channel = createChannel()
channel.call.yieldsTo('error', new Error(''), 'A reason for the error')
Channel.build.returns(channel)
bridge = createBridge()
bridge.createChannel('WINDOW', 'ORIGIN', 'TOKEN')
bridge.call({method: 'method1', params: 'params1', callback: sandbox.stub()})
assert.called(channel.destroy)
it 'no longer publishes to a channel that has had an errored response', ->
channel = createChannel()
channel.call.yieldsTo('error', new Error(''), 'A reason for the error')
Channel.build.returns(channel)
bridge = createBridge()
bridge.createChannel('WINDOW', 'ORIGIN', 'TOKEN')
bridge.call({method: 'method1', params: 'params1', callback: sandbox.stub()})
bridge.call({method: 'method1', params: 'params1', callback: sandbox.stub()})
assert.calledOnce(channel.call)
it 'treats a timeout as a success with no result', ->
channel = createChannel()
channel.call.yieldsTo('error', 'timeout_error', 'timeout')
Channel.build.returns(channel)
callback = sandbox.stub()
bridge = createBridge()
bridge.createChannel('WINDOW', 'ORIGIN', 'TOKEN')
bridge.call({method: 'method1', params: 'params1', callback: callback})
assert.called(callback)
assert.calledWith(callback, null, [null])
it 'returns a promise object', ->
channel = createChannel()
channel.call.yieldsTo('error', 'timeout_error', 'timeout')
Channel.build.returns(channel)
bridge = createBridge()
ret = bridge.call({method: 'method1', params: 'params1'})
assert.isFunction(ret.then)
describe '.notify', -> describe '.notify', ->
it 'publishes the message on every created channel' it 'publishes the message on every created channel', ->
channel = createChannel()
message = {method: 'message1', params: 'params'}
Channel.build.returns(channel)
bridge = createBridge()
bridge.createChannel('WINDOW', 'ORIGIN', 'TOKEN')
bridge.notify(message)
assert.called(channel.notify)
assert.calledWith(channel.notify, message)
describe '.on', -> describe '.on', ->
it 'registers an event listener on all created channels' it 'registers an event listener on all created channels', ->
it 'adds the message to the .channelListeners property' channel = createChannel()
it 'only allows one message to be registered per method' Channel.build.returns(channel)
bridge = createBridge()
bridge.createChannel('WINDOW', 'ORIGIN', 'TOKEN')
bridge.on('message1', sandbox.spy())
assert.called(channel.bind)
assert.calledWith(channel.bind, 'message1', sinon.match.func)
it 'only allows one message to be registered per method', ->
bridge = createBridge()
bridge.on('message1', sandbox.spy())
assert.throws ->
bridge.on('message1', sandbox.spy())
describe '.off', -> describe '.off', ->
it 'removes the event listener from the created channels' it 'removes the event listener from the created channels', ->
it 'removes the method from th .channelListeners property' channel = createChannel()
Channel.build.returns(channel)
bridge = createBridge()
bridge.createChannel('WINDOW', 'ORIGIN', 'TOKEN')
bridge.off('message1', sandbox.spy())
it 'ensures that the event is no longer bound when new channels are created', ->
channel1 = createChannel()
channel2 = createChannel()
Channel.build.returns(channel1)
bridge = createBridge()
bridge.createChannel('WINDOW', 'ORIGIN', 'TOKEN')
bridge.off('message1', sandbox.spy())
bridge.createChannel('WINDOW', 'ORIGIN', 'TOKEN')
assert.notCalled(channel2.bind)
describe '.onConnect', -> describe '.onConnect', ->
it 'adds a callback that is called when a new channel is connected' it 'adds a callback that is called when a new channel is connected', ->
it 'allows multiple callbacks to be registered' channel = createChannel()
Channel.build.returns(channel)
Channel.build.yieldsTo('onReady', channel)
callback = sandbox.stub()
bridge = createBridge()
bridge.onConnect(callback)
bridge.createChannel('WINDOW', 'ORIGIN', 'TOKEN')
assert.called(callback)
assert.calledWith(callback, channel)
it 'allows multiple callbacks to be registered', ->
channel = createChannel()
Channel.build.returns(channel)
Channel.build.yieldsTo('onReady', channel)
callback1 = sandbox.stub()
callback2 = sandbox.stub()
bridge = createBridge()
bridge.onConnect(callback1)
bridge.onConnect(callback2)
bridge.createChannel('WINDOW', 'ORIGIN', 'TOKEN')
assert.called(callback1)
assert.called(callback2)
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment