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.
Files changed (56) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +1 -1
  3. data/SPEC.md +1380 -631
  4. data/ably-rest.gemspec +11 -5
  5. data/lib/submodules/ably-ruby/.travis.yml +1 -1
  6. data/lib/submodules/ably-ruby/CHANGELOG.md +42 -48
  7. data/lib/submodules/ably-ruby/ably.gemspec +7 -1
  8. data/lib/submodules/ably-ruby/lib/ably.rb +2 -0
  9. data/lib/submodules/ably-ruby/lib/ably/auth.rb +155 -47
  10. data/lib/submodules/ably-ruby/lib/ably/exceptions.rb +2 -0
  11. data/lib/submodules/ably-ruby/lib/ably/models/channel_state_change.rb +2 -3
  12. data/lib/submodules/ably-ruby/lib/ably/models/connection_details.rb +54 -0
  13. data/lib/submodules/ably-ruby/lib/ably/models/protocol_message.rb +14 -4
  14. data/lib/submodules/ably-ruby/lib/ably/models/token_details.rb +13 -7
  15. data/lib/submodules/ably-ruby/lib/ably/models/token_request.rb +1 -2
  16. data/lib/submodules/ably-ruby/lib/ably/modules/ably.rb +3 -2
  17. data/lib/submodules/ably-ruby/lib/ably/modules/message_emitter.rb +1 -3
  18. data/lib/submodules/ably-ruby/lib/ably/modules/state_emitter.rb +2 -2
  19. data/lib/submodules/ably-ruby/lib/ably/realtime/auth.rb +6 -0
  20. data/lib/submodules/ably-ruby/lib/ably/realtime/channel.rb +15 -4
  21. data/lib/submodules/ably-ruby/lib/ably/realtime/channel/channel_manager.rb +2 -0
  22. data/lib/submodules/ably-ruby/lib/ably/realtime/client.rb +10 -3
  23. data/lib/submodules/ably-ruby/lib/ably/realtime/client/incoming_message_dispatcher.rb +11 -1
  24. data/lib/submodules/ably-ruby/lib/ably/realtime/connection.rb +62 -6
  25. data/lib/submodules/ably-ruby/lib/ably/realtime/connection/connection_manager.rb +58 -54
  26. data/lib/submodules/ably-ruby/lib/ably/realtime/presence.rb +18 -5
  27. data/lib/submodules/ably-ruby/lib/ably/rest/channel.rb +9 -1
  28. data/lib/submodules/ably-ruby/lib/ably/rest/client.rb +32 -14
  29. data/lib/submodules/ably-ruby/lib/ably/rest/presence.rb +1 -1
  30. data/lib/submodules/ably-ruby/lib/ably/version.rb +1 -1
  31. data/lib/submodules/ably-ruby/spec/acceptance/realtime/auth_spec.rb +251 -11
  32. data/lib/submodules/ably-ruby/spec/acceptance/realtime/channel_history_spec.rb +12 -2
  33. data/lib/submodules/ably-ruby/spec/acceptance/realtime/channel_spec.rb +316 -24
  34. data/lib/submodules/ably-ruby/spec/acceptance/realtime/client_spec.rb +93 -1
  35. data/lib/submodules/ably-ruby/spec/acceptance/realtime/connection_failures_spec.rb +177 -86
  36. data/lib/submodules/ably-ruby/spec/acceptance/realtime/connection_spec.rb +284 -60
  37. data/lib/submodules/ably-ruby/spec/acceptance/realtime/message_spec.rb +45 -6
  38. data/lib/submodules/ably-ruby/spec/acceptance/realtime/presence_history_spec.rb +4 -0
  39. data/lib/submodules/ably-ruby/spec/acceptance/realtime/presence_spec.rb +181 -49
  40. data/lib/submodules/ably-ruby/spec/acceptance/realtime/time_spec.rb +13 -0
  41. data/lib/submodules/ably-ruby/spec/acceptance/rest/auth_spec.rb +222 -4
  42. data/lib/submodules/ably-ruby/spec/acceptance/rest/channel_spec.rb +132 -1
  43. data/lib/submodules/ably-ruby/spec/acceptance/rest/client_spec.rb +129 -28
  44. data/lib/submodules/ably-ruby/spec/acceptance/rest/presence_spec.rb +7 -7
  45. data/lib/submodules/ably-ruby/spec/acceptance/rest/time_spec.rb +10 -0
  46. data/lib/submodules/ably-ruby/spec/shared/client_initializer_behaviour.rb +41 -17
  47. data/lib/submodules/ably-ruby/spec/spec_helper.rb +1 -0
  48. data/lib/submodules/ably-ruby/spec/support/debug_failure_helper.rb +16 -0
  49. data/lib/submodules/ably-ruby/spec/unit/models/connection_details_spec.rb +60 -0
  50. data/lib/submodules/ably-ruby/spec/unit/models/protocol_message_spec.rb +45 -0
  51. data/lib/submodules/ably-ruby/spec/unit/modules/event_emitter_spec.rb +3 -1
  52. data/lib/submodules/ably-ruby/spec/unit/realtime/channel_spec.rb +6 -5
  53. data/lib/submodules/ably-ruby/spec/unit/realtime/client_spec.rb +5 -1
  54. data/lib/submodules/ably-ruby/spec/unit/realtime/connection_spec.rb +5 -1
  55. data/lib/submodules/ably-ruby/spec/unit/realtime/realtime_spec.rb +5 -1
  56. 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 connection_ID', em_timeout: 10 do
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, connection_id: no_echo_client.connection.id)
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 => :none) }
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.001) do
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(:client_one) { auto_close Ably::Realtime::Client.new(client_options.merge(client_id: random_str)) }
13
- let(:client_two) { auto_close Ably::Realtime::Client.new(client_options.merge(client_id: random_str)) }
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: random_str)) }
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: random_str, :log_level => :error)) }
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, 'client_id', data: data)
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, 'client_id', data: data)
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
- force_connection_failure client_one
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
- stop_reactor
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
- stop_reactor
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
- stop_reactor
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', event_machine: 15 do
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', event_machine: 15 do
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::Standard, /without a client_id/)
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 { channel_anonymous_client.presence.leave }.to raise_error(Ably::Exceptions::Standard, /Unable to leave presence channel that is not entered/)
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) { random_str }
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) { 2 }
1095
- let(:members_per_page) { 100 }
1229
+ let(:pages) { 2 }
1230
+ let(:members_per_page) { 100 }
1096
1231
  let(:sync_pages_received) { [] }
1097
- let(:client_options) { default_options.merge(log_level: :none) }
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
- force_connection_failure client_two if sync_pages_received.count == 1
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(client_id: 'one') do
1200
- presence_client_two.enter client_id: 'two'
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 == 'two'
1335
+ next unless presence_message.client_id == client_two_id
1206
1336
 
1207
- presence_client_one.get(client_id: 'one') do |members|
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('one')
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: 'two') do |members|
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('two')
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(client_id: 'one') do
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
- presence_client_one.enter_client("client:#{index}")
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|