ably 0.8.4 → 0.8.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (42) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +1 -1
  3. data/Rakefile +1 -1
  4. data/lib/ably/auth.rb +23 -19
  5. data/lib/ably/models/token_details.rb +8 -6
  6. data/lib/ably/modules/conversions.rb +4 -0
  7. data/lib/ably/modules/state_emitter.rb +1 -1
  8. data/lib/ably/modules/uses_state_machine.rb +8 -1
  9. data/lib/ably/realtime/auth.rb +13 -13
  10. data/lib/ably/realtime/channel.rb +2 -2
  11. data/lib/ably/realtime/channel/channel_manager.rb +3 -3
  12. data/lib/ably/realtime/channel/channel_state_machine.rb +2 -1
  13. data/lib/ably/realtime/client/incoming_message_dispatcher.rb +13 -7
  14. data/lib/ably/realtime/client/outgoing_message_dispatcher.rb +6 -0
  15. data/lib/ably/realtime/connection.rb +4 -4
  16. data/lib/ably/realtime/connection/connection_manager.rb +9 -3
  17. data/lib/ably/realtime/connection/connection_state_machine.rb +1 -1
  18. data/lib/ably/realtime/presence.rb +4 -4
  19. data/lib/ably/rest/client.rb +2 -2
  20. data/lib/ably/version.rb +1 -1
  21. data/spec/acceptance/realtime/auth_spec.rb +9 -9
  22. data/spec/acceptance/realtime/channel_history_spec.rb +2 -2
  23. data/spec/acceptance/realtime/channel_spec.rb +13 -12
  24. data/spec/acceptance/realtime/channels_spec.rb +6 -2
  25. data/spec/acceptance/realtime/client_spec.rb +4 -3
  26. data/spec/acceptance/realtime/connection_failures_spec.rb +21 -15
  27. data/spec/acceptance/realtime/connection_spec.rb +31 -27
  28. data/spec/acceptance/realtime/message_spec.rb +31 -24
  29. data/spec/acceptance/realtime/presence_history_spec.rb +2 -2
  30. data/spec/acceptance/realtime/presence_spec.rb +10 -11
  31. data/spec/acceptance/realtime/stats_spec.rb +1 -1
  32. data/spec/acceptance/realtime/time_spec.rb +1 -1
  33. data/spec/acceptance/rest/auth_spec.rb +77 -46
  34. data/spec/acceptance/rest/channel_spec.rb +22 -3
  35. data/spec/acceptance/rest/client_spec.rb +6 -6
  36. data/spec/acceptance/rest/presence_spec.rb +9 -7
  37. data/spec/support/event_machine_helper.rb +30 -4
  38. data/spec/support/protocol_helper.rb +9 -6
  39. data/spec/unit/auth_spec.rb +1 -1
  40. data/spec/unit/models/token_details_spec.rb +8 -0
  41. data/spec/unit/modules/async_wrapper_spec.rb +1 -1
  42. metadata +2 -2
@@ -11,7 +11,7 @@ describe Ably::Realtime::Connection, :event_machine do
11
11
  end
12
12
 
13
13
  let(:client_options) { default_options }
14
- let(:client) { Ably::Realtime::Client.new(client_options) }
14
+ let(:client) { auto_close Ably::Realtime::Client.new(client_options) }
15
15
 
16
16
  before(:example) do
17
17
  EventMachine.add_shutdown_hook do
@@ -29,7 +29,7 @@ describe Ably::Realtime::Connection, :event_machine do
29
29
 
30
30
  context 'with :auto_connect option set to false' do
31
31
  let(:client) do
32
- Ably::Realtime::Client.new(default_options.merge(auto_connect: false))
32
+ auto_close Ably::Realtime::Client.new(default_options.merge(auto_connect: false))
33
33
  end
34
34
 
35
35
  it 'does not connect automatically' do
@@ -96,7 +96,7 @@ describe Ably::Realtime::Connection, :event_machine do
96
96
  stub_const 'Ably::Auth::TOKEN_DEFAULTS', Ably::Auth::TOKEN_DEFAULTS.merge(renew_token_buffer: 0)
97
97
 
98
98
  # Authorise synchronously to ensure token has been issued
99
- client.auth.authorise_sync(token_params: { ttl: ttl })
99
+ client.auth.authorise_sync(ttl: ttl)
100
100
  end
101
101
 
102
102
  let(:original_renew_token_buffer) { @original_renew_token_buffer }
@@ -158,7 +158,7 @@ describe Ably::Realtime::Connection, :event_machine do
158
158
  context 'when connected with a valid non-expired token' do
159
159
  context 'that then expires following the connection being opened' do
160
160
  let(:ttl) { 5 }
161
- let(:channel) { client.channel('test') }
161
+ let(:channel) { client.channel(random_str) }
162
162
 
163
163
  context 'the server' do
164
164
  it 'disconnects the client, and the client automatically renews the token and then reconnects', em_timeout: 15 do
@@ -204,7 +204,8 @@ describe Ably::Realtime::Connection, :event_machine do
204
204
 
205
205
  let!(:expired_token_details) do
206
206
  # Request a token synchronously
207
- Ably::Realtime::Client.new(default_options).auth.request_token_sync(token_params: { ttl: 0.01 })
207
+ token_client = auto_close Ably::Realtime::Client.new(default_options)
208
+ token_client.auth.request_token_sync(ttl: 0.01)
208
209
  end
209
210
 
210
211
  context 'opening a new connection' do
@@ -270,8 +271,7 @@ describe Ably::Realtime::Connection, :event_machine do
270
271
  end
271
272
 
272
273
  it 'calls the Deferrable callback on success' do
