websocket-rails-js 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- 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
|
+
|