ably-rest 0.8.6 → 0.8.9

Sign up to get free protection for your applications and to get access to all the features.
Files changed (79) hide show
  1. checksums.yaml +4 -4
  2. data/SPEC.md +1049 -1001
  3. data/lib/submodules/ably-ruby/CHANGELOG.md +75 -3
  4. data/lib/submodules/ably-ruby/LICENSE +2 -2
  5. data/lib/submodules/ably-ruby/README.md +81 -20
  6. data/lib/submodules/ably-ruby/SPEC.md +1209 -693
  7. data/lib/submodules/ably-ruby/ably.gemspec +4 -4
  8. data/lib/submodules/ably-ruby/lib/ably/auth.rb +13 -4
  9. data/lib/submodules/ably-ruby/lib/ably/exceptions.rb +10 -1
  10. data/lib/submodules/ably-ruby/lib/ably/logger.rb +3 -1
  11. data/lib/submodules/ably-ruby/lib/ably/models/cipher_params.rb +114 -0
  12. data/lib/submodules/ably-ruby/lib/ably/models/connection_details.rb +10 -7
  13. data/lib/submodules/ably-ruby/lib/ably/models/error_info.rb +3 -3
  14. data/lib/submodules/ably-ruby/lib/ably/models/idiomatic_ruby_wrapper.rb +28 -21
  15. data/lib/submodules/ably-ruby/lib/ably/models/message.rb +19 -17
  16. data/lib/submodules/ably-ruby/lib/ably/models/message_encoders/cipher.rb +10 -9
  17. data/lib/submodules/ably-ruby/lib/ably/models/paginated_result.rb +27 -1
  18. data/lib/submodules/ably-ruby/lib/ably/models/presence_message.rb +20 -18
  19. data/lib/submodules/ably-ruby/lib/ably/models/protocol_message.rb +26 -19
  20. data/lib/submodules/ably-ruby/lib/ably/models/{stat.rb → stats.rb} +21 -19
  21. data/lib/submodules/ably-ruby/lib/ably/models/token_details.rb +14 -12
  22. data/lib/submodules/ably-ruby/lib/ably/models/token_request.rb +16 -14
  23. data/lib/submodules/ably-ruby/lib/ably/modules/async_wrapper.rb +2 -2
  24. data/lib/submodules/ably-ruby/lib/ably/modules/channels_collection.rb +11 -1
  25. data/lib/submodules/ably-ruby/lib/ably/modules/encodeable.rb +10 -10
  26. data/lib/submodules/ably-ruby/lib/ably/modules/enum.rb +18 -2
  27. data/lib/submodules/ably-ruby/lib/ably/modules/event_emitter.rb +3 -3
  28. data/lib/submodules/ably-ruby/lib/ably/modules/model_common.rb +13 -5
  29. data/lib/submodules/ably-ruby/lib/ably/modules/safe_deferrable.rb +1 -1
  30. data/lib/submodules/ably-ruby/lib/ably/modules/safe_yield.rb +2 -2
  31. data/lib/submodules/ably-ruby/lib/ably/modules/state_emitter.rb +8 -8
  32. data/lib/submodules/ably-ruby/lib/ably/modules/statesman_monkey_patch.rb +2 -2
  33. data/lib/submodules/ably-ruby/lib/ably/modules/uses_state_machine.rb +4 -2
  34. data/lib/submodules/ably-ruby/lib/ably/realtime.rb +1 -0
  35. data/lib/submodules/ably-ruby/lib/ably/realtime/auth.rb +6 -2
  36. data/lib/submodules/ably-ruby/lib/ably/realtime/channel.rb +7 -6
  37. data/lib/submodules/ably-ruby/lib/ably/realtime/channel/channel_manager.rb +7 -1
  38. data/lib/submodules/ably-ruby/lib/ably/realtime/client.rb +7 -12
  39. data/lib/submodules/ably-ruby/lib/ably/realtime/client/incoming_message_dispatcher.rb +9 -2
  40. data/lib/submodules/ably-ruby/lib/ably/realtime/client/outgoing_message_dispatcher.rb +7 -1
  41. data/lib/submodules/ably-ruby/lib/ably/realtime/connection.rb +19 -8
  42. data/lib/submodules/ably-ruby/lib/ably/realtime/connection/connection_manager.rb +16 -9
  43. data/lib/submodules/ably-ruby/lib/ably/realtime/connection/websocket_transport.rb +12 -3
  44. data/lib/submodules/ably-ruby/lib/ably/realtime/presence.rb +35 -64
  45. data/lib/submodules/ably-ruby/lib/ably/realtime/presence/members_map.rb +23 -9
  46. data/lib/submodules/ably-ruby/lib/ably/rest/channel.rb +9 -10
  47. data/lib/submodules/ably-ruby/lib/ably/rest/client.rb +1 -1
  48. data/lib/submodules/ably-ruby/lib/ably/rest/middleware/exceptions.rb +16 -4
  49. data/lib/submodules/ably-ruby/lib/ably/rest/presence.rb +7 -5
  50. data/lib/submodules/ably-ruby/lib/ably/util/crypto.rb +50 -40
  51. data/lib/submodules/ably-ruby/lib/ably/version.rb +1 -1
  52. data/lib/submodules/ably-ruby/spec/acceptance/realtime/channel_history_spec.rb +4 -4
  53. data/lib/submodules/ably-ruby/spec/acceptance/realtime/connection_failures_spec.rb +2 -4
  54. data/lib/submodules/ably-ruby/spec/acceptance/realtime/connection_spec.rb +46 -8
  55. data/lib/submodules/ably-ruby/spec/acceptance/realtime/message_spec.rb +20 -20
  56. data/lib/submodules/ably-ruby/spec/acceptance/realtime/presence_history_spec.rb +7 -7
  57. data/lib/submodules/ably-ruby/spec/acceptance/realtime/presence_spec.rb +114 -111
  58. data/lib/submodules/ably-ruby/spec/acceptance/rest/auth_spec.rb +9 -9
  59. data/lib/submodules/ably-ruby/spec/acceptance/rest/base_spec.rb +5 -5
  60. data/lib/submodules/ably-ruby/spec/acceptance/rest/channel_spec.rb +1 -1
  61. data/lib/submodules/ably-ruby/spec/acceptance/rest/client_spec.rb +1 -1
  62. data/lib/submodules/ably-ruby/spec/acceptance/rest/encoders_spec.rb +4 -4
  63. data/lib/submodules/ably-ruby/spec/acceptance/rest/message_spec.rb +15 -15
  64. data/lib/submodules/ably-ruby/spec/acceptance/rest/presence_spec.rb +4 -4
  65. data/lib/submodules/ably-ruby/spec/shared/model_behaviour.rb +7 -7
  66. data/lib/submodules/ably-ruby/spec/shared/safe_deferrable_behaviour.rb +4 -4
  67. data/lib/submodules/ably-ruby/spec/unit/models/cipher_params_spec.rb +140 -0
  68. data/lib/submodules/ably-ruby/spec/unit/models/idiomatic_ruby_wrapper_spec.rb +15 -8
  69. data/lib/submodules/ably-ruby/spec/unit/models/message_encoders/cipher_spec.rb +28 -22
  70. data/lib/submodules/ably-ruby/spec/unit/models/message_encoders/json_spec.rb +24 -0
  71. data/lib/submodules/ably-ruby/spec/unit/models/protocol_message_spec.rb +3 -3
  72. data/lib/submodules/ably-ruby/spec/unit/models/token_details_spec.rb +20 -18
  73. data/lib/submodules/ably-ruby/spec/unit/modules/event_emitter_spec.rb +2 -2
  74. data/lib/submodules/ably-ruby/spec/unit/modules/state_emitter_spec.rb +6 -6
  75. data/lib/submodules/ably-ruby/spec/unit/realtime/channel_spec.rb +4 -4
  76. data/lib/submodules/ably-ruby/spec/unit/realtime/connection_spec.rb +1 -1
  77. data/lib/submodules/ably-ruby/spec/unit/realtime/presence_spec.rb +5 -5
  78. data/lib/submodules/ably-ruby/spec/unit/util/crypto_spec.rb +50 -17
  79. metadata +5 -3
