websocket-rails-js 0.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/.gitignore +19 -0
- data/Gemfile +11 -0
- data/Guardfile +6 -0
- data/LICENSE.txt +22 -0
- data/README.md +13 -0
- data/Rakefile +36 -0
- data/app/assets/javascripts/websocket_rails/abstract_connection.js.coffee +45 -0
- data/app/assets/javascripts/websocket_rails/channel.js.coffee +66 -0
- data/app/assets/javascripts/websocket_rails/connection.js.coffee +62 -0
- data/app/assets/javascripts/websocket_rails/event.js.coffee +43 -0
- data/app/assets/javascripts/websocket_rails/http_connection.js.coffee +56 -0
- data/app/assets/javascripts/websocket_rails/main.js +6 -0
- data/app/assets/javascripts/websocket_rails/websocket_connection.js.coffee +29 -0
- data/app/assets/javascripts/websocket_rails/websocket_rails.js.coffee +148 -0
- data/lib/websocket-rails-js.rb +1 -0
- data/lib/websocket_rails/js/engine.rb +8 -0
- data/lib/websocket_rails/js/version.rb +5 -0
- data/spec/javascripts/helpers/.gitkeep +0 -0
- data/spec/javascripts/helpers/helpers.coffee +7 -0
- data/spec/javascripts/support/jasmine.yml +139 -0
- data/spec/javascripts/support/jasmine_helper.rb +15 -0
- data/spec/javascripts/support/jquery.min.js +4 -0
- data/spec/javascripts/support/sinon-1.7.1.js +4343 -0
- data/spec/javascripts/websocket_rails/channel_spec.js.coffee +99 -0
- data/spec/javascripts/websocket_rails/connection_spec.js.coffee +136 -0
- data/spec/javascripts/websocket_rails/event_spec.js.coffee +70 -0
- data/spec/javascripts/websocket_rails/helpers.js.coffee +7 -0
- data/spec/javascripts/websocket_rails/websocket_rails_spec.js.coffee +233 -0
- data/src/websocket_rails/abstract_connection.js +71 -0
- data/src/websocket_rails/channel.js +133 -0
- data/src/websocket_rails/connection.js +91 -0
- data/src/websocket_rails/event.js +66 -0
- data/src/websocket_rails/http_connection.js +97 -0
- data/src/websocket_rails/websocket_connection.js +59 -0
- data/src/websocket_rails/websocket_rails.js +218 -0
- data/websocket-rails-js.gemspec +25 -0
- data/websocket_rails.0.0.1.min.js +1 -0
- metadata +135 -0
@@ -0,0 +1,99 @@
|
|
1
|
+
describe 'WebSocketRails.Channel:', ->
|
2
|
+
beforeEach ->
|
3
|
+
@dispatcher = new class WebSocketRailsStub
|
4
|
+
new_message: -> true
|
5
|
+
dispatch: -> true
|
6
|
+
trigger_event: (event) -> true
|
7
|
+
state: 'connected'
|
8
|
+
_conn:
|
9
|
+
connection_id: 12345
|
10
|
+
@channel = new WebSocketRails.Channel('public', @dispatcher)
|
11
|
+
sinon.spy @dispatcher, 'trigger_event'
|
12
|
+
|
13
|
+
afterEach ->
|
14
|
+
@dispatcher.trigger_event.restore()
|
15
|
+
|
16
|
+
describe '.bind', ->
|
17
|
+
it 'should add a function to the callbacks collection', ->
|
18
|
+
test_func = ->
|
19
|
+
@channel.bind 'event_name', test_func
|
20
|
+
expect(@channel._callbacks['event_name'].length).toBe 1
|
21
|
+
expect(@channel._callbacks['event_name']).toContain test_func
|
22
|
+
|
23
|
+
describe '.trigger', ->
|
24
|
+
describe 'before the channel token is set', ->
|
25
|
+
it 'queues the events', ->
|
26
|
+
@channel.trigger 'someEvent', 'someData'
|
27
|
+
queue = @channel._queue
|
28
|
+
expect(queue[0].name).toEqual 'someEvent'
|
29
|
+
expect(queue[0].data).toEqual 'someData'
|
30
|
+
|
31
|
+
describe 'when channel token is set', ->
|
32
|
+
it 'adds token to event metadata and dispatches event', ->
|
33
|
+
@channel._token = 'valid token'
|
34
|
+
@channel.trigger 'someEvent', 'someData'
|
35
|
+
expect(@dispatcher.trigger_event.calledWith(['someEvent', 'someData', {token: 'valid token'}]))
|
36
|
+
|
37
|
+
describe '.destroy', ->
|
38
|
+
it 'should destroy all callbacks', ->
|
39
|
+
event_callback = -> true
|
40
|
+
@channel.bind('new_message', @event_callback)
|
41
|
+
|
42
|
+
@channel.destroy()
|
43
|
+
|
44
|
+
expect(@channel._callbacks).toEqual {}
|
45
|
+
|
46
|
+
describe 'when this channel\'s connection is still active', ->
|
47
|
+
it 'should send unsubscribe event', ->
|
48
|
+
@channel.destroy()
|
49
|
+
expect(@dispatcher.trigger_event.args[0][0].name).toEqual 'websocket_rails.unsubscribe'
|
50
|
+
|
51
|
+
describe 'when this channel\'s connection is no more active', ->
|
52
|
+
beforeEach ->
|
53
|
+
@dispatcher._conn.connection_id++
|
54
|
+
|
55
|
+
it 'should not send unsubscribe event', ->
|
56
|
+
@channel.destroy()
|
57
|
+
expect(@dispatcher.trigger_event.notCalled).toEqual true
|
58
|
+
|
59
|
+
describe 'public channels', ->
|
60
|
+
beforeEach ->
|
61
|
+
@channel = new WebSocketRails.Channel('forchan', @dispatcher, false)
|
62
|
+
@event = @dispatcher.trigger_event.lastCall.args[0]
|
63
|
+
|
64
|
+
it 'should trigger an event containing the channel name', ->
|
65
|
+
expect(@event.data.channel).toEqual 'forchan'
|
66
|
+
|
67
|
+
it 'should trigger an event containing the correct connection_id', ->
|
68
|
+
expect(@event.connection_id).toEqual 12345
|
69
|
+
|
70
|
+
it 'should initialize an empty callbacks property', ->
|
71
|
+
expect(@channel._callbacks).toBeDefined()
|
72
|
+
expect(@channel._callbacks).toEqual {}
|
73
|
+
|
74
|
+
it 'should be public', ->
|
75
|
+
expect(@channel.is_private).toBeFalsy
|
76
|
+
|
77
|
+
describe 'channel tokens', ->
|
78
|
+
it 'should set token when event_name is websocket_rails.channel_token', ->
|
79
|
+
@channel.dispatch('websocket_rails.channel_token', {token: 'abc123'})
|
80
|
+
expect(@channel._token).toEqual 'abc123'
|
81
|
+
|
82
|
+
it 'should flush the event queue after setting token', ->
|
83
|
+
@channel.trigger 'someEvent', 'someData'
|
84
|
+
@channel.dispatch('websocket_rails.channel_token', {token: 'abc123'})
|
85
|
+
expect(@channel._queue.length).toEqual(0)
|
86
|
+
|
87
|
+
describe 'private channels', ->
|
88
|
+
beforeEach ->
|
89
|
+
@channel = new WebSocketRails.Channel('forchan',@dispatcher,true)
|
90
|
+
@event = @dispatcher.trigger_event.lastCall.args[0]
|
91
|
+
|
92
|
+
it 'should trigger a subscribe_private event when created', ->
|
93
|
+
expect(@event.name).toEqual 'websocket_rails.subscribe_private'
|
94
|
+
|
95
|
+
it 'should be private', ->
|
96
|
+
expect(@channel.is_private).toBe true
|
97
|
+
expect(@channel.is_public()).toEqual false
|
98
|
+
|
99
|
+
|
@@ -0,0 +1,136 @@
|
|
1
|
+
describe 'WebsocketRails.Connection:', ->
|
2
|
+
SAMPLE_EVENT_DATA = ['event','message',{}]
|
3
|
+
SAMPLE_EVENT_DATA_ENCODED = JSON.stringify(SAMPLE_EVENT_DATA)
|
4
|
+
SAMPLE_EVENT =
|
5
|
+
data: SAMPLE_EVENT_DATA_ENCODED
|
6
|
+
|
7
|
+
beforeEach ->
|
8
|
+
dispatcher =
|
9
|
+
new_message: -> true
|
10
|
+
dispatch: -> true
|
11
|
+
state: 'connected'
|
12
|
+
# Have to stub the WebSocket object due to Firefox error during jasmine:ci
|
13
|
+
window.WebSocket = class WebSocketStub
|
14
|
+
constructor: (@url, @dispatcher) ->
|
15
|
+
send: -> true
|
16
|
+
close: -> @onclose(null)
|
17
|
+
@dispatcher = dispatcher
|
18
|
+
@connection = new WebSocketRails.Connection('localhost:3000/websocket', dispatcher)
|
19
|
+
|
20
|
+
@dispatcher._conn = @connection
|
21
|
+
|
22
|
+
describe 'constructor', ->
|
23
|
+
|
24
|
+
it 'should redirect onmessage events\' data from the WebSocket object to this.on_message', ->
|
25
|
+
mock_connection = sinon.mock @connection
|
26
|
+
mock_connection.expects('on_message').once().withArgs SAMPLE_EVENT_DATA
|
27
|
+
@connection._conn.onmessage(SAMPLE_EVENT)
|
28
|
+
mock_connection.verify()
|
29
|
+
|
30
|
+
it 'should redirect onclose events from the WebSocket object to this.on_close', ->
|
31
|
+
mock_connection = sinon.mock @connection
|
32
|
+
mock_connection.expects('on_close').once().withArgs SAMPLE_EVENT
|
33
|
+
@connection._conn.onclose(SAMPLE_EVENT)
|
34
|
+
mock_connection.verify()
|
35
|
+
|
36
|
+
describe 'with ssl', ->
|
37
|
+
it 'should not add the ws:// prefix to the URL', ->
|
38
|
+
connection = new WebSocketRails.Connection('wss://localhost.com')
|
39
|
+
expect(connection.url).toEqual 'wss://localhost.com'
|
40
|
+
|
41
|
+
describe 'without ssl', ->
|
42
|
+
it 'should add the ws:// prefix to the URL', ->
|
43
|
+
expect(@connection.url).toEqual 'ws://localhost:3000/websocket'
|
44
|
+
|
45
|
+
describe '.close', ->
|
46
|
+
it 'should close the connection', ->
|
47
|
+
@connection.close()
|
48
|
+
expect(@dispatcher.state).toEqual 'disconnected'
|
49
|
+
|
50
|
+
describe '.trigger', ->
|
51
|
+
|
52
|
+
describe 'before the connection has been fully established', ->
|
53
|
+
it 'should queue up the events', ->
|
54
|
+
@connection.dispatcher.state = 'connecting'
|
55
|
+
event = new WebSocketRails.Event(['event','message'])
|
56
|
+
mock_queue = sinon.mock @connection.message_queue
|
57
|
+
mock_queue.expects('push').once().withArgs event
|
58
|
+
|
59
|
+
describe 'after the connection has been fully established', ->
|
60
|
+
it 'should encode the data and send it through the WebSocket object', ->
|
61
|
+
@connection.dispatcher.state = 'connected'
|
62
|
+
event = new WebSocketRails.Event(['event','message'])
|
63
|
+
@connection._conn =
|
64
|
+
send: -> true
|
65
|
+
mock_connection = sinon.mock @connection._conn
|
66
|
+
mock_connection.expects('send').once().withArgs event.serialize()
|
67
|
+
@connection.trigger event
|
68
|
+
mock_connection.verify()
|
69
|
+
|
70
|
+
describe '.on_message', ->
|
71
|
+
|
72
|
+
it 'should decode the message and pass it to the dispatcher', ->
|
73
|
+
mock_dispatcher = sinon.mock @connection.dispatcher
|
74
|
+
mock_dispatcher.expects('new_message').once().withArgs SAMPLE_EVENT_DATA
|
75
|
+
@connection.on_message SAMPLE_EVENT_DATA
|
76
|
+
mock_dispatcher.verify()
|
77
|
+
|
78
|
+
describe '.on_close', ->
|
79
|
+
it 'should dispatch the connection_closed event and pass the original event data', ->
|
80
|
+
event = new WebSocketRails.Event(['event','message'])
|
81
|
+
close_event = new WebSocketRails.Event(['connection_closed', event.data])
|
82
|
+
sinon.spy @dispatcher, 'dispatch'
|
83
|
+
@connection.on_close close_event
|
84
|
+
|
85
|
+
dispatcher = @dispatcher.dispatch
|
86
|
+
lastCall = dispatcher.lastCall.args[0]
|
87
|
+
expect(dispatcher.calledOnce).toBe(true)
|
88
|
+
expect(lastCall.data).toEqual event.data
|
89
|
+
|
90
|
+
dispatcher.restore()
|
91
|
+
|
92
|
+
it 'sets the connection state on the dispatcher to disconnected', ->
|
93
|
+
close_event = new WebSocketRails.Event(['connection_closed', {} ])
|
94
|
+
@connection.on_close close_event
|
95
|
+
|
96
|
+
expect(@dispatcher.state).toEqual('disconnected')
|
97
|
+
|
98
|
+
describe '.on_error', ->
|
99
|
+
it 'should dispatch the connection_error event and pass the original event', ->
|
100
|
+
|
101
|
+
event = new WebSocketRails.Event ['event','message']
|
102
|
+
error_event = new WebSocketRails.Event(['connection_error', event ])
|
103
|
+
sinon.spy @dispatcher, 'dispatch'
|
104
|
+
@connection.on_error event
|
105
|
+
|
106
|
+
dispatcher = @dispatcher.dispatch
|
107
|
+
lastCall = dispatcher.lastCall.args[0]
|
108
|
+
expect(dispatcher.calledOnce).toBe(true)
|
109
|
+
expect(lastCall.data).toEqual event.data
|
110
|
+
|
111
|
+
dispatcher.restore()
|
112
|
+
|
113
|
+
it 'sets the connection state on the dispatcher to disconnected', ->
|
114
|
+
close_event = new WebSocketRails.Event(['connection_closed', {} ])
|
115
|
+
@connection.on_error close_event
|
116
|
+
|
117
|
+
expect(@dispatcher.state).toEqual('disconnected')
|
118
|
+
|
119
|
+
describe '.flush_queue', ->
|
120
|
+
beforeEach ->
|
121
|
+
@event = new WebSocketRails.Event ['event','message']
|
122
|
+
@connection.message_queue.push @event
|
123
|
+
@connection._conn =
|
124
|
+
send: -> true
|
125
|
+
|
126
|
+
it 'should send out all of the messages in the queue', ->
|
127
|
+
mock_connection = sinon.mock @connection._conn
|
128
|
+
mock_connection.expects('send').once().withArgs @event.serialize()
|
129
|
+
@connection.flush_queue()
|
130
|
+
mock_connection.verify()
|
131
|
+
|
132
|
+
it 'should empty the queue after sending', ->
|
133
|
+
expect( @connection.message_queue.length ).toEqual 1
|
134
|
+
@connection.flush_queue()
|
135
|
+
expect( @connection.message_queue.length ).toEqual 0
|
136
|
+
|
@@ -0,0 +1,70 @@
|
|
1
|
+
describe 'WebSocketRails.Event', ->
|
2
|
+
|
3
|
+
describe 'standard events', ->
|
4
|
+
beforeEach ->
|
5
|
+
@data = ['event', { message: 'test'}, {connection_id: 12345}]
|
6
|
+
@event = new WebSocketRails.Event(@data)
|
7
|
+
|
8
|
+
it 'should generate an ID', ->
|
9
|
+
expect(@event.id).not.toBeNull
|
10
|
+
|
11
|
+
it 'should have a connection ID', ->
|
12
|
+
expect(@event.connection_id).toEqual 12345
|
13
|
+
|
14
|
+
it 'should assign the correct properties when passed a data array', ->
|
15
|
+
expect(@event.name).toEqual 'event'
|
16
|
+
expect(@event.data.message).toEqual 'test'
|
17
|
+
|
18
|
+
describe '.serialize()', ->
|
19
|
+
it 'should serialize the event as JSON', ->
|
20
|
+
@event.id = 1
|
21
|
+
serialized = '["event",{"message":"test"},{"id":1,"connection_id":12345}]'
|
22
|
+
expect(@event.serialize()).toEqual serialized
|
23
|
+
|
24
|
+
describe '.is_channel()', ->
|
25
|
+
it 'should be false', ->
|
26
|
+
expect(@event.is_channel()).toEqual false
|
27
|
+
|
28
|
+
describe 'channel events', ->
|
29
|
+
beforeEach ->
|
30
|
+
@data = ['event', { message: 'test'}, {connection_id: 12345, channel: 'channel', token: 'random_token'}]
|
31
|
+
@event = new WebSocketRails.Event(@data)
|
32
|
+
|
33
|
+
it 'should assign the channel property', ->
|
34
|
+
expect(@event.channel).toEqual 'channel'
|
35
|
+
expect(@event.name).toEqual 'event'
|
36
|
+
expect(@event.data.message).toEqual 'test'
|
37
|
+
expect(@event.token).toEqual 'random_token'
|
38
|
+
|
39
|
+
describe '.is_channel()', ->
|
40
|
+
it 'should be true', ->
|
41
|
+
expect(@event.is_channel()).toEqual true
|
42
|
+
|
43
|
+
describe '.serialize()', ->
|
44
|
+
it 'should serialize the event as JSON', ->
|
45
|
+
@event.id = 1
|
46
|
+
serialized = '["event",{"message":"test"},{"id":1,"connection_id":12345,"channel":"channel","token":"random_token"}]'
|
47
|
+
expect(@event.serialize()).toEqual serialized
|
48
|
+
|
49
|
+
describe '.run_callbacks()', ->
|
50
|
+
beforeEach ->
|
51
|
+
success_func = (data) ->
|
52
|
+
data
|
53
|
+
failure_func = (data) ->
|
54
|
+
data
|
55
|
+
@data = ['event', {data: { message: 'test'} }, 12345]
|
56
|
+
@event = new WebSocketRails.Event(@data, success_func, failure_func)
|
57
|
+
|
58
|
+
describe 'when successful', ->
|
59
|
+
it 'should run the success callback when passed true', ->
|
60
|
+
expect(@event.run_callbacks(true, 'success')).toEqual 'success'
|
61
|
+
|
62
|
+
it 'should not run the failure callback', ->
|
63
|
+
expect(@event.run_callbacks(true, 'success')).toBeUndefined
|
64
|
+
|
65
|
+
describe 'when failure', ->
|
66
|
+
it 'should run the failure callback when passed true', ->
|
67
|
+
expect(@event.run_callbacks(false, 'failure')).toEqual 'failure'
|
68
|
+
|
69
|
+
it 'should not run the failure callback', ->
|
70
|
+
expect(@event.run_callbacks(false, 'failure')).toBeUndefined
|
@@ -0,0 +1,7 @@
|
|
1
|
+
window.helpers =
|
2
|
+
startConnection: (dispatcher, connection_id = 1) ->
|
3
|
+
dispatcher.new_message ['client_connected', {data: ""}, {connection_id: connection_id}]
|
4
|
+
|
5
|
+
|
6
|
+
# live reload
|
7
|
+
document.write '<script src="http://localhost:35729/livereload.js?host=localhost"></script>'
|
@@ -0,0 +1,233 @@
|
|
1
|
+
describe 'WebSocketRails:', ->
|
2
|
+
beforeEach ->
|
3
|
+
@url = 'localhost:3000/websocket'
|
4
|
+
@dispatcher = new WebSocketRails @url
|
5
|
+
console.log @dispatcher
|
6
|
+
|
7
|
+
describe 'constructor', ->
|
8
|
+
it 'should start connection automatically', ->
|
9
|
+
expect(@dispatcher.state).toEqual 'connecting'
|
10
|
+
|
11
|
+
describe '.connect', ->
|
12
|
+
|
13
|
+
it 'should set the new_message method on connection to this.new_message', ->
|
14
|
+
expect(@dispatcher._conn.new_message).toEqual @dispatcher.new_message
|
15
|
+
|
16
|
+
it 'should set the initial state to connecting', ->
|
17
|
+
expect(@dispatcher.state).toEqual 'connecting'
|
18
|
+
|
19
|
+
describe 'when the browser does not support WebSockets', ->
|
20
|
+
it 'should use the Http Connection', ->
|
21
|
+
window.WebSocket = 'undefined'
|
22
|
+
dispatcher = new WebSocketRails @url, true
|
23
|
+
expect(dispatcher._conn.connection_type).toEqual 'http'
|
24
|
+
|
25
|
+
describe '.disconnect', ->
|
26
|
+
beforeEach ->
|
27
|
+
@dispatcher.disconnect()
|
28
|
+
|
29
|
+
it 'should close the connection', ->
|
30
|
+
expect(@dispatcher.state).toEqual 'disconnected'
|
31
|
+
|
32
|
+
it 'existing connection should be destroyed', ->
|
33
|
+
expect(@dispatcher._conn).toEqual undefined
|
34
|
+
|
35
|
+
describe '.reconnect', ->
|
36
|
+
OLD_CONNECTION_ID = 1
|
37
|
+
NEW_CONNECTION_ID = 2
|
38
|
+
|
39
|
+
it 'should recreate the connection', ->
|
40
|
+
helpers.startConnection(@dispatcher, OLD_CONNECTION_ID)
|
41
|
+
@dispatcher.reconnect()
|
42
|
+
window.helpers.startConnection(@dispatcher, NEW_CONNECTION_ID)
|
43
|
+
|
44
|
+
expect(@dispatcher._conn.connection_id).toEqual NEW_CONNECTION_ID
|
45
|
+
|
46
|
+
xit 'should resend all uncompleted events', ->
|
47
|
+
event = new WebSocketRails.Event ['create_post',{message: 'some_data'},{connection_id:OLD_CONNECTION_ID}]
|
48
|
+
helpers.startConnection(@dispatcher, OLD_CONNECTION_ID)
|
49
|
+
@dispatcher.trigger event
|
50
|
+
@dispatcher.reconnect()
|
51
|
+
helpers.startConnection(@dispatcher, NEW_CONNECTION_ID)
|
52
|
+
expect(@dispatcher.queue[event.id].connection_id).toEqual NEW_CONNECTION_ID
|
53
|
+
|
54
|
+
xit 'should not resend completed events', ->
|
55
|
+
event = new WebSocketRails.Event ['create_postx',{message: 'some_data'},{conneciton_id: OLD_CONNECTION_ID}]
|
56
|
+
helpers.startConnection(@dispatcher, OLD_CONNECTION_ID)
|
57
|
+
@dispatcher.trigger(event)
|
58
|
+
|
59
|
+
@dispatcher.reconnect()
|
60
|
+
helpers.startConnection(@dispatcher, NEW_CONNECTION_ID)
|
61
|
+
|
62
|
+
expect(@dispatcher.queue[event.id].connection_id).toEqual OLD_CONNECTION_ID
|
63
|
+
|
64
|
+
it 'should reconnect to all channels', ->
|
65
|
+
mock_dispatcher = sinon.mock @dispatcher
|
66
|
+
mock_dispatcher.expects('reconnect_channels').once()
|
67
|
+
@dispatcher.reconnect()
|
68
|
+
mock_dispatcher.verify()
|
69
|
+
|
70
|
+
describe '.reconnect_channels', ->
|
71
|
+
beforeEach ->
|
72
|
+
@channel_callback = -> true
|
73
|
+
helpers.startConnection(@dispatcher, 1)
|
74
|
+
@dispatcher.subscribe('public 4chan')
|
75
|
+
@dispatcher.subscribe_private('private 4chan')
|
76
|
+
@dispatcher.channels['public 4chan'].bind('new_post', @channel_callback)
|
77
|
+
|
78
|
+
it 'should recreate existing channels, keeping their private/public type', ->
|
79
|
+
@dispatcher.reconnect_channels()
|
80
|
+
expect(@dispatcher.channels['public 4chan'].is_public()).toEqual true
|
81
|
+
expect(@dispatcher.channels['private 4chan'].is_public()).toEqual false
|
82
|
+
|
83
|
+
it 'should move all existing callbacks from old channel objects to new ones', ->
|
84
|
+
old_public_channel = @dispatcher.channels['public 4chan']
|
85
|
+
|
86
|
+
@dispatcher.reconnect_channels()
|
87
|
+
|
88
|
+
expect(old_public_channel._callbacks).toEqual {}
|
89
|
+
expect(@dispatcher.channels['public 4chan']._callbacks).toEqual {new_post: [@channel_callback]}
|
90
|
+
|
91
|
+
describe '.new_message', ->
|
92
|
+
|
93
|
+
describe 'when this.state is "connecting"', ->
|
94
|
+
beforeEach ->
|
95
|
+
@connection_id = 123
|
96
|
+
|
97
|
+
it 'should call this.connection_established on the "client_connected" event', ->
|
98
|
+
mock_dispatcher = sinon.mock @dispatcher
|
99
|
+
mock_dispatcher.expects('connection_established').once()
|
100
|
+
helpers.startConnection(@dispatcher, @connection_id)
|
101
|
+
mock_dispatcher.verify()
|
102
|
+
|
103
|
+
it 'should set the state to connected', ->
|
104
|
+
helpers.startConnection(@dispatcher, @connection_id)
|
105
|
+
expect(@dispatcher.state).toEqual 'connected'
|
106
|
+
|
107
|
+
it 'should flush any messages queued before the connection was established', ->
|
108
|
+
mock_con = sinon.mock @dispatcher._conn
|
109
|
+
mock_con.expects('flush_queue').once()
|
110
|
+
helpers.startConnection(@dispatcher, @connection_id)
|
111
|
+
mock_con.verify()
|
112
|
+
|
113
|
+
it 'should set the correct connection_id', ->
|
114
|
+
helpers.startConnection(@dispatcher, @connection_id)
|
115
|
+
expect(@dispatcher._conn.connection_id).toEqual 123
|
116
|
+
|
117
|
+
it 'should call the user defined on_open callback', ->
|
118
|
+
spy = sinon.spy()
|
119
|
+
@dispatcher.on_open = spy
|
120
|
+
helpers.startConnection(@dispatcher, @connection_id)
|
121
|
+
expect(spy.calledOnce).toEqual true
|
122
|
+
|
123
|
+
describe 'after the connection has been established', ->
|
124
|
+
beforeEach ->
|
125
|
+
@dispatcher.state = 'connected'
|
126
|
+
@data = ['event', 'message', {channel: 'channel'}]
|
127
|
+
|
128
|
+
it 'should dispatch channel messages', ->
|
129
|
+
mock_dispatcher = sinon.mock @dispatcher
|
130
|
+
mock_dispatcher.expects('dispatch_channel').once()
|
131
|
+
@dispatcher.new_message @data
|
132
|
+
mock_dispatcher.verify()
|
133
|
+
|
134
|
+
it 'should dispatch standard events', ->
|
135
|
+
data = ['event','message']
|
136
|
+
mock_dispatcher = sinon.mock @dispatcher
|
137
|
+
mock_dispatcher.expects('dispatch').once()
|
138
|
+
@dispatcher.new_message data
|
139
|
+
mock_dispatcher.verify()
|
140
|
+
|
141
|
+
describe 'result events', ->
|
142
|
+
beforeEach ->
|
143
|
+
@attributes = {}
|
144
|
+
@attributes['success'] = true
|
145
|
+
@attributes['id'] = 1
|
146
|
+
@event = { run_callbacks: (data) -> }
|
147
|
+
@event_mock = sinon.mock @event
|
148
|
+
@dispatcher.queue[1] = @event
|
149
|
+
|
150
|
+
it 'should run callbacks for result events', ->
|
151
|
+
data = ['event', 'message', @attributes]
|
152
|
+
@event_mock.expects('run_callbacks').once()
|
153
|
+
@dispatcher.new_message data
|
154
|
+
@event_mock.verify()
|
155
|
+
|
156
|
+
describe '.bind', ->
|
157
|
+
|
158
|
+
it 'should store the callback on the correct event', ->
|
159
|
+
callback = ->
|
160
|
+
@dispatcher.bind 'event', callback
|
161
|
+
expect(@dispatcher.callbacks['event']).toContain callback
|
162
|
+
|
163
|
+
describe '.dispatch', ->
|
164
|
+
|
165
|
+
it 'should execute the callback for the correct event', ->
|
166
|
+
callback = sinon.spy()
|
167
|
+
event = new WebSocketRails.Event(['event',{data: 'message'}, {connection_id: 1}])
|
168
|
+
@dispatcher.bind 'event', callback
|
169
|
+
@dispatcher.dispatch event
|
170
|
+
expect(callback.calledWith({data: 'message'})).toEqual true
|
171
|
+
|
172
|
+
describe 'triggering events with', ->
|
173
|
+
beforeEach ->
|
174
|
+
@dispatcher._conn =
|
175
|
+
connection_id: 123
|
176
|
+
trigger: ->
|
177
|
+
trigger_channel: ->
|
178
|
+
|
179
|
+
describe '.trigger', ->
|
180
|
+
|
181
|
+
it 'should delegate to the connection object', ->
|
182
|
+
con_trigger = sinon.spy @dispatcher._conn, 'trigger'
|
183
|
+
@dispatcher.trigger 'event', 'message'
|
184
|
+
event = new WebSocketRails.Event ['websocket_rails.subscribe', {}, {channel: 'awesome', connection_id: 123}]
|
185
|
+
expect(con_trigger.called).toEqual true
|
186
|
+
|
187
|
+
describe '.connection_stale', ->
|
188
|
+
describe 'when state is connected', ->
|
189
|
+
it 'should return false', ->
|
190
|
+
@dispatcher.state = 'connected'
|
191
|
+
expect(@dispatcher.connection_stale()).toEqual false
|
192
|
+
|
193
|
+
describe 'when state is disconnected', ->
|
194
|
+
it 'should return true', ->
|
195
|
+
@dispatcher.state = 'disconnected'
|
196
|
+
expect(@dispatcher.connection_stale()).toEqual true
|
197
|
+
|
198
|
+
describe 'working with channels', ->
|
199
|
+
beforeEach ->
|
200
|
+
WebSocketRails.Channel = (@name, @dispatcher, @is_private) ->
|
201
|
+
|
202
|
+
describe '.subscribe', ->
|
203
|
+
describe 'for new channels', ->
|
204
|
+
it 'should create and store a new Channel object', ->
|
205
|
+
channel = @dispatcher.subscribe 'test_channel'
|
206
|
+
expect(channel.name).toEqual 'test_channel'
|
207
|
+
|
208
|
+
describe 'for existing channels', ->
|
209
|
+
it 'should return the same Channel object', ->
|
210
|
+
channel = @dispatcher.subscribe 'test_channel'
|
211
|
+
expect(@dispatcher.subscribe('test_channel')).toEqual channel
|
212
|
+
|
213
|
+
describe '.subscribe_private', ->
|
214
|
+
it 'should create private channels', ->
|
215
|
+
private_channel = @dispatcher.subscribe_private 'private_something'
|
216
|
+
expect(private_channel.is_private).toBe true
|
217
|
+
|
218
|
+
describe '.unsubscribe', ->
|
219
|
+
describe 'for existing channels', ->
|
220
|
+
it 'should remove the Channel object', ->
|
221
|
+
@dispatcher.unsubscribe 'test_channel'
|
222
|
+
expect(@dispatcher.channels['test_channel']).toBeUndefined
|
223
|
+
|
224
|
+
describe '.dispatch_channel', ->
|
225
|
+
|
226
|
+
it 'should delegate to the Channel object', ->
|
227
|
+
channel = @dispatcher.subscribe 'test'
|
228
|
+
channel.dispatch = ->
|
229
|
+
spy = sinon.spy channel, 'dispatch'
|
230
|
+
event = new WebSocketRails.Event(['event', 'awesome', {channel: 'test'}])
|
231
|
+
@dispatcher.dispatch_channel event
|
232
|
+
expect(spy.calledWith('event', 'awesome')).toEqual true
|
233
|
+
|