273
- connection.connect.callback do |connection|
274
- expect(connection).to be_a(Ably::Realtime::Connection)
274
+ connection.connect.callback do
275
275
  expect(connection.state).to eq(:connected)
276
276
  stop_reactor
277
277
  end
@@ -306,7 +306,8 @@ describe Ably::Realtime::Connection, :event_machine do
306
306
  end
307
307
 
308
308
  describe 'once connected' do
309
- let(:connection2) { Ably::Realtime::Client.new(client_options).connection }
309
+ let(:client2) { auto_close Ably::Realtime::Client.new(client_options) }
310
+ let(:connection2) { client2.connection }
310
311
 
311
312
  describe 'connection#id' do
312
313
  it 'is a string' do
@@ -436,7 +437,7 @@ describe Ably::Realtime::Connection, :event_machine do
436
437
 
437
438
  it 'calls the Deferrable callback on success' do
438
439
  connection.connect do
439
- connection.close.callback do |connection|
440
+ connection.close.callback do
440
441
  expect(connection).to be_a(Ably::Realtime::Connection)
441
442
  expect(connection.state).to eq(:closed)
442
443
  stop_reactor
@@ -576,7 +577,7 @@ describe Ably::Realtime::Connection, :event_machine do
576
577
  let(:channel_name) { random_str }
577
578
  let(:channel) { client.channel(channel_name) }
578
579
  let(:publishing_client) do
579
- Ably::Realtime::Client.new(client_options)
580
+ auto_close Ably::Realtime::Client.new(client_options)
580
581
  end
581
582
  let(:publishing_client_channel) { publishing_client.channel(channel_name) }
582
583
  let(:client_options) { default_options.merge(log_level: :fatal) }
@@ -594,9 +595,10 @@ describe Ably::Realtime::Connection, :event_machine do
594
595
  def self.available_states
595
596
  [:connecting, :connected, :disconnected, :suspended, :failed]
596
597
  end
597
- let(:available_states) { self.class.available_states}
598
+ let(:available_states) { self.class.available_states }
598
599
  let(:states) { Hash.new }
599
600
  let(:client_options) { default_options.merge(log_level: :none) }
601
+ let(:channel) { client.channel(random_str) }
600
602
 
601
603
  it 'is composed of connection key and serial that is kept up to date with each message ACK received' do
602
604
  connection.on(:connected) do
@@ -604,7 +606,7 @@ describe Ably::Realtime::Connection, :event_machine do
604
606
  expect(connection.key).to_not be_nil
605
607
  expect(connection.serial).to eql(expected_serial)
606
608
 
607
- client.channel('test').attach do |channel|
609
+ channel.attach do
608
610
  channel.publish('event', 'data') do
609
611
  expected_serial += 1 # attach message received
610
612
  expect(connection.serial).to eql(expected_serial)
@@ -670,9 +672,10 @@ describe Ably::Realtime::Connection, :event_machine do
670
672
  end
671
673
 
672
674
  connection.once(:failed) do
673
- recover_client = Ably::Realtime::Client.new(default_options.merge(recover: client.connection.recovery_key))
675
+ recover_client = auto_close Ably::Realtime::Client.new(default_options.merge(recover: client.connection.recovery_key))
674
676
  recover_client.connection.on(:connected) do
675
- expect(recover_client.connection.key).to eql(previous_connection_key)
677
+ expect(recover_client.connection.key[/^\w{5,}-/, 0]).to_not be_nil
678
+ expect(recover_client.connection.key[/^\w{5,}-/, 0]).to eql(previous_connection_key[/^\w{5,}-/, 0])
676
679
  expect(recover_client.connection.id).to eql(previous_connection_id)
677
680
  stop_reactor
678
681
  end
@@ -685,7 +688,7 @@ describe Ably::Realtime::Connection, :event_machine do
685
688
  end
686
689
 
687
690
  connection.once(:failed) do
688
- recover_client = Ably::Realtime::Client.new(default_options.merge(recover: client.connection.recovery_key))
691
+ recover_client = auto_close Ably::Realtime::Client.new(default_options.merge(recover: client.connection.recovery_key))
689
692
  recover_client.connection.on_resume do
690
693
  raise 'Should not call the resume callback'
691
694
  end
@@ -701,14 +704,15 @@ describe Ably::Realtime::Connection, :event_machine do
701
704
  let(:client_options) { default_options.merge(log_level: :none) }
702
705
 
703
706
  it 'recovers server-side queued messages' do
704
- channel.attach do |message|
707
+ channel.attach do
705
708
  connection.transition_state_machine! :failed
706
709
  end
707
710
 
708
711
  connection.on(:failed) do
709
712
  publishing_client_channel.publish('event', 'message') do
710
- recover_client = Ably::Realtime::Client.new(default_options.merge(recover: client.connection.recovery_key))
711
- recover_client.channel(channel_name).attach do |recover_client_channel|
713
+ recover_client = auto_close Ably::Realtime::Client.new(default_options.merge(recover: client.connection.recovery_key))
714
+ recover_client_channel = recover_client.channel(channel_name)
715
+ recover_client_channel.attach do
712
716
  recover_client_channel.subscribe('event') do |message|
713
717
  expect(message.data).to eql('message')
714
718
  stop_reactor
@@ -737,9 +741,9 @@ describe Ably::Realtime::Connection, :event_machine do
737
741
  it 'emits a fatal error on the connection object, sets the #error_reason and disconnects' do
738
742
  connection.once(:error) do |error|
739
743
  expect(connection.state).to eq(:failed)