@@ -345,7 +345,7 @@ describe 'Ably::Realtime::Channel Message', :event_machine do
345
345
  let(:secret_key) { Base64.decode64(data['key']) }
346
346
  let(:iv) { Base64.decode64(data['iv']) }
347
347
 
348
- let(:cipher_options) { { key: secret_key, iv: iv, algorithm: algorithm, mode: mode, key_length: key_length } }
348
+ let(:cipher_options) { { key: secret_key, fixed_iv: iv, algorithm: algorithm, mode: mode, key_length: key_length } }
349
349
 
350
350
  context 'with #publish and #subscribe' do
351
351
  let(:encoded) { item['encoded'] }
@@ -372,7 +372,7 @@ describe 'Ably::Realtime::Channel Message', :event_machine do
372
372
  end
373
373
  end
374
374
 
375
- let(:encrypted_channel) { client.channel(channel_name, encrypted: true, cipher_params: cipher_options) }
375
+ let(:encrypted_channel) { client.channel(channel_name, cipher: cipher_options) }
376
376
 
377
377
  it 'encrypts message automatically before they are pushed to the server' do
378
378
  encrypted_channel.__incoming_msgbus__.unsubscribe # remove all subscribe callbacks that could decrypt the message
@@ -424,9 +424,9 @@ describe 'Ably::Realtime::Channel Message', :event_machine do
424
424
  end
425
425
 
426
426
  context 'with multiple sends from one client to another' do
427
- let(:cipher_options) { { key: random_str(32) } }
428
- let(:encrypted_channel_client1) { client.channel(channel_name, encrypted: true, cipher_params: cipher_options) }
429
- let(:encrypted_channel_client2) { other_client.channel(channel_name, encrypted: true, cipher_params: cipher_options) }
427
+ let(:cipher_options) { { key: Ably::Util::Crypto.generate_random_key } }
428
+ let(:encrypted_channel_client1) { client.channel(channel_name, cipher: cipher_options) }
429
+ let(:encrypted_channel_client2) { other_client.channel(channel_name, cipher: cipher_options) }
430
430
 
431
431
  let(:data) { { 'key' => random_str } }
432
432
  let(:message_count) { 50 }
@@ -471,9 +471,9 @@ describe 'Ably::Realtime::Channel Message', :event_machine do
471
471
  auto_close Ably::Realtime::Client.new(default_options.merge(protocol: other_protocol))
472
472
  end
473
473
 
474
- let(:cipher_options) { { key: random_str(32), algorithm: 'aes', mode: 'cbc', key_length: 256 } }
475
- let(:encrypted_channel_client1) { client.channel(channel_name, encrypted: true, cipher_params: cipher_options) }
476
- let(:encrypted_channel_client2) { other_client.channel(channel_name, encrypted: true, cipher_params: cipher_options) }
474
+ let(:cipher_options) { { key: Ably::Util::Crypto.generate_random_key, algorithm: 'aes', mode: 'cbc', key_length: 256 } }
475
+ let(:encrypted_channel_client1) { client.channel(channel_name, cipher: cipher_options) }
476
+ let(:encrypted_channel_client2) { other_client.channel(channel_name, cipher: cipher_options) }
477
477
 
478
478
  before do
479
479
  expect(other_client.protocol_binary?).to_not eql(client.protocol_binary?)
@@ -495,9 +495,9 @@ describe 'Ably::Realtime::Channel Message', :event_machine do
495
495
 
496
496
  context 'publishing on an unencrypted channel and subscribing on an encrypted channel with another client' do
497
497
  let(:client_options) { default_options.merge(log_level: :fatal) }
498
- let(:cipher_options) { { key: random_str(32), algorithm: 'aes', mode: 'cbc', key_length: 256 } }
498
+ let(:cipher_options) { { key: Ably::Util::Crypto.generate_random_key, algorithm: 'aes', mode: 'cbc', key_length: 256 } }
499
499
  let(:unencrypted_channel_client1) { client.channel(channel_name) }
