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.
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
+