740
- expect(error.message).to match(/Invalid connection key/)
741
- expect(connection.error_reason.message).to match(/Invalid connection key/)
742
- expect(connection.error_reason.code).to eql(40006)
744
+ expect(error.message).to match(/Invalid connectionKey/i)
745
+ expect(connection.error_reason.message).to match(/Invalid connectionKey/i)
746
+ expect(connection.error_reason.code).to eql(80018)
743
747
  expect(connection.error_reason).to eql(error)
744
748
  stop_reactor
745
749
  end
@@ -747,13 +751,13 @@ describe Ably::Realtime::Connection, :event_machine do
747
751
  end
748
752
 
749
753
  context 'with expired (missing) value sent to server' do
750
- let(:client_options) { default_options.merge(recover: '0123456789abcdef:0', log_level: :fatal) }
754
+ let(:client_options) { default_options.merge(recover: 'wVIsgTHAB1UvXh7z-1991d8586:0', log_level: :fatal) }
751
755
 
752
756
  it 'emits an error on the connection object, sets the #error_reason, yet will connect anyway' do
753
757
  connection.once(:error) do |error|
754
758
  expect(connection.state).to eq(:connected)
755
- expect(error.message).to match(/Invalid connection key/i)
756
- expect(connection.error_reason.message).to match(/Invalid connection key/i)
759
+ expect(error.message).to match(/Unable to recover connection/i)
760
+ expect(connection.error_reason.message).to match(/Unable to recover connection/i)
757
761
  expect(connection.error_reason.code).to eql(80008)
758
762
  expect(connection.error_reason).to eql(error)
759
763
  stop_reactor
@@ -1046,7 +1050,7 @@ describe Ably::Realtime::Connection, :event_machine do
1046
1050
  end
1047
1051
 
1048
1052
  context 'retry_in' do
1049
- let(:client_options) { default_options.merge(log_level: :debug) }
1053
+ let(:client_options) { default_options.merge(log_level: :error) }
1050
1054
 
1051
1055
  it 'is nil when a retry is not required' do
1052
1056
  connection.on(:connected) do |connection_state_change|
@@ -1061,7 +1065,7 @@ describe Ably::Realtime::Connection, :event_machine do
1061
1065
  expect(connection_state_change.retry_in).to eql(0)
1062
1066
  stop_reactor
1063
1067
  end
1064
- EventMachine.add_timer(0.001) { connection.transport.unbind }
1068
+ EventMachine.add_timer(0.005) { connection.transport.unbind }
1065
1069
  end
1066
1070
  end
1067
1071
 
@@ -1082,7 +1086,7 @@ describe Ably::Realtime::Connection, :event_machine do
1082
1086
  expect(connection_state_change.retry_in).to be > 0
1083
1087
  stop_reactor
1084
1088
  end
1085
- EventMachine.add_timer(0.001) { connection.transport.unbind }
1089
+ EventMachine.add_timer(0.005) { connection.transport.unbind }
1086
1090
  end
1087
1091
  connection.transport.unbind
1088
1092
  end
@@ -9,12 +9,12 @@ describe 'Ably::Realtime::Channel Message', :event_machine do
9
9
  let(:default_options) { options.merge(key: api_key, environment: environment, protocol: protocol) }
10
10
  let(:client_options) { default_options }
11
11
  let(:client) do
12
- Ably::Realtime::Client.new(client_options)
12
+ auto_close Ably::Realtime::Client.new(client_options)
13
13
  end
14
14
  let(:channel) { client.channel(channel_name) }
15
15
 
16
16
  let(:other_client) do
17
- Ably::Realtime::Client.new(client_options)
17
+ auto_close Ably::Realtime::Client.new(client_options)
18
18
  end
19
19
  let(:other_client_channel) { other_client.channel(channel_name) }
20
20
 
@@ -181,12 +181,12 @@ describe 'Ably::Realtime::Channel Message', :event_machine do
181
181
 
182
182
  context 'with :echo_messages option set to false' do
183
183
  let(:no_echo_client) do
184
- Ably::Realtime::Client.new(default_options.merge(echo_messages: false, log_level: :debug))
184
+ auto_close Ably::Realtime::Client.new(default_options.merge(echo_messages: false))
185
185
  end
186
186
  let(:no_echo_channel) { no_echo_client.channel(channel_name) }
187
187
 
188
188
  let(:rest_client) do
189
- Ably::Rest::Client.new(default_options.merge(log_level: :debug))
189
+ Ably::Rest::Client.new(default_options)
190
190
  end
191
191
 
192
192
  it 'will not echo messages to the client but will still broadcast messages to other connected clients', em_timeout: 10 do
@@ -275,7 +275,7 @@ describe 'Ably::Realtime::Channel Message', :event_machine do
275
275
 
276
276
  context 'without suitable publishing permissions' do
277
277
  let(:restricted_client) do
278
- Ably::Realtime::Client.new(options.merge(key: restricted_api_key, environment: environment, protocol: protocol, :log_level => :error))
278
+ auto_close Ably::Realtime::Client.new(options.merge(key: restricted_api_key, environment: environment, protocol: protocol, :log_level => :error))
279
279
  end
280
280
  let(:restricted_channel) { restricted_client.channel("cansubscribe:example") }
281
281
  let(:payload) { 'Test message without permission to publish' }
@@ -283,8 +283,7 @@ describe 'Ably::Realtime::Channel Message', :event_machine do
283
283
  it 'calls the error callback' do
284
284
  restricted_channel.attach do
285
285
  deferrable = restricted_channel.publish('test_event', payload)
286
- deferrable.errback do |message, error|
287
- expect(message.data).to eql(payload)
286
+ deferrable.errback do |error|
288
287
  expect(error.status).to eql(401)
289
288
  stop_reactor