500
- let(:encrypted_channel_client2) { other_client.channel(channel_name, encrypted: true, cipher_params: cipher_options) }
500
+ let(:encrypted_channel_client2) { other_client.channel(channel_name, cipher: cipher_options) }
501
501
 
502
502
  let(:payload) { MessagePack.pack({ 'key' => random_str }) }
503
503
 
@@ -513,8 +513,8 @@ describe 'Ably::Realtime::Channel Message', :event_machine do
513
513
 
514
514
  context 'publishing on an encrypted channel and subscribing on an unencrypted channel with another client' do
515
515
  let(:client_options) { default_options.merge(log_level: :fatal) }
516
- let(:cipher_options) { { key: random_str(32), algorithm: 'aes', mode: 'cbc', key_length: 256 } }
517
- let(:encrypted_channel_client1) { client.channel(channel_name, encrypted: true, cipher_params: cipher_options) }
516
+ let(:cipher_options) { { key: Ably::Util::Crypto.generate_random_key, algorithm: 'aes', mode: 'cbc', key_length: 256 } }
517
+ let(:encrypted_channel_client1) { client.channel(channel_name, cipher: Ably::Util::Crypto.get_default_params(cipher_options)) }
518
518
  let(:unencrypted_channel_client2) { other_client.channel(channel_name) }
519
519
 
520
520
  let(:payload) { MessagePack.pack({ 'key' => random_str }) }
@@ -543,10 +543,10 @@ describe 'Ably::Realtime::Channel Message', :event_machine do
543
543
 
544
544
  context 'publishing on an encrypted channel and subscribing with a different algorithm on another client' do
545
545
  let(:client_options) { default_options.merge(log_level: :fatal) }
546
- let(:cipher_options_client1) { { key: random_str(32), algorithm: 'aes', mode: 'cbc', key_length: 256 } }
547
- let(:encrypted_channel_client1) { client.channel(channel_name, encrypted: true, cipher_params: cipher_options_client1) }
548
- let(:cipher_options_client2) { { key: random_str(32), algorithm: 'aes', mode: 'cbc', key_length: 128 } }
549
- let(:encrypted_channel_client2) { other_client.channel(channel_name, encrypted: true, cipher_params: cipher_options_client2) }
546
+ let(:cipher_options_client1) { { key: Ably::Util::Crypto.generate_random_key, algorithm: 'aes', mode: 'cbc', key_length: 256 } }
547
+ let(:encrypted_channel_client1) { client.channel(channel_name, cipher: Ably::Util::Crypto.get_default_params(cipher_options_client1)) }
548
+ let(:cipher_options_client2) { { key: Ably::Util::Crypto.generate_random_key(128), algorithm: 'aes', mode: 'cbc', key_length: 128 } }
549
+ let(:encrypted_channel_client2) { other_client.channel(channel_name, cipher: Ably::Util::Crypto.get_default_params(cipher_options_client2)) }
550
550
 
551
551
  let(:payload) { MessagePack.pack({ 'key' => random_str }) }
552
552
 
@@ -574,10 +574,10 @@ describe 'Ably::Realtime::Channel Message', :event_machine do
574
574
 
575
575
  context 'publishing on an encrypted channel and subscribing with a different key on another client' do
576
576
  let(:client_options) { default_options.merge(log_level: :fatal) }
577
- let(:cipher_options_client1) { { key: random_str(32), algorithm: 'aes', mode: 'cbc', key_length: 256 } }
578
- let(:encrypted_channel_client1) { client.channel(channel_name, encrypted: true, cipher_params: cipher_options_client1) }
579
- let(:cipher_options_client2) { { key: random_str(32), algorithm: 'aes', mode: 'cbc', key_length: 256 } }
580
- let(:encrypted_channel_client2) { other_client.channel(channel_name, encrypted: true, cipher_params: cipher_options_client2) }
577
+ let(:cipher_options_client1) { { key: Ably::Util::Crypto.generate_random_key, algorithm: 'aes', mode: 'cbc', key_length: 256 } }
578
+ let(:encrypted_channel_client1) { client.channel(channel_name, cipher: cipher_options_client1) }
579
+ let(:cipher_options_client2) { { key: Ably::Util::Crypto.generate_random_key, algorithm: 'aes', mode: 'cbc', key_length: 256 } }
580
+ let(:encrypted_channel_client2) { other_client.channel(channel_name, cipher: cipher_options_client2) }
581
581
 
582
582
  let(:payload) { MessagePack.pack({ 'key' => random_str }) }
583
583
 
@@ -19,8 +19,8 @@ describe Ably::Realtime::Presence, 'history', :event_machine do
19
19
  let(:leave_data) { random_str }
20
20
 
21
21
  it 'provides up to the moment presence history' do
22
- presence_client_one.enter(data: data) do
23
- presence_client_one.leave(data: leave_data) do
22
+ presence_client_one.enter(data) do
23
+ presence_client_one.leave(leave_data) do
24
24
  presence_client_one.history do |history_page|
25
25
  expect(history_page).to be_a(Ably::Models::PaginatedResult)
26
26
  expect(history_page.items.count).to eql(2)
@@ -50,7 +50,7 @@ describe Ably::Realtime::Presence, 'history', :event_machine do
50
50
  end
51
51
  end
52
52
 
53
- presence_client_one.enter(data: data)
53
+ presence_client_one.enter(data)
54
54
  end
55
55
 
56
56
  context 'with option until_attach: true' do
@@ -59,8 +59,8 @@ describe Ably::Realtime::Presence, 'history', :event_machine do
59
59
  let(:presence_data_after_attach) { random_str }
60
60
 
61
61
  it 'retrieves all presence messages before channel was attached' do
62
- presence_client_two.enter(data: presence_data_before_attach) do
63
- presence_client_one.enter(data: presence_data_after_attach) do
62
+ presence_client_two.enter(presence_data_before_attach) do
63
+ presence_client_one.enter(presence_data_after_attach) do
64
64
  presence_client_one.history(until_attach: true) do |presence_page|
