websocket-rails-js 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (39) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +19 -0
  3. data/Gemfile +11 -0
  4. data/Guardfile +6 -0
  5. data/LICENSE.txt +22 -0
  6. data/README.md +13 -0
  7. data/Rakefile +36 -0
  8. data/app/assets/javascripts/websocket_rails/abstract_connection.js.coffee +45 -0
  9. data/app/assets/javascripts/websocket_rails/channel.js.coffee +66 -0
  10. data/app/assets/javascripts/websocket_rails/connection.js.coffee +62 -0
  11. data/app/assets/javascripts/websocket_rails/event.js.coffee +43 -0
  12. data/app/assets/javascripts/websocket_rails/http_connection.js.coffee +56 -0
  13. data/app/assets/javascripts/websocket_rails/main.js +6 -0
  14. data/app/assets/javascripts/websocket_rails/websocket_connection.js.coffee +29 -0
  15. data/app/assets/javascripts/websocket_rails/websocket_rails.js.coffee +148 -0
  16. data/lib/websocket-rails-js.rb +1 -0
  17. data/lib/websocket_rails/js/engine.rb +8 -0
  18. data/lib/websocket_rails/js/version.rb +5 -0
  19. data/spec/javascripts/helpers/.gitkeep +0 -0
  20. data/spec/javascripts/helpers/helpers.coffee +7 -0
  21. data/spec/javascripts/support/jasmine.yml +139 -0
  22. data/spec/javascripts/support/jasmine_helper.rb +15 -0
  23. data/spec/javascripts/support/jquery.min.js +4 -0
  24. data/spec/javascripts/support/sinon-1.7.1.js +4343 -0
  25. data/spec/javascripts/websocket_rails/channel_spec.js.coffee +99 -0
  26. data/spec/javascripts/websocket_rails/connection_spec.js.coffee +136 -0
  27. data/spec/javascripts/websocket_rails/event_spec.js.coffee +70 -0
  28. data/spec/javascripts/websocket_rails/helpers.js.coffee +7 -0
  29. data/spec/javascripts/websocket_rails/websocket_rails_spec.js.coffee +233 -0
  30. data/src/websocket_rails/abstract_connection.js +71 -0
  31. data/src/websocket_rails/channel.js +133 -0
  32. data/src/websocket_rails/connection.js +91 -0
  33. data/src/websocket_rails/event.js +66 -0
  34. data/src/websocket_rails/http_connection.js +97 -0
  35. data/src/websocket_rails/websocket_connection.js +59 -0
  36. data/src/websocket_rails/websocket_rails.js +218 -0
  37. data/websocket-rails-js.gemspec +25 -0
  38. data/websocket_rails.0.0.1.min.js +1 -0
  39. 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
+