290
289
  end
@@ -418,31 +417,39 @@ describe 'Ably::Realtime::Channel Message', :event_machine do
418
417
  let(:encrypted_channel_client1) { client.channel(channel_name, encrypted: true, cipher_params: cipher_options) }
419
418
  let(:encrypted_channel_client2) { other_client.channel(channel_name, encrypted: true, cipher_params: cipher_options) }
420
419
 
421
- let(:data) { MessagePack.pack({ 'key' => random_str }) }
420
+ let(:data) { { 'key' => random_str } }
422
421
  let(:message_count) { 50 }
423
422
 
424
423
  it 'encrypts and decrypts all messages' do
425
- messages_received = {
426
- decrypted: 0,
427
- encrypted: 0
428
- }
424
+ messages_received = []
429
425
 
430
- encrypted_channel_client2.attach do
431
- encrypted_channel_client2.subscribe do |message|
432
- expect(message.data).to eql("#{message.name}-#{data}")
426
+ encrypted_channel_client1.attach do
427
+ encrypted_channel_client1.subscribe do |message|
428
+ expect(message.data).to eql(MessagePack.pack(data.merge(index: message.name.to_i)))
433
429
  expect(message.encoding).to be_nil
434
- messages_received[:decrypted] += 1
435
- stop_reactor if messages_received[:decrypted] == message_count
430
+ messages_received << message
431
+ stop_reactor if messages_received.count == message_count
436
432
  end
437
433
 
438
- encrypted_channel_client1.__incoming_msgbus__.subscribe(:message) do |message|
439
- expect(message['encoding']).to match(/cipher\+/)
440
- messages_received[:encrypted] += 1
434
+ message_count.times do |index|
435
+ encrypted_channel_client2.publish index.to_s, MessagePack.pack(data.merge(index: index))
441
436
  end
442
437
  end
438
+ end
439
+
440
+ it 'receives raw messages with the correct encoding' do
441
+ encrypted_channel_client1.attach do
442
+ client.connection.__incoming_protocol_msgbus__.unsubscribe # remove all listeners
443
+ client.connection.__incoming_protocol_msgbus__.subscribe(:protocol_message) do |protocol_message|
444
+ if protocol_message.action == Ably::Models::ProtocolMessage::ACTION.Message
445
+ protocol_message.messages.each do |message|
446
+ expect(message['encoding']).to match(/cipher\+/)
447
+ end
448
+ stop_reactor
449
+ end
450
+ end
443
451
 
444
- message_count.times do |index|
445
- encrypted_channel_client2.publish index.to_s, "#{index}-#{data}"
452
+ encrypted_channel_client2.publish 'name', MessagePack.pack('data')
446
453
  end
447
454
  end
448
455
  end
@@ -450,7 +457,7 @@ describe 'Ably::Realtime::Channel Message', :event_machine do
450
457
  context 'subscribing with a different transport protocol' do
451
458
  let(:other_protocol) { protocol == :msgpack ? :json : :msgpack }
452
459
  let(:other_client) do
453
- Ably::Realtime::Client.new(default_options.merge(protocol: other_protocol))
460
+ auto_close Ably::Realtime::Client.new(default_options.merge(protocol: other_protocol))
454
461
  end
455
462
 
456
463
  let(:cipher_options) { { key: random_str(32), algorithm: 'aes', mode: 'cbc', key_length: 256 } }
@@ -592,7 +599,7 @@ describe 'Ably::Realtime::Channel Message', :event_machine do
592
599
  let(:event_name) { random_str }
593
600
  let(:message_state) { [] }
594
601
  let(:connection) { client.connection }
595
- let(:client_options) { default_options.merge(:log_level => :debug) }
602
+ let(:client_options) { default_options.merge(:log_level => :none) }
596
603
  let(:msgs_received) { [] }
597
604
 
598
605
  it 'publishes the message again, later receives the ACK and only one message is ever received from Ably' do
@@ -7,11 +7,11 @@ describe Ably::Realtime::Presence, 'history', :event_machine do
7
7
 
8
8
  let(:channel_name) { "persisted:#{random_str(2)}" }
9
9
 
10
- let(:client_one) { Ably::Realtime::Client.new(default_options.merge(client_id: random_str)) }
10
+ let(:client_one) { auto_close Ably::Realtime::Client.new(default_options.merge(client_id: random_str)) }
11
11
  let(:channel_client_one) { client_one.channel(channel_name) }
12
12
  let(:presence_client_one) { channel_client_one.presence }
13
13
 
14
- let(:client_two) { Ably::Realtime::Client.new(default_options.merge(client_id: random_str)) }
14
+ let(:client_two) { auto_close Ably::Realtime::Client.new(default_options.merge(client_id: random_str)) }
15
15
  let(:channel_client_two) { client_two.channel(channel_name) }
16
16
  let(:presence_client_two) { channel_client_two.presence }
17
17
 
@@ -8,9 +8,9 @@ describe Ably::Realtime::Presence, :event_machine do
8
8
  let(:default_options) { { key: api_key, environment: environment, protocol: protocol } }
9
9
  let(:client_options) { default_options }
10
10
 
11
- let(:anonymous_client) { Ably::Realtime::Client.new(client_options) }
12
- let(:client_one) { Ably::Realtime::Client.new(client_options.merge(client_id: random_str)) }
13
- let(:client_two) { Ably::Realtime::Client.new(client_options.merge(client_id: random_str)) }
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)) }
14
14
 
15
15
  let(:channel_name) { "presence-#{random_str(4)}" }
16
16
  let(:channel_anonymous_client) { anonymous_client.channel(channel_name) }