65
65
  expect(presence_page.items.count).to eql(1)
66
66
  expect(presence_page.items.first.data).to eql(presence_data_before_attach)
@@ -76,8 +76,8 @@ describe Ably::Realtime::Presence, 'history', :event_machine do
76
76
  let(:client_two) { auto_close Ably::Realtime::Client.new(default_options.merge(auth_callback: wildcard_token)) }
77
77
 
78
78
  it 'retrieves two pages of messages before channel was attached' do
79
- when_all(*10.times.map { |i| presence_client_two.enter_client("client:#{i}", data: presence_data_before_attach) }) do
80
- when_all(*10.times.map { |i| presence_client_one.enter_client("client:#{i}", data: presence_data_after_attach) }) do
79
+ when_all(*10.times.map { |i| presence_client_two.enter_client("client:#{i}", presence_data_before_attach) }) do
80
+ when_all(*10.times.map { |i| presence_client_one.enter_client("client:#{i}", presence_data_after_attach) }) do
81
81
  presence_client_one.history(until_attach: true, limit: 5) do |presence_page|
82
82
  expect(presence_page.items.count).to eql(5)
83
83
  expect(presence_page.items.map(&:data).uniq.first).to eql(presence_data_before_attach)
@@ -133,9 +133,9 @@ describe Ably::Realtime::Presence, :event_machine do
133
133
  context 'with supported data payload content type' do
134
134
  def register_presence_and_check_data(method_name, data)
135
135
  if method_name.to_s.match(/_client/)
136
- presence_client_one.public_send(method_name, client_id, data: data)
136
+ presence_client_one.public_send(method_name, client_id, data)
137
137
  else
138
- presence_client_one.public_send(method_name, data: data)
138
+ presence_client_one.public_send(method_name, data)
139
139
  end
140
140
 
141
141
  presence_client_one.subscribe do |presence_message|
@@ -188,9 +188,9 @@ describe Ably::Realtime::Presence, :event_machine do
188
188
  context 'with unsupported data payload content type' do
189
189
  def presence_action(method_name, data)
190
190
  if method_name.to_s.match(/_client/)
191
- presence_client_one.public_send(method_name, client_id, data: data)
191
+ presence_client_one.public_send(method_name, client_id, data)
192
192
  else
193
- presence_client_one.public_send(method_name, data: data)
193
+ presence_client_one.public_send(method_name, data)
194
194
  end
195
195
  end
196
196
 
@@ -509,7 +509,7 @@ describe Ably::Realtime::Presence, :event_machine do
509
509
  end
510
510
 
511
511
  context '250 existing (present) members on a channel (3 SYNC pages)' do
512
- context 'requires at least 3 SYNC ProtocolMessages' do
512
+ context 'requires at least 3 SYNC ProtocolMessages', em_timeout: 30 do
513
513
  let(:enter_expected_count) { 250 }
514
514
  let(:present) { [] }
515
515
  let(:entered) { [] }
@@ -518,15 +518,18 @@ describe Ably::Realtime::Presence, :event_machine do
518
518
 
519
519
  def setup_members_on(presence)
520
520
  enter_expected_count.times do |index|
521
- presence.enter_client("client:#{index}") do |message|
522
- entered << message
523
- next unless entered.count == enter_expected_count
524
- yield
521
+ # 10 messages per second max rate on simulation accounts
522
+ EventMachine.add_timer(index / 10) do
523
+ presence.enter_client("client:#{index}") do |message|
524
+ entered << message
525
+ next unless entered.count == enter_expected_count
526
+ yield
527
+ end
525
528
  end
526
529
  end
527
530
  end
528
531
 
529
- context 'when a client attaches to the presence channel', em_timeout: 10 do
532
+ context 'when a client attaches to the presence channel' do
530
533
  it 'emits :present for each member' do
531
534
  setup_members_on(presence_client_one) do
532
535
  presence_anonymous_client.subscribe(:present) do |present_message|
@@ -674,16 +677,18 @@ describe Ably::Realtime::Presence, :event_machine do
674
677
 
675
678
  context '#get' do
676
679
  context 'with :wait_for_sync option set to true' do
677
- it 'waits until sync is complete', em_timeout: 15 do
680
+ it 'waits until sync is complete', em_timeout: 30 do # allow for slow connections and lots of messages
678
681
  enter_expected_count.times do |index|
679
- presence_client_one.enter_client("client:#{index}") do |message|
680
- entered << message
681
- next unless entered.count == enter_expected_count
682
-
683
- presence_anonymous_client.get(wait_for_sync: true) do |members|
684
- expect(members.map(&:client_id).uniq.count).to eql(enter_expected_count)
685
- expect(members.count).to eql(enter_expected_count)
686
- stop_reactor
682
+ EventMachine.add_timer(index / 10) do
683
+ presence_client_one.enter_client("client:#{index}") do |message|
684
+ entered << message
685
+ next unless entered.count == enter_expected_count
686
+
687
+ presence_anonymous_client.get(wait_for_sync: true) do |members|
688
+ expect(members.map(&:client_id).uniq.count).to eql(enter_expected_count)
689
+ expect(members.count).to eql(enter_expected_count)
690
+ stop_reactor
691
+ end
687
692
  end
688
693
  end
689
694
  end
@@ -691,17 +696,19 @@ describe Ably::Realtime::Presence, :event_machine do
691
696
  end
692
697
 
693
698
  context 'by default' do
694
- it 'it does not wait for sync', em_timeout: 15 do
699
+ it 'it does not wait for sync', em_timeout: 30 do # allow for slow connections and lots of messages
695
700
  enter_expected_count.times do |index|
696
- presence_client_one.enter_client("client:#{index}") do |message|
697
- entered << message
698
- next unless entered.count == enter_expected_count
699
-
700
- channel_anonymous_client.attach do
701
- presence_anonymous_client.get do |members|
702
- expect(presence_anonymous_client.members).to_not be_in_sync
703
- expect(members.count).to eql(0)
704
- stop_reactor
701
+ EventMachine.add_timer(index / 10) do
702
+ presence_client_one.enter_client("client:#{index}") do |message|
703
+ entered << message
704
+ next unless entered.count == enter_expected_count
705
+
706
+ channel_anonymous_client.attach do
707
+ presence_anonymous_client.get do |members|
708
+ expect(presence_anonymous_client.members).to_not be_in_sync
709
+ expect(members.count).to eql(0)
710
+ stop_reactor
711
+ end
705
712
  end
