ably-rest 0.8.5 → 0.8.6
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +1 -1
- data/SPEC.md +1380 -631
- data/ably-rest.gemspec +11 -5
- data/lib/submodules/ably-ruby/.travis.yml +1 -1
- data/lib/submodules/ably-ruby/CHANGELOG.md +42 -48
- data/lib/submodules/ably-ruby/ably.gemspec +7 -1
- data/lib/submodules/ably-ruby/lib/ably.rb +2 -0
- data/lib/submodules/ably-ruby/lib/ably/auth.rb +155 -47
- data/lib/submodules/ably-ruby/lib/ably/exceptions.rb +2 -0
- data/lib/submodules/ably-ruby/lib/ably/models/channel_state_change.rb +2 -3
- data/lib/submodules/ably-ruby/lib/ably/models/connection_details.rb +54 -0
- data/lib/submodules/ably-ruby/lib/ably/models/protocol_message.rb +14 -4
- data/lib/submodules/ably-ruby/lib/ably/models/token_details.rb +13 -7
- data/lib/submodules/ably-ruby/lib/ably/models/token_request.rb +1 -2
- data/lib/submodules/ably-ruby/lib/ably/modules/ably.rb +3 -2
- data/lib/submodules/ably-ruby/lib/ably/modules/message_emitter.rb +1 -3
- data/lib/submodules/ably-ruby/lib/ably/modules/state_emitter.rb +2 -2
- data/lib/submodules/ably-ruby/lib/ably/realtime/auth.rb +6 -0
- data/lib/submodules/ably-ruby/lib/ably/realtime/channel.rb +15 -4
- data/lib/submodules/ably-ruby/lib/ably/realtime/channel/channel_manager.rb +2 -0
- data/lib/submodules/ably-ruby/lib/ably/realtime/client.rb +10 -3
- data/lib/submodules/ably-ruby/lib/ably/realtime/client/incoming_message_dispatcher.rb +11 -1
- data/lib/submodules/ably-ruby/lib/ably/realtime/connection.rb +62 -6
- data/lib/submodules/ably-ruby/lib/ably/realtime/connection/connection_manager.rb +58 -54
- data/lib/submodules/ably-ruby/lib/ably/realtime/presence.rb +18 -5
- data/lib/submodules/ably-ruby/lib/ably/rest/channel.rb +9 -1
- data/lib/submodules/ably-ruby/lib/ably/rest/client.rb +32 -14
- data/lib/submodules/ably-ruby/lib/ably/rest/presence.rb +1 -1
- data/lib/submodules/ably-ruby/lib/ably/version.rb +1 -1
- data/lib/submodules/ably-ruby/spec/acceptance/realtime/auth_spec.rb +251 -11
- data/lib/submodules/ably-ruby/spec/acceptance/realtime/channel_history_spec.rb +12 -2
- data/lib/submodules/ably-ruby/spec/acceptance/realtime/channel_spec.rb +316 -24
- data/lib/submodules/ably-ruby/spec/acceptance/realtime/client_spec.rb +93 -1
- data/lib/submodules/ably-ruby/spec/acceptance/realtime/connection_failures_spec.rb +177 -86
- data/lib/submodules/ably-ruby/spec/acceptance/realtime/connection_spec.rb +284 -60
- data/lib/submodules/ably-ruby/spec/acceptance/realtime/message_spec.rb +45 -6
- data/lib/submodules/ably-ruby/spec/acceptance/realtime/presence_history_spec.rb +4 -0
- data/lib/submodules/ably-ruby/spec/acceptance/realtime/presence_spec.rb +181 -49
- data/lib/submodules/ably-ruby/spec/acceptance/realtime/time_spec.rb +13 -0
- data/lib/submodules/ably-ruby/spec/acceptance/rest/auth_spec.rb +222 -4
- data/lib/submodules/ably-ruby/spec/acceptance/rest/channel_spec.rb +132 -1
- data/lib/submodules/ably-ruby/spec/acceptance/rest/client_spec.rb +129 -28
- data/lib/submodules/ably-ruby/spec/acceptance/rest/presence_spec.rb +7 -7
- data/lib/submodules/ably-ruby/spec/acceptance/rest/time_spec.rb +10 -0
- data/lib/submodules/ably-ruby/spec/shared/client_initializer_behaviour.rb +41 -17
- data/lib/submodules/ably-ruby/spec/spec_helper.rb +1 -0
- data/lib/submodules/ably-ruby/spec/support/debug_failure_helper.rb +16 -0
- data/lib/submodules/ably-ruby/spec/unit/models/connection_details_spec.rb +60 -0
- data/lib/submodules/ably-ruby/spec/unit/models/protocol_message_spec.rb +45 -0
- data/lib/submodules/ably-ruby/spec/unit/modules/event_emitter_spec.rb +3 -1
- data/lib/submodules/ably-ruby/spec/unit/realtime/channel_spec.rb +6 -5
- data/lib/submodules/ably-ruby/spec/unit/realtime/client_spec.rb +5 -1
- data/lib/submodules/ably-ruby/spec/unit/realtime/connection_spec.rb +5 -1
- data/lib/submodules/ably-ruby/spec/unit/realtime/realtime_spec.rb +5 -1
- metadata +57 -13
@@ -132,7 +132,6 @@ describe 'Ably::Realtime::Channel Message', :event_machine do
|
|
132
132
|
let(:client_options) { default_options.merge(client_id: client_id) }
|
133
133
|
|
134
134
|
it 'contains a #client_id attribute' do
|
135
|
-
skip 'Waiting for issue #256 to be resolved'
|
136
135
|
when_all(channel.attach, other_client_channel.attach) do
|
137
136
|
other_client_channel.subscribe('event') do |message|
|
138
137
|
expect(message.client_id).to eql(client_id)
|
@@ -208,14 +207,26 @@ describe 'Ably::Realtime::Channel Message', :event_machine do
|
|
208
207
|
end
|
209
208
|
end
|
210
209
|
|
211
|
-
it 'will not echo messages to the client from other REST clients publishing using that
|
212
|
-
skip 'Waiting on realtime#285 to be resolved'
|
210
|
+
it 'will not echo messages to the client from other REST clients publishing using that connection_key', em_timeout: 10 do
|
213
211
|
no_echo_channel.attach do
|
214
212
|
no_echo_channel.subscribe('test_event') do |message|
|
215
213
|
fail "Message should not have been echoed back"
|
216
214
|
end
|
217
215
|
|
218
|
-
rest_client.channel(channel_name).publish('test_event', nil,
|
216
|
+
rest_client.channel(channel_name).publish('test_event', nil, connection_key: no_echo_client.connection.key)
|
217
|
+
EventMachine.add_timer(1.5) do
|
218
|
+
stop_reactor
|
219
|
+
end
|
220
|
+
end
|
221
|
+
end
|
222
|
+
|
223
|
+
it 'will echo messages with a valid connection_id to the client from other REST clients publishing using that connection_key', em_timeout: 10 do
|
224
|
+
channel.attach do
|
225
|
+
channel.subscribe('test_event') do |message|
|
226
|
+
expect(message.connection_id).to eql(client.connection.id)
|
227
|
+
end
|
228
|
+
|
229
|
+
rest_client.channel(channel_name).publish('test_event', nil, connection_key: client.connection.key)
|
219
230
|
EventMachine.add_timer(1.5) do
|
220
231
|
stop_reactor
|
221
232
|
end
|
@@ -599,7 +610,7 @@ describe 'Ably::Realtime::Channel Message', :event_machine do
|
|
599
610
|
let(:event_name) { random_str }
|
600
611
|
let(:message_state) { [] }
|
601
612
|
let(:connection) { client.connection }
|
602
|
-
let(:client_options) { default_options.merge(:log_level => :
|
613
|
+
let(:client_options) { default_options.merge(:log_level => :fatal) }
|
603
614
|
let(:msgs_received) { [] }
|
604
615
|
|
605
616
|
it 'publishes the message again, later receives the ACK and only one message is ever received from Ably' do
|
@@ -642,6 +653,32 @@ describe 'Ably::Realtime::Channel Message', :event_machine do
|
|
642
653
|
let(:connection) { client.connection }
|
643
654
|
let(:event_name) { random_str }
|
644
655
|
|
656
|
+
describe 'the connection is not resumed' do
|
657
|
+
let(:client_options) { default_options.merge(:log_level => :fatal) }
|
658
|
+
|
659
|
+
it 'calls the errback for all messages' do
|
660
|
+
connection.once(:connected) do
|
661
|
+
connection.transport.__outgoing_protocol_msgbus__.subscribe(:protocol_message) do |protocol_message|
|
662
|
+
if protocol_message.messages.find { |message| message.name == event_name }
|
663
|
+
EventMachine.add_timer(0.0001) do
|
664
|
+
connection.transport.unbind # trigger failure
|
665
|
+
connection.configure_new '0123456789abcdef', 'wVIsgTHAB1UvXh7z-1991d8586', -1 # force the resume connection key to be invalid
|
666
|
+
end
|
667
|
+
end
|
668
|
+
end
|
669
|
+
end
|
670
|
+
|
671
|
+
channel.publish(event_name).tap do |deferrable|
|
672
|
+
deferrable.callback do
|
673
|
+
raise 'Message delivery should not happen'
|
674
|
+
end
|
675
|
+
deferrable.errback do
|
676
|
+
stop_reactor
|
677
|
+
end
|
678
|
+
end
|
679
|
+
end
|
680
|
+
end
|
681
|
+
|
645
682
|
describe 'the connection becomes suspended' do
|
646
683
|
let(:client_options) { default_options.merge(:log_level => :fatal) }
|
647
684
|
|
@@ -649,8 +686,10 @@ describe 'Ably::Realtime::Channel Message', :event_machine do
|
|
649
686
|
connection.once(:connected) do
|
650
687
|
connection.transport.__outgoing_protocol_msgbus__.subscribe(:protocol_message) do |protocol_message|
|
651
688
|
if protocol_message.messages.find { |message| message.name == event_name }
|
652
|
-
EventMachine.add_timer(0.
|
689
|
+
EventMachine.add_timer(0.0001) do
|
653
690
|
connection.transition_state_machine :suspended
|
691
|
+
stub_const 'Ably::FALLBACK_HOSTS', []
|
692
|
+
allow(client).to receive(:endpoint).and_return(URI::Generic.build(scheme: 'wss', host: 'does.not.exist.com'))
|
654
693
|
end
|
655
694
|
end
|
656
695
|
end
|
@@ -71,6 +71,10 @@ describe Ably::Realtime::Presence, 'history', :event_machine do
|
|
71
71
|
end
|
72
72
|
|
73
73
|
context 'and two pages of messages' do
|
74
|
+
let(:wildcard_token) { Proc.new { Ably::Rest::Client.new(default_options).auth.request_token(client_id: '*') } }
|
75
|
+
let(:client_one) { auto_close Ably::Realtime::Client.new(default_options.merge(auth_callback: wildcard_token)) }
|
76
|
+
let(:client_two) { auto_close Ably::Realtime::Client.new(default_options.merge(auth_callback: wildcard_token)) }
|
77
|
+
|
74
78
|
it 'retrieves two pages of messages before channel was attached' do
|
75
79
|
when_all(*10.times.map { |i| presence_client_two.enter_client("client:#{i}", data: presence_data_before_attach) }) do
|
76
80
|
when_all(*10.times.map { |i| presence_client_one.enter_client("client:#{i}", data: presence_data_after_attach) }) do
|
@@ -9,9 +9,12 @@ describe Ably::Realtime::Presence, :event_machine do
|
|
9
9
|
let(:client_options) { default_options }
|
10
10
|
|
11
11
|
let(:anonymous_client) { auto_close Ably::Realtime::Client.new(client_options) }
|
12
|
-
let(:
|
13
|
-
let(:
|
12
|
+
let(:client_one_id) { random_str }
|
13
|
+
let(:client_one) { auto_close Ably::Realtime::Client.new(client_options.merge(client_id: client_one_id)) }
|
14
|
+
let(:client_two_id) { random_str }
|
15
|
+
let(:client_two) { auto_close Ably::Realtime::Client.new(client_options.merge(client_id: client_two_id)) }
|
14
16
|
|
17
|
+
let(:wildcard_token) { Proc.new { Ably::Rest::Client.new(client_options).auth.request_token(client_id: '*') } }
|
15
18
|
let(:channel_name) { "presence-#{random_str(4)}" }
|
16
19
|
let(:channel_anonymous_client) { anonymous_client.channel(channel_name) }
|
17
20
|
let(:presence_anonymous_client) { channel_anonymous_client.presence }
|
@@ -29,6 +32,14 @@ describe Ably::Realtime::Presence, :event_machine do
|
|
29
32
|
end
|
30
33
|
|
31
34
|
shared_examples_for 'a public presence method' do |method_name, expected_state, args, options = {}|
|
35
|
+
let(:client_id) do
|
36
|
+
if args.empty?
|
37
|
+
random_str
|
38
|
+
else
|
39
|
+
args
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
32
43
|
def setup_test(method_name, args, options)
|
33
44
|
if options[:enter_first]
|
34
45
|
presence_client_one.public_send(method_name.to_s.gsub(/leave|update/, 'enter'), args) do
|
@@ -72,7 +83,7 @@ describe Ably::Realtime::Presence, :event_machine do
|
|
72
83
|
end
|
73
84
|
|
74
85
|
context 'when :queue_messages client option is false' do
|
75
|
-
let(:client_one) { auto_close Ably::Realtime::Client.new(default_options.merge(queue_messages: false, client_id:
|
86
|
+
let(:client_one) { auto_close Ably::Realtime::Client.new(default_options.merge(queue_messages: false, client_id: client_id)) }
|
76
87
|
|
77
88
|
context 'and connection state initialized' do
|
78
89
|
it 'raises an exception' do
|
@@ -94,7 +105,7 @@ describe Ably::Realtime::Presence, :event_machine do
|
|
94
105
|
end
|
95
106
|
|
96
107
|
context 'and connection state disconnected' do
|
97
|
-
let(:client_one) { auto_close Ably::Realtime::Client.new(default_options.merge(queue_messages: false, client_id:
|
108
|
+
let(:client_one) { auto_close Ably::Realtime::Client.new(default_options.merge(queue_messages: false, client_id: client_id, :log_level => :error)) }
|
98
109
|
|
99
110
|
it 'raises an exception' do
|
100
111
|
client_one.connection.once(:connected) do
|
@@ -122,7 +133,7 @@ describe Ably::Realtime::Presence, :event_machine do
|
|
122
133
|
context 'with supported data payload content type' do
|
123
134
|
def register_presence_and_check_data(method_name, data)
|
124
135
|
if method_name.to_s.match(/_client/)
|
125
|
-
presence_client_one.public_send(method_name,
|
136
|
+
presence_client_one.public_send(method_name, client_id, data: data)
|
126
137
|
else
|
127
138
|
presence_client_one.public_send(method_name, data: data)
|
128
139
|
end
|
@@ -177,7 +188,7 @@ describe Ably::Realtime::Presence, :event_machine do
|
|
177
188
|
context 'with unsupported data payload content type' do
|
178
189
|
def presence_action(method_name, data)
|
179
190
|
if method_name.to_s.match(/_client/)
|
180
|
-
presence_client_one.public_send(method_name,
|
191
|
+
presence_client_one.public_send(method_name, client_id, data: data)
|
181
192
|
else
|
182
193
|
presence_client_one.public_send(method_name, data: data)
|
183
194
|
end
|
@@ -255,15 +266,6 @@ describe Ably::Realtime::Presence, :event_machine do
|
|
255
266
|
end
|
256
267
|
|
257
268
|
context 'if connection fails before success' do
|
258
|
-
before do
|
259
|
-
# Reconfigure client library so that it makes no retry attempts and fails immediately
|
260
|
-
stub_const 'Ably::Realtime::Connection::ConnectionManager::CONNECT_RETRY_CONFIG',
|
261
|
-
Ably::Realtime::Connection::ConnectionManager::CONNECT_RETRY_CONFIG.merge(
|
262
|
-
disconnected: { retry_every: 0.1, max_time_in_state: 0 },
|
263
|
-
suspended: { retry_every: 0.1, max_time_in_state: 0 }
|
264
|
-
)
|
265
|
-
end
|
266
|
-
|
267
269
|
let(:client_options) { default_options.merge(log_level: :none) }
|
268
270
|
|
269
271
|
it 'calls the Deferrable errback if channel is detached' do
|
@@ -272,7 +274,8 @@ describe Ably::Realtime::Presence, :event_machine do
|
|
272
274
|
client_one.connection.__outgoing_protocol_msgbus__.subscribe(:protocol_message) do |protocol_message|
|
273
275
|
# Don't allow any messages to reach the server
|
274
276
|
client_one.connection.__outgoing_protocol_msgbus__.unsubscribe
|
275
|
-
|
277
|
+
error_message = Ably::Models::ProtocolMessage.new(action: 9, error: { message: 'force failure' })
|
278
|
+
client_one.connection.__incoming_protocol_msgbus__.publish :protocol_message, error_message
|
276
279
|
end
|
277
280
|
|
278
281
|
presence_client_one.public_send(method_name, args).tap do |deferrable|
|
@@ -288,6 +291,123 @@ describe Ably::Realtime::Presence, :event_machine do
|
|
288
291
|
end
|
289
292
|
end
|
290
293
|
|
294
|
+
shared_examples_for 'a presence on behalf of another client method' do |method_name|
|
295
|
+
context ":#{method_name} when authenticated with a wildcard client_id" do
|
296
|
+
let(:token) { Ably::Rest::Client.new(default_options).auth.request_token(client_id: '*').token }
|
297
|
+
let(:client_options) { default_options.merge(key: nil, token: token) }
|
298
|
+
let(:client) { auto_close Ably::Realtime::Client.new(client_options) }
|
299
|
+
let(:presence_channel) { client.channels.get(channel_name).presence }
|
300
|
+
|
301
|
+
context 'and a valid client_id' do
|
302
|
+
it 'succeeds' do
|
303
|
+
presence_channel.public_send(method_name, 'clientId') do
|
304
|
+
EM.add_timer(0.5) { stop_reactor }
|
305
|
+
end.tap do |deferrable|
|
306
|
+
deferrable.errback { raise 'Should have succeeded' }
|
307
|
+
end
|
308
|
+
end
|
309
|
+
end
|
310
|
+
|
311
|
+
context 'and a wildcard client_id' do
|
312
|
+
it 'throws an exception' do
|
313
|
+
expect { presence_channel.public_send(method_name, '*') }.to raise_error Ably::Exceptions::IncompatibleClientId
|
314
|
+
stop_reactor
|
315
|
+
end
|
316
|
+
end
|
317
|
+
|
318
|
+
context 'and an empty client_id' do
|
319
|
+
it 'throws an exception' do
|
320
|
+
expect { presence_channel.public_send(method_name, nil) }.to raise_error Ably::Exceptions::IncompatibleClientId
|
321
|
+
stop_reactor
|
322
|
+
end
|
323
|
+
end
|
324
|
+
end
|
325
|
+
|
326
|
+
context ":#{method_name} when authenticated with a valid client_id" do
|
327
|
+
let(:token) { Ably::Rest::Client.new(default_options).auth.request_token(client_id: 'valid').token }
|
328
|
+
let(:client_options) { default_options.merge(key: nil, token: token) }
|
329
|
+
let(:client) { auto_close Ably::Realtime::Client.new(client_options.merge(log_level: :error)) }
|
330
|
+
let(:channel) { client.channels.get(channel_name) }
|
331
|
+
let(:presence_channel) { channel.presence }
|
332
|
+
|
333
|
+
context 'and another invalid client_id' do
|
334
|
+
context 'before authentication' do
|
335
|
+
it 'allows the operation and then Ably rejects the operation' do
|
336
|
+
presence_channel.public_send(method_name, 'invalid').errback do |error|
|
337
|
+
expect(error.code).to eql(40012)
|
338
|
+
stop_reactor
|
339
|
+
end
|
340
|
+
end
|
341
|
+
end
|
342
|
+
|
343
|
+
context 'after authentication' do
|
344
|
+
it 'throws an exception' do
|
345
|
+
channel.attach do
|
346
|
+
expect { presence_channel.public_send(method_name, 'invalid') }.to raise_error Ably::Exceptions::IncompatibleClientId
|
347
|
+
stop_reactor
|
348
|
+
end
|
349
|
+
end
|
350
|
+
end
|
351
|
+
end
|
352
|
+
|
353
|
+
context 'and a wildcard client_id' do
|
354
|
+
it 'throws an exception' do
|
355
|
+
expect { presence_channel.public_send(method_name, '*') }.to raise_error Ably::Exceptions::IncompatibleClientId
|
356
|
+
stop_reactor
|
357
|
+
end
|
358
|
+
end
|
359
|
+
|
360
|
+
context 'and an empty client_id' do
|
361
|
+
it 'throws an exception' do
|
362
|
+
expect { presence_channel.public_send(method_name, nil) }.to raise_error Ably::Exceptions::IncompatibleClientId
|
363
|
+
stop_reactor
|
364
|
+
end
|
365
|
+
end
|
366
|
+
end
|
367
|
+
|
368
|
+
context ":#{method_name} when anonymous and no client_id" do
|
369
|
+
let(:token) { Ably::Rest::Client.new(default_options).auth.request_token(client_id: nil).token }
|
370
|
+
let(:client_options) { default_options.merge(key: nil, token: token) }
|
371
|
+
let(:client) { auto_close Ably::Realtime::Client.new(client_options.merge(log_level: :error)) }
|
372
|
+
let(:channel) { client.channels.get(channel_name) }
|
373
|
+
let(:presence_channel) { channel.presence }
|
374
|
+
|
375
|
+
context 'and another invalid client_id' do
|
376
|
+
context 'before authentication' do
|
377
|
+
it 'allows the operation and then Ably rejects the operation' do
|
378
|
+
presence_channel.public_send(method_name, 'invalid').errback do |error|
|
379
|
+
expect(error.code).to eql(40012)
|
380
|
+
stop_reactor
|
381
|
+
end
|
382
|
+
end
|
383
|
+
end
|
384
|
+
|
385
|
+
context 'after authentication' do
|
386
|
+
it 'throws an exception' do
|
387
|
+
channel.attach do
|
388
|
+
expect { presence_channel.public_send(method_name, 'invalid') }.to raise_error Ably::Exceptions::IncompatibleClientId
|
389
|
+
stop_reactor
|
390
|
+
end
|
391
|
+
end
|
392
|
+
end
|
393
|
+
end
|
394
|
+
|
395
|
+
context 'and a wildcard client_id' do
|
396
|
+
it 'throws an exception' do
|
397
|
+
expect { presence_channel.public_send(method_name, '*') }.to raise_error Ably::Exceptions::IncompatibleClientId
|
398
|
+
stop_reactor
|
399
|
+
end
|
400
|
+
end
|
401
|
+
|
402
|
+
context 'and an empty client_id' do
|
403
|
+
it 'throws an exception' do
|
404
|
+
expect { presence_channel.public_send(method_name, nil) }.to raise_error Ably::Exceptions::IncompatibleClientId
|
405
|
+
stop_reactor
|
406
|
+
end
|
407
|
+
end
|
408
|
+
end
|
409
|
+
end
|
410
|
+
|
291
411
|
context 'when attached (but not present) on a presence channel with an anonymous client (no client ID)' do
|
292
412
|
it 'maintains state as other clients enter and leave the channel' do
|
293
413
|
channel_anonymous_client.attach do
|
@@ -394,6 +514,7 @@ describe Ably::Realtime::Presence, :event_machine do
|
|
394
514
|
let(:present) { [] }
|
395
515
|
let(:entered) { [] }
|
396
516
|
let(:sync_pages_received) { [] }
|
517
|
+
let(:client_one) { auto_close Ably::Realtime::Client.new(client_options.merge(auth_callback: wildcard_token)) }
|
397
518
|
|
398
519
|
def setup_members_on(presence)
|
399
520
|
enter_expected_count.times do |index|
|
@@ -434,7 +555,10 @@ describe Ably::Realtime::Presence, :event_machine do
|
|
434
555
|
presence_anonymous_client.subscribe(:leave) do |leave_message|
|
435
556
|
expect(leave_message.client_id).to eql(leave_member.client_id)
|
436
557
|
expect(present.count).to be < enter_expected_count
|
437
|
-
|
558
|
+
EventMachine.add_timer(1) do
|
559
|
+
presence_anonymous_client.unsubscribe
|
560
|
+
stop_reactor
|
561
|
+
end
|
438
562
|
end
|
439
563
|
|
440
564
|
anonymous_client.connect do
|
@@ -471,7 +595,10 @@ describe Ably::Realtime::Presence, :event_machine do
|
|
471
595
|
if present.count == enter_expected_count
|
472
596
|
presence_anonymous_client.get do |members|
|
473
597
|
expect(members.find { |member| member.client_id == leave_member.client_id}.action).to eq(:present)
|
474
|
-
|
598
|
+
EventMachine.add_timer(1) do
|
599
|
+
presence_anonymous_client.unsubscribe
|
600
|
+
stop_reactor
|
601
|
+
end
|
475
602
|
end
|
476
603
|
end
|
477
604
|
end
|
@@ -523,7 +650,10 @@ describe Ably::Realtime::Presence, :event_machine do
|
|
523
650
|
expect(members.count).to eql(enter_expected_count - 1)
|
524
651
|
expect(member_left_emitted).to eql(true)
|
525
652
|
expect(members.map(&:client_id)).to_not include(left_client_id)
|
526
|
-
|
653
|
+
EventMachine.add_timer(1) do
|
654
|
+
presence_anonymous_client.unsubscribe
|
655
|
+
stop_reactor
|
656
|
+
end
|
527
657
|
end
|
528
658
|
|
529
659
|
channel_anonymous_client.attach do
|
@@ -544,7 +674,7 @@ describe Ably::Realtime::Presence, :event_machine do
|
|
544
674
|
|
545
675
|
context '#get' do
|
546
676
|
context 'with :wait_for_sync option set to true' do
|
547
|
-
it 'waits until sync is complete',
|
677
|
+
it 'waits until sync is complete', em_timeout: 15 do
|
548
678
|
enter_expected_count.times do |index|
|
549
679
|
presence_client_one.enter_client("client:#{index}") do |message|
|
550
680
|
entered << message
|
@@ -561,7 +691,7 @@ describe Ably::Realtime::Presence, :event_machine do
|
|
561
691
|
end
|
562
692
|
|
563
693
|
context 'by default' do
|
564
|
-
it 'it does not wait for sync',
|
694
|
+
it 'it does not wait for sync', em_timeout: 15 do
|
565
695
|
enter_expected_count.times do |index|
|
566
696
|
presence_client_one.enter_client("client:#{index}") do |message|
|
567
697
|
entered << message
|
@@ -656,7 +786,7 @@ describe Ably::Realtime::Presence, :event_machine do
|
|
656
786
|
end
|
657
787
|
|
658
788
|
it 'raises an exception if client_id is not set' do
|
659
|
-
expect { channel_anonymous_client.presence.enter }.to raise_error(Ably::Exceptions::
|
789
|
+
expect { channel_anonymous_client.presence.enter }.to raise_error(Ably::Exceptions::IncompatibleClientId, /without a client_id/)
|
660
790
|
stop_reactor
|
661
791
|
end
|
662
792
|
|
@@ -789,7 +919,7 @@ describe Ably::Realtime::Presence, :event_machine do
|
|
789
919
|
end
|
790
920
|
|
791
921
|
it 'raises an exception if not entered' do
|
792
|
-
expect {
|
922
|
+
expect { channel_client_one.presence.leave }.to raise_error(Ably::Exceptions::Standard, /Unable to leave presence channel that is not entered/)
|
793
923
|
stop_reactor
|
794
924
|
end
|
795
925
|
|
@@ -824,8 +954,10 @@ describe Ably::Realtime::Presence, :event_machine do
|
|
824
954
|
|
825
955
|
context 'entering/updating/leaving presence state on behalf of another client_id' do
|
826
956
|
let(:client_count) { 5 }
|
827
|
-
let(:clients)
|
828
|
-
let(:data)
|
957
|
+
let(:clients) { [] }
|
958
|
+
let(:data) { random_str }
|
959
|
+
let(:client_one) { auto_close Ably::Realtime::Client.new(client_options.merge(auth_callback: wildcard_token)) }
|
960
|
+
let(:client_two) { auto_close Ably::Realtime::Client.new(client_options.merge(auth_callback: wildcard_token)) }
|
829
961
|
|
830
962
|
context '#enter_client' do
|
831
963
|
context 'multiple times on the same channel with different client_ids' do
|
@@ -875,8 +1007,6 @@ describe Ably::Realtime::Presence, :event_machine do
|
|
875
1007
|
end
|
876
1008
|
end
|
877
1009
|
|
878
|
-
it_should_behave_like 'a public presence method', :enter_client, nil, 'client_id'
|
879
|
-
|
880
1010
|
context 'without necessary capabilities to enter on behalf of another client' do
|
881
1011
|
let(:restricted_client) do
|
882
1012
|
auto_close Ably::Realtime::Client.new(default_options.merge(key: restricted_api_key, log_level: :fatal))
|
@@ -891,6 +1021,9 @@ describe Ably::Realtime::Presence, :event_machine do
|
|
891
1021
|
end
|
892
1022
|
end
|
893
1023
|
end
|
1024
|
+
|
1025
|
+
it_should_behave_like 'a public presence method', :enter_client, nil, 'client_id'
|
1026
|
+
it_should_behave_like 'a presence on behalf of another client method', :enter_client
|
894
1027
|
end
|
895
1028
|
|
896
1029
|
context '#update_client' do
|
@@ -955,6 +1088,7 @@ describe Ably::Realtime::Presence, :event_machine do
|
|
955
1088
|
end
|
956
1089
|
|
957
1090
|
it_should_behave_like 'a public presence method', :update_client, nil, 'client_id'
|
1091
|
+
it_should_behave_like 'a presence on behalf of another client method', :update_client
|
958
1092
|
end
|
959
1093
|
|
960
1094
|
context '#leave_client' do
|
@@ -1048,6 +1182,7 @@ describe Ably::Realtime::Presence, :event_machine do
|
|
1048
1182
|
end
|
1049
1183
|
|
1050
1184
|
it_should_behave_like 'a public presence method', :leave_client, nil, 'client_id'
|
1185
|
+
it_should_behave_like 'a presence on behalf of another client method', :leave_client
|
1051
1186
|
end
|
1052
1187
|
end
|
1053
1188
|
|
@@ -1091,10 +1226,11 @@ describe Ably::Realtime::Presence, :event_machine do
|
|
1091
1226
|
end
|
1092
1227
|
|
1093
1228
|
context 'during a sync' do
|
1094
|
-
let(:pages)
|
1095
|
-
let(:members_per_page)
|
1229
|
+
let(:pages) { 2 }
|
1230
|
+
let(:members_per_page) { 100 }
|
1096
1231
|
let(:sync_pages_received) { [] }
|
1097
|
-
let(:
|
1232
|
+
let(:client_one) { auto_close Ably::Realtime::Client.new(client_options.merge(auth_callback: wildcard_token)) }
|
1233
|
+
let(:client_options) { default_options.merge(log_level: :none) }
|
1098
1234
|
|
1099
1235
|
def connect_members_deferrables
|
1100
1236
|
(members_per_page * pages + 1).times.map do |index|
|
@@ -1102,15 +1238,6 @@ describe Ably::Realtime::Presence, :event_machine do
|
|
1102
1238
|
end
|
1103
1239
|
end
|
1104
1240
|
|
1105
|
-
before do
|
1106
|
-
# Reconfigure client library so that it makes no retry attempts and fails immediately
|
1107
|
-
stub_const 'Ably::Realtime::Connection::ConnectionManager::CONNECT_RETRY_CONFIG',
|
1108
|
-
Ably::Realtime::Connection::ConnectionManager::CONNECT_RETRY_CONFIG.merge(
|
1109
|
-
disconnected: { retry_every: 0.1, max_time_in_state: 0 },
|
1110
|
-
suspended: { retry_every: 0.1, max_time_in_state: 0 }
|
1111
|
-
)
|
1112
|
-
end
|
1113
|
-
|
1114
1241
|
context 'when :wait_for_sync is true' do
|
1115
1242
|
it 'fails if the connection fails' do
|
1116
1243
|
when_all(*connect_members_deferrables) do
|
@@ -1118,7 +1245,10 @@ describe Ably::Realtime::Presence, :event_machine do
|
|
1118
1245
|
client_two.connection.transport.__incoming_protocol_msgbus__.subscribe(:protocol_message) do |protocol_message|
|
1119
1246
|
if protocol_message.action == :sync
|
1120
1247
|
sync_pages_received << protocol_message
|
1121
|
-
|
1248
|
+
if sync_pages_received.count == 1
|
1249
|
+
error_message = Ably::Models::ProtocolMessage.new(action: 9, error: { message: 'force failure' })
|
1250
|
+
client_two.connection.__incoming_protocol_msgbus__.publish :protocol_message, error_message
|
1251
|
+
end
|
1122
1252
|
end
|
1123
1253
|
end
|
1124
1254
|
end
|
@@ -1196,22 +1326,22 @@ describe Ably::Realtime::Presence, :event_machine do
|
|
1196
1326
|
end
|
1197
1327
|
|
1198
1328
|
it 'filters by client_id option if provided' do
|
1199
|
-
presence_client_one.enter
|
1200
|
-
presence_client_two.enter
|
1329
|
+
presence_client_one.enter do
|
1330
|
+
presence_client_two.enter
|
1201
1331
|
end
|
1202
1332
|
|
1203
1333
|
presence_client_one.subscribe(:enter) do |presence_message|
|
1204
1334
|
# wait until the client_two enter event has been sent to client_one
|
1205
|
-
next unless presence_message.client_id ==
|
1335
|
+
next unless presence_message.client_id == client_two_id
|
1206
1336
|
|
1207
|
-
presence_client_one.get(client_id:
|
1337
|
+
presence_client_one.get(client_id: client_one_id) do |members|
|
1208
1338
|
expect(members.count).to eq(1)
|
1209
|
-
expect(members.first.client_id).to eql(
|
1339
|
+
expect(members.first.client_id).to eql(client_one_id)
|
1210
1340
|
expect(members.first.connection_id).to eql(client_one.connection.id)
|
1211
1341
|
|
1212
|
-
presence_client_one.get(client_id:
|
1342
|
+
presence_client_one.get(client_id: client_two_id) do |members|
|
1213
1343
|
expect(members.count).to eq(1)
|
1214
|
-
expect(members.first.client_id).to eql(
|
1344
|
+
expect(members.first.client_id).to eql(client_two_id)
|
1215
1345
|
expect(members.first.connection_id).to eql(client_two.connection.id)
|
1216
1346
|
stop_reactor
|
1217
1347
|
end
|
@@ -1220,7 +1350,7 @@ describe Ably::Realtime::Presence, :event_machine do
|
|
1220
1350
|
end
|
1221
1351
|
|
1222
1352
|
it 'does not wait for SYNC to complete if :wait_for_sync option is false' do
|
1223
|
-
presence_client_one.enter
|
1353
|
+
presence_client_one.enter do
|
1224
1354
|
presence_client_two.get(wait_for_sync: false) do |members|
|
1225
1355
|
expect(members.count).to eql(0)
|
1226
1356
|
stop_reactor
|
@@ -1242,6 +1372,8 @@ describe Ably::Realtime::Presence, :event_machine do
|
|
1242
1372
|
end
|
1243
1373
|
|
1244
1374
|
context 'with lots of members on different clients' do
|
1375
|
+
let(:client_one) { auto_close Ably::Realtime::Client.new(client_options.merge(auth_callback: wildcard_token)) }
|
1376
|
+
let(:client_two) { auto_close Ably::Realtime::Client.new(client_options.merge(auth_callback: wildcard_token)) }
|
1245
1377
|
let(:members_per_client) { 10 }
|
1246
1378
|
let(:clients_entered) { Hash.new { |hash, key| hash[key] = 0 } }
|
1247
1379
|
let(:total_members) { members_per_client * 2 }
|
@@ -1588,7 +1720,7 @@ describe Ably::Realtime::Presence, :event_machine do
|
|
1588
1720
|
|
1589
1721
|
it 'resumes the SYNC operation', em_timeout: 15 do
|
1590
1722
|
when_all(*members_count.times.map do |index|
|
1591
|
-
|
1723
|
+
presence_anonymous_client.enter_client("client:#{index}")
|
1592
1724
|
end) do
|
1593
1725
|
channel_client_two.attach do
|
1594
1726
|
client_two.connection.transport.__incoming_protocol_msgbus__.subscribe(:protocol_message) do |protocol_message|
|