@@ -72,7 +72,7 @@ describe Ably::Realtime::Presence, :event_machine do
72
72
  end
73
73
 
74
74
  context 'when :queue_messages client option is false' do
75
- let(:client_one) { Ably::Realtime::Client.new(default_options.merge(queue_messages: false, client_id: random_str)) }
75
+ let(:client_one) { auto_close Ably::Realtime::Client.new(default_options.merge(queue_messages: false, client_id: random_str)) }
76
76
 
77
77
  context 'and connection state initialized' do
78
78
  it 'raises an exception' do
@@ -94,7 +94,7 @@ describe Ably::Realtime::Presence, :event_machine do
94
94
  end
95
95
 
96
96
  context 'and connection state disconnected' do
97
- let(:client_one) { Ably::Realtime::Client.new(default_options.merge(queue_messages: false, client_id: random_str, :log_level => :error)) }
97
+ let(:client_one) { auto_close Ably::Realtime::Client.new(default_options.merge(queue_messages: false, client_id: random_str, :log_level => :error)) }
98
98
 
99
99
  it 'raises an exception' do
100
100
  client_one.connection.once(:connected) do
@@ -277,8 +277,7 @@ describe Ably::Realtime::Presence, :event_machine do
277
277
 
278
278
  presence_client_one.public_send(method_name, args).tap do |deferrable|
279
279
  deferrable.callback { raise 'Should not succeed' }
280
- deferrable.errback do |presence, error|
281
- expect(presence).to be_a(Ably::Realtime::Presence)
280
+ deferrable.errback do |error|
282
281
  expect(error).to be_kind_of(Ably::Exceptions::BaseAblyException)
283
282
  stop_reactor
284
283
  end
@@ -663,7 +662,7 @@ describe Ably::Realtime::Presence, :event_machine do
663
662
 
664
663
  context 'without necessary capabilities to join presence' do
665
664
  let(:restricted_client) do
666
- Ably::Realtime::Client.new(default_options.merge(key: restricted_api_key, log_level: :fatal))
665
+ auto_close Ably::Realtime::Client.new(default_options.merge(key: restricted_api_key, log_level: :fatal))
667
666
  end
668
667
  let(:restricted_channel) { restricted_client.channel("cansubscribe:channel") }
669
668
  let(:restricted_presence) { restricted_channel.presence }
@@ -880,7 +879,7 @@ describe Ably::Realtime::Presence, :event_machine do
880
879
 
881
880
  context 'without necessary capabilities to enter on behalf of another client' do
882
881
  let(:restricted_client) do
883
- Ably::Realtime::Client.new(default_options.merge(key: restricted_api_key, log_level: :fatal))
882
+ auto_close Ably::Realtime::Client.new(default_options.merge(key: restricted_api_key, log_level: :fatal))
884
883
  end
885
884
  let(:restricted_channel) { restricted_client.channel("cansubscribe:channel") }
886
885
  let(:restricted_presence) { restricted_channel.presence }
@@ -1400,7 +1399,7 @@ describe Ably::Realtime::Presence, :event_machine do
1400
1399
  let(:client_id) { random_str.encode(Encoding::ASCII_8BIT) }
1401
1400
 
1402
1401
  context 'in connection set up' do
1403
- let(:client_one) { Ably::Realtime::Client.new(default_options.merge(client_id: client_id)) }
1402
+ let(:client_one) { auto_close Ably::Realtime::Client.new(default_options.merge(client_id: client_id)) }
1404
1403
 
1405
1404
  it 'is converted into UTF_8' do
1406
1405
  presence_client_one.enter
@@ -1413,7 +1412,7 @@ describe Ably::Realtime::Presence, :event_machine do
1413
1412
  end
1414
1413
 
1415
1414
  context 'in channel options' do
1416
- let(:client_one) { Ably::Realtime::Client.new(default_options) }
1415
+ let(:client_one) { auto_close Ably::Realtime::Client.new(default_options) }
1417
1416
 
1418
1417
  it 'is converted into UTF_8' do
1419
1418
  presence_client_one.enter(client_id: client_id)
@@ -3,7 +3,7 @@ require 'spec_helper'
3
3
  describe Ably::Realtime::Client, '#stats', :event_machine do
4
4
  vary_by_protocol do
5
5
  let(:client) do
6
- Ably::Realtime::Client.new(key: api_key, environment: environment, protocol: protocol)
6
+ auto_close Ably::Realtime::Client.new(key: api_key, environment: environment, protocol: protocol)
7
7
  end
8
8
 
9
9
  describe 'fetching stats' do
@@ -3,7 +3,7 @@ require 'spec_helper'
3
3
  describe Ably::Realtime::Client, '#time', :event_machine do
4
4
  vary_by_protocol do
5
5
  let(:client) do
6
- Ably::Realtime::Client.new(key: api_key, environment: environment, protocol: protocol)
6
+ auto_close Ably::Realtime::Client.new(key: api_key, environment: environment, protocol: protocol)
7
7
  end
8
8
 
9
9
  describe 'fetching the service time' do
@@ -27,7 +27,7 @@ describe Ably::Auth do
27
27
 
28
28
  vary_by_protocol do
29
29
  let(:default_options) { { environment: environment, protocol: protocol } }
30
- let(:client_options) { default_options.merge(key: api_key) }
30
+ let(:client_options) { default_options.merge(key: api_key) }
31
31
  let(:client) do
32
32
  Ably::Rest::Client.new(client_options)
33
33
  end
@@ -66,10 +66,10 @@ describe Ably::Auth do
66
66
  let(:capability) { { :foo => ['publish'] } }
67
67
 
68
68
  let(:token_details) do
