ably 0.8.4 → 0.8.5
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +1 -1
- data/Rakefile +1 -1
- data/lib/ably/auth.rb +23 -19
- data/lib/ably/models/token_details.rb +8 -6
- data/lib/ably/modules/conversions.rb +4 -0
- data/lib/ably/modules/state_emitter.rb +1 -1
- data/lib/ably/modules/uses_state_machine.rb +8 -1
- data/lib/ably/realtime/auth.rb +13 -13
- data/lib/ably/realtime/channel.rb +2 -2
- data/lib/ably/realtime/channel/channel_manager.rb +3 -3
- data/lib/ably/realtime/channel/channel_state_machine.rb +2 -1
- data/lib/ably/realtime/client/incoming_message_dispatcher.rb +13 -7
- data/lib/ably/realtime/client/outgoing_message_dispatcher.rb +6 -0
- data/lib/ably/realtime/connection.rb +4 -4
- data/lib/ably/realtime/connection/connection_manager.rb +9 -3
- data/lib/ably/realtime/connection/connection_state_machine.rb +1 -1
- data/lib/ably/realtime/presence.rb +4 -4
- data/lib/ably/rest/client.rb +2 -2
- data/lib/ably/version.rb +1 -1
- data/spec/acceptance/realtime/auth_spec.rb +9 -9
- data/spec/acceptance/realtime/channel_history_spec.rb +2 -2
- data/spec/acceptance/realtime/channel_spec.rb +13 -12
- data/spec/acceptance/realtime/channels_spec.rb +6 -2
- data/spec/acceptance/realtime/client_spec.rb +4 -3
- data/spec/acceptance/realtime/connection_failures_spec.rb +21 -15
- data/spec/acceptance/realtime/connection_spec.rb +31 -27
- data/spec/acceptance/realtime/message_spec.rb +31 -24
- data/spec/acceptance/realtime/presence_history_spec.rb +2 -2
- data/spec/acceptance/realtime/presence_spec.rb +10 -11
- data/spec/acceptance/realtime/stats_spec.rb +1 -1
- data/spec/acceptance/realtime/time_spec.rb +1 -1
- data/spec/acceptance/rest/auth_spec.rb +77 -46
- data/spec/acceptance/rest/channel_spec.rb +22 -3
- data/spec/acceptance/rest/client_spec.rb +6 -6
- data/spec/acceptance/rest/presence_spec.rb +9 -7
- data/spec/support/event_machine_helper.rb +30 -4
- data/spec/support/protocol_helper.rb +9 -6
- data/spec/unit/auth_spec.rb +1 -1
- data/spec/unit/models/token_details_spec.rb +8 -0
- data/spec/unit/modules/async_wrapper_spec.rb +1 -1
- 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(
|
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(
|
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)
|
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
|
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(:
|
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
|
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
|
-
|
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).
|
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
|
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)
|
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
|
741
|
-
expect(connection.error_reason.message).to match(/Invalid
|
742
|
-
expect(connection.error_reason.code).to eql(
|
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: '
|
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(/
|
756
|
-
expect(connection.error_reason.message).to match(/
|
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: :
|
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.
|
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.
|
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
|
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
|
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 |
|
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) {
|
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
|
-
|
431
|
-
|
432
|
-
expect(message.data).to eql(
|
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
|
435
|
-
stop_reactor if messages_received
|
430
|
+
messages_received << message
|
431
|
+
stop_reactor if messages_received.count == message_count
|
436
432
|
end
|
437
433
|
|
438
|
-
|
439
|
-
|
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
|
-
|
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 => :
|
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 |
|
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)
|
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(
|
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
|
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(
|
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(
|
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(
|
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(
|
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(
|
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
|
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(:
|
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
|
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(
|
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(
|
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(:
|
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(
|
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(
|
499
|
-
auth.authorise
|
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
|
534
|
-
expect(auth.
|
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.
|
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
|
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(
|
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(
|
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)
|