706
713
  end
707
714
  end
@@ -738,21 +745,12 @@ describe Ably::Realtime::Presence, :event_machine do
738
745
  end
739
746
 
740
747
  context '#enter' do
741
- it 'allows client_id to be set on enter for anonymous clients' do
742
- channel_anonymous_client.presence.enter client_id: "123"
743
-
744
- channel_anonymous_client.presence.subscribe do |presence|
745
- expect(presence.client_id).to eq("123")
746
- stop_reactor
747
- end
748
- end
749
-
750
748
  context 'data attribute' do
751
749
  context 'when provided as argument option to #enter' do
752
- it 'remains intact following #leave' do
750
+ it 'changes to value provided in #leave' do
753
751
  leave_callback_called = false
754
752
 
755
- presence_client_one.enter(data: 'stored') do
753
+ presence_client_one.enter('stored') do
756
754
  expect(presence_client_one.data).to eql('stored')
757
755
 
758
756
  presence_client_one.leave do |presence|
@@ -760,7 +758,7 @@ describe Ably::Realtime::Presence, :event_machine do
760
758
  end
761
759
 
762
760
  presence_client_one.on(:left) do
763
- expect(presence_client_one.data).to eql('stored')
761
+ expect(presence_client_one.data).to eql(nil)
764
762
 
765
763
  EventMachine.next_tick do
766
764
  expect(leave_callback_called).to eql(true)
@@ -785,11 +783,6 @@ describe Ably::Realtime::Presence, :event_machine do
785
783
  end
786
784
  end
787
785
 
788
- it 'raises an exception if client_id is not set' do
789
- expect { channel_anonymous_client.presence.enter }.to raise_error(Ably::Exceptions::IncompatibleClientId, /without a client_id/)
790
- stop_reactor
791
- end
792
-
793
786
  context 'without necessary capabilities to join presence' do
794
787
  let(:restricted_client) do
795
788
  auto_close Ably::Realtime::Client.new(default_options.merge(key: restricted_api_key, log_level: :fatal))
@@ -798,7 +791,7 @@ describe Ably::Realtime::Presence, :event_machine do
798
791
  let(:restricted_presence) { restricted_channel.presence }
799
792
 
800
793
  it 'calls the Deferrable errback on capabilities failure' do
801
- restricted_presence.enter(client_id: 'clientId').tap do |deferrable|
794
+ restricted_presence.enter_client('bob').tap do |deferrable|
802
795
  deferrable.callback { raise "Should not succeed" }
803
796
  deferrable.errback { stop_reactor }
804
797
  end
@@ -810,7 +803,7 @@ describe Ably::Realtime::Presence, :event_machine do
810
803
 
811
804
  context '#update' do
812
805
  it 'without previous #enter automatically enters' do
813
- presence_client_one.update(data: data_payload) do
806
+ presence_client_one.update(data_payload) do
814
807
  EventMachine.add_timer(1) do
815
808
  expect(presence_client_one.state).to eq(:entered)
816
809
  stop_reactor
@@ -823,7 +816,7 @@ describe Ably::Realtime::Presence, :event_machine do
823
816
  presence_client_one.enter do
824
817
  presence_client_one.once_state_changed { fail 'State should not have changed ' }
825
818
 
826
- presence_client_one.update(data: data_payload) do
819
+ presence_client_one.update(data_payload) do
827
820
  EventMachine.add_timer(1) do
828
821
  expect(presence_client_one.state).to eq(:entered)
829
822
  presence_client_one.off
@@ -835,8 +828,8 @@ describe Ably::Realtime::Presence, :event_machine do
835
828
  end
836
829
 
837
830
  it 'updates the data if :data argument provided' do
838
- presence_client_one.enter(data: 'prior') do
839
- presence_client_one.update(data: data_payload)
831
+ presence_client_one.enter('prior') do
832
+ presence_client_one.update(data_payload)
840
833
  end
841
834
  presence_client_one.subscribe(:update) do |message|
842
835
  expect(message.data).to eql(data_payload)
@@ -845,7 +838,7 @@ describe Ably::Realtime::Presence, :event_machine do
845
838
  end
846
839
 
847
840
  it 'updates the data to nil if :data argument is not provided (assumes nil value)' do
848
- presence_client_one.enter(data: 'prior') do
841
+ presence_client_one.enter('prior') do
849
842
  presence_client_one.update
850
843
  end
851
844
  presence_client_one.subscribe(:update) do |message|
@@ -864,8 +857,8 @@ describe Ably::Realtime::Presence, :event_machine do
864
857
 
865
858
  context 'when set to a string' do
866
859
  it 'emits the new data for the leave event' do
867
- presence_client_one.enter data: enter_data do
868
- presence_client_one.leave data: data
860
+ presence_client_one.enter enter_data do
861
+ presence_client_one.leave data
869
862
  end
870
863
 
871
864
  presence_client_one.subscribe(:leave) do |presence_message|
@@ -876,9 +869,9 @@ describe Ably::Realtime::Presence, :event_machine do
876
869
  end
877
870
 
878
871
  context 'when set to nil' do
879
- it 'emits a nil value for the data attribute when leaving' do
880
- presence_client_one.enter data: enter_data do
881
- presence_client_one.leave data: nil
872
+ it 'emits the last value for the data attribute when leaving' do
873
+ presence_client_one.enter enter_data do
874
+ presence_client_one.leave nil
882
875
  end
883
876
 
884
877
  presence_client_one.subscribe(:leave) do |presence_message|
@@ -888,9 +881,9 @@ describe Ably::Realtime::Presence, :event_machine do
888
881
  end
889
882
  end
890
883
 