69
- auth.request_token(token_params: {
69
+ auth.request_token(
70
70
  ttl: ttl,
71
71
  capability: capability
72
- })
72
+ )
73
73
  end
74
74
 
75
75
  it 'creates a TokenRequest automatically and sends it to Ably to obtain a token', webmock: true do
@@ -112,7 +112,7 @@ describe Ably::Auth do
112
112
  )
113
113
  end
114
114
 
115
- before { auth.request_token token_params: token_params }
115
+ before { auth.request_token token_params }
116
116
 
117
117
  it "overrides default and uses camelCase notation for attributes" do
118
118
  expect(request_token_stub).to have_been_requested
@@ -126,7 +126,7 @@ describe Ably::Auth do
126
126
  let(:nonce) { random_str }
127
127
  let(:auth_options) { { key: "#{key_name}:#{key_secret}" } }
128
128
  let(:token_params) { { nonce: nonce, timestamp: Time.now } }
129
- let(:token_request) { auth.create_token_request(auth_options, token_params) }
129
+ let(:token_request) { auth.create_token_request(token_params, auth_options) }
130
130
  let(:mac) do
131
131
  hmac_for(token_request, key_secret)
132
132
  end
@@ -142,7 +142,7 @@ describe Ably::Auth do
142
142
  :headers => { 'Content-Type' => content_type })
143
143
  end
144
144
 
145
- let!(:token) { auth.request_token(auth_options, token_params) }
145
+ let!(:token) { auth.request_token(token_params, auth_options) }
146
146
 
147
147
  specify 'key_name is used in request and signing uses key_secret' do
148
148
  expect(request_token_stub).to have_been_requested
@@ -156,7 +156,7 @@ describe Ably::Auth do
156
156
 
157
157
  let(:auth_options) { { key_name: key_name, key_secret: key_secret } }
158
158
  let(:token_params) { { nonce: nonce, timestamp: Time.now } }
159
- let(:token_request) { auth.create_token_request(auth_options, token_params) }
159
+ let(:token_request) { auth.create_token_request(token_params, auth_options) }
160
160
  let(:mac) do
161
161
  hmac_for(token_request, key_secret)
162
162
  end
@@ -172,7 +172,7 @@ describe Ably::Auth do
172
172
  :headers => { 'Content-Type' => content_type })
173
173
  end
174
174
 
175
- let!(:token) { auth.request_token(auth_options, token_params) }
175
+ let!(:token) { auth.request_token(token_params, auth_options) }
176
176
 
177
177
  specify 'key_name is used in request and signing uses key_secret' do
178
178
  expect(request_token_stub).to have_been_requested
@@ -184,7 +184,7 @@ describe Ably::Auth do
184
184
 
185
185
  it 'queries the server for the time' do
186
186
  expect(client).to receive(:time).and_call_original
187
- auth.request_token(options)
187
+ auth.request_token({}, options)
188
188
  end
189
189
  end
190
190
 
@@ -193,7 +193,7 @@ describe Ably::Auth do
193
193
 
194
194
  it 'does not query the server for the time' do
195
195
  expect(client).to_not receive(:time)
196
- auth.request_token(options)
196
+ auth.request_token({}, options)
197
197
  end
198
198
  end
199
199
 
@@ -237,7 +237,7 @@ describe Ably::Auth do
237
237
  end
238
238
 
239
239
  context 'when response from :auth_url is a valid token request' do
240
- let!(:token) { auth.request_token(auth_options) }
240
+ let!(:token) { auth.request_token({}, auth_options) }
241
241
 
242
242
  it 'requests a token from :auth_url using an HTTP GET request' do
243
243
  expect(request_token_stub).to have_been_requested
@@ -290,7 +290,7 @@ describe Ably::Auth do
290
290
  }.to_json
291
291
  end
292
292
 
293
- let!(:token_details) { auth.request_token(auth_options) }
293
+ let!(:token_details) { auth.request_token({}, auth_options) }
294
294
 
295
295
  it 'returns TokenDetails created from the token JSON' do
296
296
  expect(auth_url_request_stub).to have_been_requested
@@ -308,7 +308,7 @@ describe Ably::Auth do
308
308
  let(:auth_url_content_type) { 'text/plain' }
309
309
  let(:auth_url_response) { token }
310
310
 
311
- let!(:token_details) { auth.request_token(auth_options) }
311
+ let!(:token_details) { auth.request_token({}, auth_options) }
312
312
 
313
313
  it 'returns TokenDetails created from the token JSON' do
314
314
  expect(auth_url_request_stub).to have_been_requested
@@ -325,7 +325,7 @@ describe Ably::Auth do
325
325
  end
326
326
 
327
327
  it 'raises ServerError' do
328
- expect { auth.request_token auth_options }.to raise_error(Ably::Exceptions::ServerError)
328
+ expect { auth.request_token({}, auth_options) }.to raise_error(Ably::Exceptions::ServerError)
329
329
  end
330
330
  end
331
331
 
@@ -336,7 +336,7 @@ describe Ably::Auth do
336
336
  end
337
337
 
338
338
  it 'raises InvalidResponseBody' do
339
- expect { auth.request_token auth_options }.to raise_error(Ably::Exceptions::InvalidResponseBody)
339
+ expect { auth.request_token({}, auth_options) }.to raise_error(Ably::Exceptions::InvalidResponseBody)
340
340
  end
341
341
  end
342
342
  end
@@ -350,12 +350,12 @@ describe Ably::Auth do
350
350
  Proc.new do |token_params_arg|
351
351
  @block_called = true
352
352
  expect(token_params_arg).to eq(token_params)
353
- auth.create_token_request(token_params: { client_id: client_id })
353
+ auth.create_token_request(client_id: client_id)
354
354
  end
355
355
  end
356
356
  let(:token_params) { { ttl: ttl } }
357
357
  let!(:request_token) do
358
- auth.request_token(auth_callback: auth_callback, token_params: token_params)
358
+ auth.request_token(token_params, auth_callback: auth_callback)
359
359
  end
360
360
 
361
361
  it 'calls the Proc with token_params when authenticating to obtain the request token' do
@@ -369,7 +369,7 @@ describe Ably::Auth do
369
369
 
370
370
  context 'that returns a TokenDetails JSON object' do
371
371
  let(:client_id) { random_str }
372
- let(:options) { { client_id: client_id } }
372
+ let(:token_params){ { client_id: client_id } }
373
373
  let(:token) { 'J_0Tlg.D7AVZkdOZW-PqNNGvCSp38' }
374
374
  let(:issued) { Time.now }
375
375
  let(:expires) { Time.now + 60}
@@ -377,7 +377,7 @@ describe Ably::Auth do
377
377
  let(:capability_str) { JSON.dump(capability) }
378
378
 
379
379
  let!(:token_details) do
380
- auth.request_token(auth_callback: Proc.new do |token_params_arg|
380
+ auth.request_token(token_params, auth_callback: Proc.new do |token_params_arg|
381
381
  @block_called = true
382
382
  @block_params = token_params_arg
383
383
  {
@@ -388,12 +388,12 @@ describe Ably::Auth do
388
388
  'expires' => expires.to_i * 1000,
389
389
  'capability'=> capability_str
390
390
  }
391
- end, token_params: options)
391
+ end)
392
392
  end
393
393
 
394
394
  it 'calls the Proc when authenticating to obtain the request token' do
395
395
  expect(@block_called).to eql(true)
396
- expect(@block_params).to include(options)
396
+ expect(@block_params).to include(token_params)
397
397
  end
398
398
 
399
399
  it 'uses the token request returned from the callback when requesting a new token' do
@@ -410,10 +410,8 @@ describe Ably::Auth do
410
410
  let(:client_id) { random_str }
411
411
 
412
412
  let!(:token_details) do