891
- context 'when not passed as an argument' do
892
- it 'emits the previously defined value as a convenience' do
893
- presence_client_one.enter data: enter_data do
884
+ context 'when not passed as an argument (i.e. nil)' do
885
+ it 'emits the previous value for the data attribute when leaving' do
886
+ presence_client_one.enter enter_data do
894
887
  presence_client_one.leave
895
888
  end
896
889
 
@@ -903,10 +896,10 @@ describe Ably::Realtime::Presence, :event_machine do
903
896
 
904
897
  context 'and sync is complete' do
905
898
  it 'does not cache members that have left' do
906
- presence_client_one.enter data: enter_data do
899
+ presence_client_one.enter enter_data do
907
900
  expect(presence_client_one.members).to be_in_sync
908
901
  expect(presence_client_one.members.send(:members).count).to eql(1)
909
- presence_client_one.leave data: data
902
+ presence_client_one.leave data
910
903
  end
911
904
 
912
905
  presence_client_one.subscribe(:leave) do |presence_message|
@@ -928,7 +921,7 @@ describe Ably::Realtime::Presence, :event_machine do
928
921
 
929
922
  context ':left event' do
930
923
  it 'emits the data defined in enter' do
931
- channel_client_one.presence.enter(data: 'data') do
924
+ channel_client_one.presence.enter('data') do
932
925
  channel_client_one.presence.leave
933
926
  end
934
927
 
@@ -939,8 +932,8 @@ describe Ably::Realtime::Presence, :event_machine do
939
932
  end
940
933
 
941
934
  it 'emits the data defined in update' do
942
- channel_client_one.presence.enter(data: 'something else') do
943
- channel_client_one.presence.update(data: 'data') do
935
+ channel_client_one.presence.enter('something else') do
936
+ channel_client_one.presence.update('data') do
944
937
  channel_client_one.presence.leave
945
938
  end
946
939
  end
@@ -977,7 +970,7 @@ describe Ably::Realtime::Presence, :event_machine do
977
970
 
978
971
  it 'enters a channel and sets the data based on the provided :data option' do
979
972
  client_count.times do |client_id|
980
- presence_client_one.enter_client("client:#{client_id}", data: data)
973
+ presence_client_one.enter_client("client:#{client_id}", data)
981
974
  end
982
975
 
983
976
  presence_anonymous_client.subscribe(:enter) do |presence|
@@ -1033,7 +1026,7 @@ describe Ably::Realtime::Presence, :event_machine do
1033
1026
 
1034
1027
  client_count.times do |client_id|
1035
1028
  presence_client_one.enter_client("client:#{client_id}") do
1036
- presence_client_one.update_client("client:#{client_id}", data: data) do
1029
+ presence_client_one.update_client("client:#{client_id}", data) do
1037
1030
  updated_callback_count += 1
1038
1031
  end
1039
1032
  end
@@ -1068,7 +1061,7 @@ describe Ably::Realtime::Presence, :event_machine do
1068
1061
  updated_callback_count = 0
1069
1062
 
1070
1063
  client_count.times do |client_id|
1071
- presence_client_one.update_client("client:#{client_id}", data: data) do
1064
+ presence_client_one.update_client("client:#{client_id}", data) do
1072
1065
  updated_callback_count += 1
1073
1066
  end
1074
1067
  end
@@ -1098,8 +1091,8 @@ describe Ably::Realtime::Presence, :event_machine do
1098
1091
  left_callback_count = 0
1099
1092
 
1100
1093
  client_count.times do |client_id|
1101
- presence_client_one.enter_client("client:#{client_id}", data: random_str) do
1102
- presence_client_one.leave_client("client:#{client_id}", data: data) do
1094
+ presence_client_one.enter_client("client:#{client_id}", random_str) do
1095
+ presence_client_one.leave_client("client:#{client_id}", data) do
1103
1096
  left_callback_count += 1
1104
1097
  end
1105
1098
  end
@@ -1143,8 +1136,8 @@ describe Ably::Realtime::Presence, :event_machine do
1143
1136
 
1144
1137
  context 'with a new value in :data option' do
1145
1138
  it 'emits the leave event with the new data value' do
1146
- presence_client_one.enter_client("client:unique", data: random_str) do
1147
- presence_client_one.leave_client("client:unique", data: data)
1139
+ presence_client_one.enter_client("client:unique", random_str) do
1140
+ presence_client_one.leave_client("client:unique", data)
1148
1141
  end
1149
1142
 
1150
1143
  presence_client_one.subscribe(:leave) do |presence_message|
@@ -1156,8 +1149,8 @@ describe Ably::Realtime::Presence, :event_machine do
1156
1149
 
1157
1150
  context 'with a nil value in :data option' do
1158
1151
  it 'emits the leave event with the previous value as a convenience' do
1159
- presence_client_one.enter_client("client:unique", data: data) do
1160
- presence_client_one.leave_client("client:unique", data: nil)
1152
+ presence_client_one.enter_client("client:unique", data) do
1153
+ presence_client_one.leave_client("client:unique", nil)
1161
1154
  end
1162
1155
 
1163
1156
  presence_client_one.subscribe(:leave) do |presence_message|
@@ -1169,7 +1162,7 @@ describe Ably::Realtime::Presence, :event_machine do
1169
1162
 
1170
1163
  context 'with no :data option' do
1171
1164
  it 'emits the leave event with the previous value as a convenience' do
1172
- presence_client_one.enter_client("client:unique", data: data) do
1165
+ presence_client_one.enter_client("client:unique", data) do
1173
1166
  presence_client_one.leave_client("client:unique")
1174
1167
  end
1175
1168
 
@@ -1225,7 +1218,7 @@ describe Ably::Realtime::Presence, :event_machine do
1225
1218
  end
1226
1219
  end
1227
1220
 
1228
- context 'during a sync' do
1221
+ context 'during a sync', em_timeout: 30 do
1229
1222
  let(:pages) { 2 }
1230
1223
  let(:members_per_page) { 100 }
1231
1224
  let(:sync_pages_received) { [] }
@@ -1234,7 +1227,15 @@ describe Ably::Realtime::Presence, :event_machine do
1234
1227
 
1235
1228
  def connect_members_deferrables
1236
1229
  (members_per_page * pages + 1).times.map do |index|
1237
- presence_client_one.enter_client("client:#{index}")
1230
+ # rate limit to 10 per second
1231
+ EventMachine::DefaultDeferrable.new.tap do |deferrable|
1232
+ EventMachine.add_timer(index / 10) do
1233
+ presence_client_one.enter_client("client:#{index}").tap do |enter_deferrable|
1234
+ enter_deferrable.callback { |*args| deferrable.succeed *args }
1235
+ enter_deferrable.errback { |*args| deferrable.fail *args }
1236
+ end
1237
+ end
1238
+ end
1238
1239
  end
1239
1240
  end
1240
1241
 
@@ -1316,9 +1317,9 @@ describe Ably::Realtime::Presence, :event_machine do
1316
1317
  expect(members.count).to eq(1)
1317
1318
  expect(members.first.connection_id).to eql(client_one.connection.id)
1318
1319
 
1319
- presence_client_one.get(connection_id: client_two.connection.id) do |members|
1320
- expect(members.count).to eq(1)
1321
- expect(members.first.connection_id).to eql(client_two.connection.id)
1320
+ presence_client_one.get(connection_id: client_two.connection.id) do |members_two|
1321
+ expect(members_two.count).to eq(1)
1322
+ expect(members_two.first.connection_id).to eql(client_two.connection.id)
1322
1323
  stop_reactor
1323
1324
  end
1324
1325
  end
@@ -1339,10 +1340,10 @@ describe Ably::Realtime::Presence, :event_machine do
1339
1340
  expect(members.first.client_id).to eql(client_one_id)
1340
1341
  expect(members.first.connection_id).to eql(client_one.connection.id)
1341
1342
 
1342
- presence_client_one.get(client_id: client_two_id) do |members|
1343
- expect(members.count).to eq(1)
1344
- expect(members.first.client_id).to eql(client_two_id)
1345
- expect(members.first.connection_id).to eql(client_two.connection.id)
1343
+ presence_client_one.get(client_id: client_two_id) do |members_two|
1344
+ expect(members_two.count).to eq(1)
1345
+ expect(members_two.first.client_id).to eql(client_two_id)
1346
+ expect(members_two.first.connection_id).to eql(client_two.connection.id)
1346
1347
  stop_reactor
1347
1348
  end
1348
1349
  end
@@ -1469,8 +1470,8 @@ describe Ably::Realtime::Presence, :event_machine do
1469
1470
  it 'removes the callback for all presence events' do
1470
1471
  when_all(channel_client_one.attach, channel_client_two.attach) do
1471
1472
  subscribe_callback = proc { raise 'Should not be called' }
1472
- presence_client_two.subscribe &subscribe_callback
1473
- presence_client_two.unsubscribe &subscribe_callback
1473
+ presence_client_two.subscribe(&subscribe_callback)
1474
+ presence_client_two.unsubscribe(&subscribe_callback)
1474
1475
 
1475
1476
  presence_client_one.enter
1476
1477
  presence_client_one.update
@@ -1504,7 +1505,7 @@ describe Ably::Realtime::Presence, :event_machine do
1504
1505
 
1505
1506
  context 'REST #get' do
1506
1507
  it 'returns current members' do
1507
- presence_client_one.enter(data: data_payload) do
1508
+ presence_client_one.enter(data_payload) do
1508
1509
  members_page = channel_rest_client_one.presence.get
1509
1510
  this_member = members_page.items.first
1510
1511
 
@@ -1517,7 +1518,7 @@ describe Ably::Realtime::Presence, :event_machine do
1517
1518
  end
1518
1519
 
1519
1520
  it 'returns no members once left' do
1520
- presence_client_one.enter(data: data_payload) do
1521
+ presence_client_one.enter(data_payload) do
1521
1522
  presence_client_one.leave do
1522
1523
  members_page = channel_rest_client_one.presence.get
1523
1524
  expect(members_page.items.count).to eql(0)
@@ -1547,32 +1548,34 @@ describe Ably::Realtime::Presence, :event_machine do
1547
1548
  let(:client_one) { auto_close Ably::Realtime::Client.new(default_options) }
1548
1549
 
1549
1550
  it 'is converted into UTF_8' do
1550
- presence_client_one.enter(client_id: client_id)
1551
- presence_client_one.on(:entered) do |presence|
1552
- expect(presence.client_id.encoding).to eql(Encoding::UTF_8)
1553
- expect(presence.client_id.encode(Encoding::ASCII_8BIT)).to eql(client_id)
1554
- stop_reactor
1551
+ channel_client_one.attach do
1552
+ presence_client_one.subscribe(:enter) do |presence|
1553
+ expect(presence.client_id.encoding).to eql(Encoding::UTF_8)
1554
+ expect(presence.client_id.encode(Encoding::ASCII_8BIT)).to eql(client_id)
1555
+ stop_reactor
1556
+ end
1557
+ presence_anonymous_client.enter_client(client_id)
1555
1558
  end
1556
1559
  end
1557
1560
  end
1558
1561
  end
1559
1562
 
1560
1563
  context 'encoding and decoding of presence message data' do
1561
- let(:secret_key) { random_str }
1564
+ let(:secret_key) { Ably::Util::Crypto.generate_random_key(256) }
1562
1565
  let(:cipher_options) { { key: secret_key, algorithm: 'aes', mode: 'cbc', key_length: 256 } }
1563
1566
  let(:channel_name) { random_str }
1564
- let(:encrypted_channel) { client_one.channel(channel_name, encrypted: true, cipher_params: cipher_options) }
1565
- let(:channel_rest_client_one) { client_one.rest_client.channel(channel_name, encrypted: true, cipher_params: cipher_options) }
1567
+ let(:encrypted_channel) { client_one.channel(channel_name, cipher: cipher_options) }
1568
+ let(:channel_rest_client_one) { client_one.rest_client.channel(channel_name, cipher: cipher_options) }
1566
1569
 