413
- auth.request_token(auth_callback: Proc.new do |block_options|
414
- auth.create_token_request(token_params: {
415
- client_id: client_id
416
- })
413
+ auth.request_token({}, auth_callback: Proc.new do |block_options|
414
+ auth.create_token_request(client_id: client_id)
417
415
  end)
418
416
  end
419
417
 
@@ -428,7 +426,7 @@ describe Ably::Auth do
428
426
  let(:token) { second_client.auth.request_token.token }
429
427
 
430
428
  let!(:token_details) do
431
- auth.request_token(auth_callback: Proc.new do |block_options|
429
+ auth.request_token({}, auth_callback: Proc.new do |block_options|
432
430
  token
433
431
  end)
434
432
  end
@@ -440,10 +438,9 @@ describe Ably::Auth do
440
438
  end
441
439
  end
442
440
 
443
- context 'persisted option', api_private: true do
441
+ context 'persisted option of token params', api_private: true do
444
442
  context 'when set to true', api_private: true do
445
- let(:options) { { persisted: true } }
446
- let(:token_details) { auth.request_token(token_params: options) }
443
+ let(:token_details) { auth.request_token(persisted: true) }
447
444
 
448
445
  it 'returns a token with a short token ID that is used to look up the token details' do
449
446
  expect(token_details.token.length).to be < 64
@@ -462,7 +459,7 @@ describe Ably::Auth do
462
459
 
463
460
  context 'with auth_option :client_id' do
464
461
  let(:client_id) { random_str }
465
- let(:token_details) { auth.request_token(client_id: client_id) }
462
+ let(:token_details) { auth.request_token({}, client_id: client_id) }
466
463
 
467
464
  it 'returns a token with the client_id' do
468
465
  expect(token_details.client_id).to eql(client_id)
@@ -471,7 +468,7 @@ describe Ably::Auth do
471
468
 
472
469
  context 'with token_param :client_id' do
473
470
  let(:client_id) { random_str }
474
- let(:token_details) { auth.request_token(token_params: { client_id: client_id }) }
471
+ let(:token_details) { auth.request_token(client_id: client_id) }
475
472
 
476
473
  it 'returns a token with the client_id' do
477
474
  expect(token_details.client_id).to eql(client_id)
@@ -495,8 +492,8 @@ describe Ably::Auth do
495
492
  end
496
493
 
497
494
  it 'passes all auth_options and token_params to #request_token' do
498
- expect(auth).to receive(:request_token).with(auth_options, token_params)
499
- auth.authorise auth_options, token_params
495
+ expect(auth).to receive(:request_token).with(token_params, auth_options)
496
+ auth.authorise token_params, auth_options
500
497
  end
501
498
 
502
499
  it 'returns a valid token' do
@@ -526,20 +523,26 @@ describe Ably::Auth do
526
523
  end
527
524
 
528
525
  it 'issues a new token if option :force => true' do
529
- expect { auth.authorise(force: true) }.to change { auth.current_token_details }
526
+ expect { auth.authorise({}, force: true) }.to change { auth.current_token_details }
530
527
  end
531
528
  end
532
529
 
533
- it 'updates the persisted auth options that are then used for subsequent authorise requests' do
534
- expect(auth.options[:ttl]).to_not eql(26)
530
+ it 'updates the persisted token params that are then used for subsequent authorise requests' do
531
+ expect(auth.token_params[:ttl]).to_not eql(26)
535
532
  auth.authorise(ttl: 26)
536
- expect(auth.options[:ttl]).to eql(26)
533
+ expect(auth.token_params[:ttl]).to eql(26)
534
+ end
535
+
536
+ it 'updates the persisted token params that are then used for subsequent authorise requests' do
537
+ expect(auth.options[:query_time]).to_not eql(true)
538
+ auth.authorise({}, query_time: true)
539
+ expect(auth.options[:query_time]).to eql(true)
537
540
  end
538
541
 
539
542
  context 'with a Proc for the :auth_callback option' do
540
543
  let(:client_id) { random_str }
541
544
  let!(:token) do
542
- auth.authorise(auth_callback: Proc.new do
545
+ auth.authorise({}, auth_callback: Proc.new do
543
546
  @block_called ||= 0
544
547
  @block_called += 1
545
548
  auth.create_token_request(client_id: client_id)
@@ -564,13 +567,41 @@ describe Ably::Auth do
564
567
 
565
568
  context 'with a provided block' do
566
569
  it 'does not call the originally provided Proc and calls the new #request_token :auth_callback Proc' do
567
- auth.request_token(auth_callback: Proc.new { @request_block_called = true; auth.create_token_request })
570
+ auth.request_token({}, auth_callback: Proc.new { @request_block_called = true; auth.create_token_request })
568
571
  expect(@block_called).to eql(1)
569
572
  expect(@request_block_called).to eql(true)
570
573
  end
571
574
  end
572
575
  end
573
576
  end
577
+
578
+ context 'with an explicit token string that expires' do
579
+ context 'and a Proc for the :auth_callback option to provide a means to renew the token' do
580
+ before do
581
+ # Ensure a soon to expire token is not treated as expired
582
+ stub_const 'Ably::Models::TokenDetails::TOKEN_EXPIRY_BUFFER', 0
583
+ old_token_defaults = Ably::Auth::TOKEN_DEFAULTS
584
+ stub_const 'Ably::Auth::TOKEN_DEFAULTS', old_token_defaults.merge(renew_token_buffer: 0)
585
+ end
586
+
587
+ let(:token_client) { Ably::Rest::Client.new(default_options.merge(key: api_key, token_params: { ttl: 3 })) }
588
+ let(:client_options) {
589
+ default_options.merge(token: token_client.auth.request_token.token, auth_callback: Proc.new do
590
+ @block_called ||= 0
591
+ @block_called += 1
592
+ token_client.auth.create_token_request
593
+ end)
594
+ }
595
+
596
+ it 'calls the Proc once the token has expired and the new token is used' do
597
+ client.stats
598
+ expect(@block_called).to be_nil
599
+ sleep 3.5
600
+ expect { client.stats }.to change { client.auth.current_token_details }
601
+ expect(@block_called).to eql(1)
602
+ end
603
+ end
604
+ end
574
605
  end
575
606
 
576
607
  describe '#create_token_request' do
@@ -578,7 +609,7 @@ describe Ably::Auth do
578
609
  let(:capability) { { "foo" => ["publish"] } }
579
610
  let(:token_params) { Hash.new }
580
611
 
581
- subject { auth.create_token_request(token_params: token_params) }
612
+ subject { auth.create_token_request(token_params) }
582
613
 
583
614
  it 'returns a TokenRequest object' do
584
615
  expect(subject).to be_a(Ably::Models::TokenRequest)
@@ -666,11 +697,11 @@ describe Ably::Auth do
666
697
  let(:client) { Ably::Rest::Client.new(auth_url: 'http://example.com', protocol: protocol) }
667
698
 
668
699
  it 'should raise an exception if key secret is missing' do
669
- expect { auth.create_token_request(key_name: 'name') }.to raise_error Ably::Exceptions::TokenRequestFailed
700
+ expect { auth.create_token_request({}, key_name: 'name') }.to raise_error Ably::Exceptions::TokenRequestFailed
670
701
  end
671
702
 
672
703
  it 'should raise an exception if key name is missing' do
673
- expect { auth.create_token_request(key_secret: 'secret') }.to raise_error Ably::Exceptions::TokenRequestFailed
704
+ expect { auth.create_token_request({}, key_secret: 'secret') }.to raise_error Ably::Exceptions::TokenRequestFailed
674
705
  end
675
706
  end
676
707
 
@@ -679,7 +710,7 @@ describe Ably::Auth do
679
710
  let(:time) { Time.now - 30 }
680
711
  let(:auth_options) { { query_time: true } }
681
712
 
682
- subject { auth.create_token_request(auth_options) }
713
+ subject { auth.create_token_request({}, auth_options) }
683
714
 
684
715
  it 'queries the server for the timestamp' do
685
716
  expect(client).to receive(:time).and_return(time)
@@ -733,10 +764,10 @@ describe Ably::Auth do
733
764
  describe 'with :token option' do
734
765
  let(:ttl) { 60 * 60 }
735
766
  let(:token_details) do
736
- auth.request_token(token_params: {
767
+ auth.request_token(
737
768
  ttl: ttl,
738
769
  capability: capability
739
- })
770
+ )
740
771
  end
741
772
  let(:token) { token_details.token }
742
773
  let(:token_auth_client) do
@@ -756,7 +787,7 @@ describe Ably::Auth do
756
787
  end
757
788
 
758
789
  it 'fails if timestamp is invalid' do
759
- expect { auth.request_token(token_params: { timestamp: Time.now - 180 }) }.to raise_error do |error|
790
+ expect { auth.request_token(timestamp: Time.now - 180) }.to raise_error do |error|
760
791
  expect(error).to be_a(Ably::Exceptions::InvalidRequest)
761
792
  expect(error.status).to eql(401)
762
793
  expect(error.code).to eql(40101)