1567
1570
  let(:crypto) { Ably::Util::Crypto.new(cipher_options) }
1568
1571
 
1569
- let(:data) { { 'key' => random_str } }
1572
+ let(:data) { { 'hash_id' => random_str } }
1570
1573
  let(:data_as_json) { data.to_json }
1571
1574
  let(:data_as_cipher) { crypto.encrypt(data.to_json) }
1572
1575
 
1573
1576
  it 'encrypts presence message data' do
1574
1577
  encrypted_channel.attach do
1575
- encrypted_channel.presence.enter data: data
1578
+ encrypted_channel.presence.enter data
1576
1579
  end
1577
1580
 
1578
1581
  encrypted_channel.presence.__incoming_msgbus__.unsubscribe(:presence) # remove all subscribe callbacks that could decrypt the message
@@ -1591,7 +1594,7 @@ describe Ably::Realtime::Presence, :event_machine do
1591
1594
  context '#subscribe' do
1592
1595
  it 'emits decrypted enter events' do
1593
1596
  encrypted_channel.attach do
1594
- encrypted_channel.presence.enter data: data
1597
+ encrypted_channel.presence.enter data
1595
1598
  end
1596
1599
 
1597
1600
  encrypted_channel.presence.subscribe(:enter) do |presence_message|
@@ -1603,8 +1606,8 @@ describe Ably::Realtime::Presence, :event_machine do
1603
1606
 
1604
1607
  it 'emits decrypted update events' do
1605
1608
  encrypted_channel.attach do
1606
- encrypted_channel.presence.enter(data: 'to be updated') do
1607
- encrypted_channel.presence.update data: data
1609
+ encrypted_channel.presence.enter('to be updated') do
1610
+ encrypted_channel.presence.update data
1608
1611
  end
1609
1612
  end
1610
1613
 
@@ -1617,7 +1620,7 @@ describe Ably::Realtime::Presence, :event_machine do
1617
1620
 
1618
1621
  it 'emits previously set data for leave events' do
1619
1622
  encrypted_channel.attach do
1620
- encrypted_channel.presence.enter(data: data) do
1623
+ encrypted_channel.presence.enter(data) do
1621
1624
  encrypted_channel.presence.leave
1622
1625
  end
1623
1626
  end
@@ -1632,7 +1635,7 @@ describe Ably::Realtime::Presence, :event_machine do
1632
1635
 
1633
1636
  context '#get' do
1634
1637
  it 'returns a list of members with decrypted data' do
1635
- encrypted_channel.presence.enter(data: data) do
1638
+ encrypted_channel.presence.enter(data) do
1636
1639
  encrypted_channel.presence.get do |members|
1637
1640
  member = members.first
1638
1641
  expect(member.encoding).to be_nil
@@ -1645,7 +1648,7 @@ describe Ably::Realtime::Presence, :event_machine do
1645
1648
 
1646
1649
  context 'REST #get' do
1647
1650
  it 'returns a list of members with decrypted data' do
1648
- encrypted_channel.presence.enter(data: data) do
1651
+ encrypted_channel.presence.enter(data) do
1649
1652
  member = channel_rest_client_one.presence.get.items.first
1650
1653
  expect(member.encoding).to be_nil
1651
1654
  expect(member.data).to eql(data)
@@ -1656,11 +1659,11 @@ describe Ably::Realtime::Presence, :event_machine do
1656
1659
 
1657
1660
  context 'when cipher settings do not match publisher' do
1658
1661
  let(:client_options) { default_options.merge(log_level: :fatal) }
1659
- let(:incompatible_cipher_options) { { key: secret_key, algorithm: 'aes', mode: 'cbc', key_length: 128 } }
1660
- let(:incompatible_encrypted_channel) { client_two.channel(channel_name, encrypted: true, cipher_params: incompatible_cipher_options) }
1662
+ let(:incompatible_cipher_options) { { key: Ably::Util::Crypto.generate_random_key(128), algorithm: 'aes', mode: 'cbc', key_length: 128 } }
1663
+ let(:incompatible_encrypted_channel) { client_two.channel(channel_name, cipher: incompatible_cipher_options) }
1661
1664
 
1662
1665
  it 'delivers an unencoded presence message left with encoding value' do
1663
- encrypted_channel.presence.enter data: data
1666
+ encrypted_channel.presence.enter data
1664
1667
 
1665
1668
  incompatible_encrypted_channel.presence.subscribe(:enter) do
1666
1669
  incompatible_encrypted_channel.presence.get do |members|
@@ -1681,7 +1684,7 @@ describe Ably::Realtime::Presence, :event_machine do
1681
1684
  end
1682
1685
 
1683
1686
  encrypted_channel.attach do
1684
- encrypted_channel.presence.enter data: data
1687
+ encrypted_channel.presence.enter data
1685
1688
  end
1686
1689
  end
1687
1690
  end
@@ -1707,14 +1710,14 @@ describe Ably::Realtime::Presence, :event_machine do
1707
1710
  stop_reactor
1708
1711
  end
1709
1712
  end
1710
- presence_client_one.enter(data: data_payload) do
1713
+ presence_client_one.enter(data_payload) do
1711
1714
  presence_client_one.leave
1712
1715
  end
1713
1716
  end
1714
1717
  end
1715
1718
 
1716
1719
  context 'connection failure mid-way through a large member sync' do
1717
- let(:members_count) { 400 }
1720
+ let(:members_count) { 250 }
1718
1721
  let(:sync_pages_received) { [] }
1719
1722
  let(:client_options) { default_options.merge(log_level: :error) }
1720
1723
 
@@ -1726,7 +1729,7 @@ describe Ably::Realtime::Presence, :event_machine do
1726
1729
  client_two.connection.transport.__incoming_protocol_msgbus__.subscribe(:protocol_message) do |protocol_message|
1727
1730
  if protocol_message.action == :sync
1728
1731
  sync_pages_received << protocol_message
1729
- force_connection_failure client_two if sync_pages_received.count == 2
1732
+ force_connection_failure client_two if sync_pages_received.count == 1
1730
1733
  end
1731
1734
  end
1732
1735
  end