ably-rest 0.8.2 → 0.8.3
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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +1 -43
- data/SPEC.md +707 -580
- data/lib/submodules/ably-ruby/.travis.yml +1 -0
- data/lib/submodules/ably-ruby/CHANGELOG.md +143 -3
- data/lib/submodules/ably-ruby/README.md +1 -1
- data/lib/submodules/ably-ruby/SPEC.md +842 -520
- data/lib/submodules/ably-ruby/ably.gemspec +1 -1
- data/lib/submodules/ably-ruby/lib/ably/auth.rb +114 -87
- data/lib/submodules/ably-ruby/lib/ably/exceptions.rb +40 -14
- data/lib/submodules/ably-ruby/lib/ably/models/message.rb +3 -5
- data/lib/submodules/ably-ruby/lib/ably/models/paginated_result.rb +3 -12
- data/lib/submodules/ably-ruby/lib/ably/models/presence_message.rb +8 -2
- data/lib/submodules/ably-ruby/lib/ably/models/protocol_message.rb +15 -3
- data/lib/submodules/ably-ruby/lib/ably/models/stat.rb +1 -1
- data/lib/submodules/ably-ruby/lib/ably/models/token_details.rb +1 -1
- data/lib/submodules/ably-ruby/lib/ably/modules/channels_collection.rb +7 -1
- data/lib/submodules/ably-ruby/lib/ably/modules/conversions.rb +1 -1
- data/lib/submodules/ably-ruby/lib/ably/modules/encodeable.rb +6 -3
- data/lib/submodules/ably-ruby/lib/ably/modules/message_pack.rb +2 -2
- data/lib/submodules/ably-ruby/lib/ably/modules/model_common.rb +1 -1
- data/lib/submodules/ably-ruby/lib/ably/modules/state_machine.rb +2 -2
- data/lib/submodules/ably-ruby/lib/ably/realtime.rb +1 -0
- data/lib/submodules/ably-ruby/lib/ably/realtime/auth.rb +191 -0
- data/lib/submodules/ably-ruby/lib/ably/realtime/channel.rb +97 -25
- data/lib/submodules/ably-ruby/lib/ably/realtime/channel/channel_manager.rb +11 -3
- data/lib/submodules/ably-ruby/lib/ably/realtime/client.rb +22 -6
- data/lib/submodules/ably-ruby/lib/ably/realtime/connection.rb +73 -40
- data/lib/submodules/ably-ruby/lib/ably/realtime/connection/connection_manager.rb +48 -33
- data/lib/submodules/ably-ruby/lib/ably/realtime/presence.rb +17 -3
- data/lib/submodules/ably-ruby/lib/ably/rest/channel.rb +43 -16
- data/lib/submodules/ably-ruby/lib/ably/rest/client.rb +57 -26
- data/lib/submodules/ably-ruby/lib/ably/rest/middleware/exceptions.rb +3 -1
- data/lib/submodules/ably-ruby/lib/ably/rest/middleware/fail_if_unsupported_mime_type.rb +4 -2
- data/lib/submodules/ably-ruby/lib/ably/rest/presence.rb +1 -0
- data/lib/submodules/ably-ruby/lib/ably/version.rb +1 -1
- data/lib/submodules/ably-ruby/spec/acceptance/realtime/auth_spec.rb +242 -0
- data/lib/submodules/ably-ruby/spec/acceptance/realtime/channel_spec.rb +277 -5
- data/lib/submodules/ably-ruby/spec/acceptance/realtime/channels_spec.rb +64 -0
- data/lib/submodules/ably-ruby/spec/acceptance/realtime/client_spec.rb +26 -5
- data/lib/submodules/ably-ruby/spec/acceptance/realtime/connection_failures_spec.rb +23 -6
- data/lib/submodules/ably-ruby/spec/acceptance/realtime/connection_spec.rb +167 -16
- data/lib/submodules/ably-ruby/spec/acceptance/realtime/message_spec.rb +9 -8
- data/lib/submodules/ably-ruby/spec/acceptance/realtime/presence_history_spec.rb +1 -0
- data/lib/submodules/ably-ruby/spec/acceptance/realtime/presence_spec.rb +121 -10
- data/lib/submodules/ably-ruby/spec/acceptance/realtime/stats_spec.rb +13 -1
- data/lib/submodules/ably-ruby/spec/acceptance/rest/auth_spec.rb +161 -79
- data/lib/submodules/ably-ruby/spec/acceptance/rest/base_spec.rb +3 -3
- data/lib/submodules/ably-ruby/spec/acceptance/rest/channel_spec.rb +142 -15
- data/lib/submodules/ably-ruby/spec/acceptance/rest/channels_spec.rb +23 -0
- data/lib/submodules/ably-ruby/spec/acceptance/rest/client_spec.rb +180 -18
- data/lib/submodules/ably-ruby/spec/acceptance/rest/message_spec.rb +8 -8
- data/lib/submodules/ably-ruby/spec/acceptance/rest/presence_spec.rb +136 -25
- data/lib/submodules/ably-ruby/spec/acceptance/rest/stats_spec.rb +60 -4
- data/lib/submodules/ably-ruby/spec/shared/client_initializer_behaviour.rb +54 -3
- data/lib/submodules/ably-ruby/spec/unit/auth_spec.rb +7 -6
- data/lib/submodules/ably-ruby/spec/unit/models/message_spec.rb +1 -9
- data/lib/submodules/ably-ruby/spec/unit/models/paginated_result_spec.rb +1 -18
- data/lib/submodules/ably-ruby/spec/unit/models/presence_message_spec.rb +1 -1
- data/lib/submodules/ably-ruby/spec/unit/models/protocol_message_spec.rb +21 -1
- data/lib/submodules/ably-ruby/spec/unit/realtime/channel_spec.rb +10 -3
- data/lib/submodules/ably-ruby/spec/unit/realtime/channels_spec.rb +27 -8
- data/lib/submodules/ably-ruby/spec/unit/rest/channel_spec.rb +0 -8
- data/lib/submodules/ably-ruby/spec/unit/rest/client_spec.rb +7 -7
- metadata +5 -2
@@ -167,12 +167,12 @@ describe Ably::Realtime::Connection, 'failures', :event_machine do
|
|
167
167
|
|
168
168
|
context 'when connection state is :failed' do
|
169
169
|
describe '#close' do
|
170
|
-
it 'will not transition state to :close and raises a
|
170
|
+
it 'will not transition state to :close and raises a InvalidStateChange exception' do
|
171
171
|
connection.on(:connected) { raise 'Connection should not have reached :connected state' }
|
172
172
|
|
173
173
|
connection.once(:failed) do
|
174
174
|
expect(connection.state).to eq(:failed)
|
175
|
-
expect { connection.close }.to raise_error Ably::Exceptions::
|
175
|
+
expect { connection.close }.to raise_error Ably::Exceptions::InvalidStateChange, /Unable to transition from failed => closing/
|
176
176
|
stop_reactor
|
177
177
|
end
|
178
178
|
end
|
@@ -228,6 +228,8 @@ describe Ably::Realtime::Connection, 'failures', :event_machine do
|
|
228
228
|
end
|
229
229
|
|
230
230
|
context 'connection opening times out' do
|
231
|
+
let(:client_options) { client_failure_options }
|
232
|
+
|
231
233
|
it 'attempts to reconnect' do
|
232
234
|
started_at = Time.now
|
233
235
|
|
@@ -249,8 +251,6 @@ describe Ably::Realtime::Connection, 'failures', :event_machine do
|
|
249
251
|
end
|
250
252
|
|
251
253
|
context 'when retry intervals are stubbed to attempt reconnection quickly' do
|
252
|
-
let(:client_options) { client_failure_options }
|
253
|
-
|
254
254
|
before do
|
255
255
|
# Reconfigure client library retry periods and timeouts so that tests run quickly
|
256
256
|
stub_const 'Ably::Realtime::Connection::ConnectionManager::CONNECT_RETRY_CONFIG',
|
@@ -488,7 +488,8 @@ describe Ably::Realtime::Connection, 'failures', :event_machine do
|
|
488
488
|
when_all(*channels.map(&:attach)) do
|
489
489
|
detached_channels = []
|
490
490
|
channels.each do |channel|
|
491
|
-
channel.on(:detached) do
|
491
|
+
channel.on(:detached) do |error|
|
492
|
+
expect(error.message).to match(/Invalid connection key/i)
|
492
493
|
detached_channels << channel
|
493
494
|
next unless detached_channels.count == channel_count
|
494
495
|
expect(detached_channels.count).to eql(channel_count)
|
@@ -537,7 +538,7 @@ describe Ably::Realtime::Connection, 'failures', :event_machine do
|
|
537
538
|
|
538
539
|
context 'with custom realtime websocket host option' do
|
539
540
|
let(:expected_host) { 'this.host.does.not.exist' }
|
540
|
-
let(:client_options) { default_options.merge(realtime_host: expected_host, log_level: :none) }
|
541
|
+
let(:client_options) { default_options.merge(realtime_host: expected_host, :environment => :production, log_level: :none) }
|
541
542
|
|
542
543
|
it 'never uses a fallback host' do
|
543
544
|
expect(EventMachine).to receive(:connect).exactly(retry_count_for_all_states).times do |host|
|
@@ -551,6 +552,22 @@ describe Ably::Realtime::Connection, 'failures', :event_machine do
|
|
551
552
|
end
|
552
553
|
end
|
553
554
|
|
555
|
+
context 'with custom realtime websocket port option' do
|
556
|
+
let(:custom_port) { 666}
|
557
|
+
let(:client_options) { default_options.merge(tls_port: custom_port, :environment => :production, log_level: :none) }
|
558
|
+
|
559
|
+
it 'never uses a fallback host' do
|
560
|
+
expect(EventMachine).to receive(:connect).exactly(retry_count_for_all_states).times do |host, port|
|
561
|
+
expect(port).to eql(custom_port)
|
562
|
+
raise EventMachine::ConnectionError
|
563
|
+
end
|
564
|
+
|
565
|
+
connection.on(:failed) do
|
566
|
+
stop_reactor
|
567
|
+
end
|
568
|
+
end
|
569
|
+
end
|
570
|
+
|
554
571
|
context 'with non-production environment' do
|
555
572
|
let(:environment) { 'sandbox' }
|
556
573
|
let(:expected_host) { "#{environment}-#{Ably::Realtime::Client::DOMAIN}" }
|
@@ -52,9 +52,12 @@ describe Ably::Realtime::Connection, :event_machine do
|
|
52
52
|
before do
|
53
53
|
# Reduce token expiry buffer to zero so that a token expired? predicate is exact
|
54
54
|
# Normally there is a buffer so that a token expiring soon is considered expired
|
55
|
+
@original_token_expiry_buffer = Ably::Models::TokenDetails::TOKEN_EXPIRY_BUFFER
|
55
56
|
stub_const 'Ably::Models::TokenDetails::TOKEN_EXPIRY_BUFFER', 0
|
56
57
|
end
|
57
58
|
|
59
|
+
let(:original_token_expiry_buffer) { @original_token_expiry_buffer }
|
60
|
+
|
58
61
|
context 'for renewable tokens' do
|
59
62
|
context 'that are valid for the duration of the test' do
|
60
63
|
context 'with valid pre authorised token expiring in the future' do
|
@@ -71,7 +74,7 @@ describe Ably::Realtime::Connection, :event_machine do
|
|
71
74
|
let(:client_options) { default_options.merge(client_id: 'force_token_auth') }
|
72
75
|
|
73
76
|
it 'uses the token created by the implicit authorisation' do
|
74
|
-
expect(client.auth).to receive(:request_token).once.and_call_original
|
77
|
+
expect(client.rest_client.auth).to receive(:request_token).once.and_call_original
|
75
78
|
|
76
79
|
connection.once(:connected) do
|
77
80
|
stop_reactor
|
@@ -84,20 +87,36 @@ describe Ably::Realtime::Connection, :event_machine do
|
|
84
87
|
let(:client_options) { default_options.merge(log_level: :none) }
|
85
88
|
|
86
89
|
before do
|
87
|
-
client.
|
90
|
+
expect(client.rest_client.time.to_f).to be_within(2).of(Time.now.to_i), "Local clock is out of sync with Ably"
|
91
|
+
end
|
92
|
+
|
93
|
+
before do
|
94
|
+
# Ensure tokens issued expire immediately after issue
|
95
|
+
@original_renew_token_buffer = Ably::Auth::TOKEN_DEFAULTS.fetch(:renew_token_buffer)
|
96
|
+
stub_const 'Ably::Auth::TOKEN_DEFAULTS', Ably::Auth::TOKEN_DEFAULTS.merge(renew_token_buffer: 0)
|
97
|
+
|
98
|
+
# Authorise synchronously to ensure token has been issued
|
99
|
+
client.auth.authorise_sync(token_params: { ttl: ttl })
|
88
100
|
end
|
89
101
|
|
102
|
+
let(:original_renew_token_buffer) { @original_renew_token_buffer }
|
103
|
+
|
90
104
|
context 'opening a new connection' do
|
91
105
|
context 'with recently expired token' do
|
92
106
|
let(:ttl) { 2 }
|
93
107
|
|
94
|
-
it 'renews the token on connect' do
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
108
|
+
it 'renews the token on connect without changing connection state' do
|
109
|
+
connection.once(:connecting) do
|
110
|
+
sleep ttl + 0.1
|
111
|
+
expect(client.auth.current_token_details).to be_expired
|
112
|
+
expect(client.rest_client.auth).to receive(:authorise).at_least(:once).and_call_original
|
113
|
+
connection.once(:connected) do
|
114
|
+
expect(client.auth.current_token_details).to_not be_expired
|
115
|
+
stop_reactor
|
116
|
+
end
|
117
|
+
connection.once_state_changed do
|
118
|
+
raise "Invalid state #{connection.state}" unless connection.state == :connected
|
119
|
+
end
|
101
120
|
end
|
102
121
|
end
|
103
122
|
end
|
@@ -106,7 +125,7 @@ describe Ably::Realtime::Connection, :event_machine do
|
|
106
125
|
let(:ttl) { 0.001 }
|
107
126
|
|
108
127
|
it 'renews the token on connect, and only makes one subsequent attempt to obtain a new token' do
|
109
|
-
expect(client.auth).to receive(:authorise).at_least(:twice).and_call_original
|
128
|
+
expect(client.rest_client.auth).to receive(:authorise).at_least(:twice).and_call_original
|
110
129
|
connection.once(:disconnected) do
|
111
130
|
connection.once(:failed) do |error|
|
112
131
|
expect(error.code).to eql(40140) # token expired
|
@@ -149,6 +168,12 @@ describe Ably::Realtime::Connection, :event_machine do
|
|
149
168
|
connection.once(:connected) do
|
150
169
|
started_at = Time.now
|
151
170
|
connection.once(:disconnected) do |error|
|
171
|
+
expect(error.code).to eq(40140) # Token expired
|
172
|
+
|
173
|
+
# Token has expired, so now ensure it is not used again
|
174
|
+
stub_const 'Ably::Models::TokenDetails::TOKEN_EXPIRY_BUFFER', original_token_expiry_buffer
|
175
|
+
stub_const 'Ably::Auth::TOKEN_DEFAULTS', Ably::Auth::TOKEN_DEFAULTS.merge(renew_token_buffer: original_renew_token_buffer)
|
176
|
+
|
152
177
|
connection.once(:connected) do
|
153
178
|
expect(client.auth.current_token_details).to_not be_expired
|
154
179
|
expect(Time.now - started_at >= ttl)
|
@@ -159,6 +184,8 @@ describe Ably::Realtime::Connection, :event_machine do
|
|
159
184
|
end
|
160
185
|
end
|
161
186
|
|
187
|
+
connection.unsafe_once(:failed) { |error| fail error.inspect }
|
188
|
+
|
162
189
|
channel.attach
|
163
190
|
end
|
164
191
|
end
|
@@ -172,8 +199,13 @@ describe Ably::Realtime::Connection, :event_machine do
|
|
172
199
|
|
173
200
|
context 'for non-renewable tokens' do
|
174
201
|
context 'that are expired' do
|
202
|
+
before do
|
203
|
+
stub_const 'Ably::Auth::TOKEN_DEFAULTS', Ably::Auth::TOKEN_DEFAULTS.merge(renew_token_buffer: 0)
|
204
|
+
end
|
205
|
+
|
175
206
|
let!(:expired_token_details) do
|
176
|
-
|
207
|
+
# Request a token synchronously
|
208
|
+
Ably::Realtime::Client.new(default_options).auth.request_token_sync(token_params: { ttl: 0.01 })
|
177
209
|
end
|
178
210
|
|
179
211
|
context 'opening a new connection' do
|
@@ -260,6 +292,20 @@ describe Ably::Realtime::Connection, :event_machine do
|
|
260
292
|
end
|
261
293
|
end
|
262
294
|
|
295
|
+
describe 'connection#id' do
|
296
|
+
it 'is null before connecting' do
|
297
|
+
expect(connection.id).to be_nil
|
298
|
+
stop_reactor
|
299
|
+
end
|
300
|
+
end
|
301
|
+
|
302
|
+
describe 'connection#key' do
|
303
|
+
it 'is null before connecting' do
|
304
|
+
expect(connection.key).to be_nil
|
305
|
+
stop_reactor
|
306
|
+
end
|
307
|
+
end
|
308
|
+
|
263
309
|
describe 'once connected' do
|
264
310
|
let(:connection2) { Ably::Realtime::Client.new(client_options).connection }
|
265
311
|
|
@@ -326,6 +372,18 @@ describe Ably::Realtime::Connection, :event_machine do
|
|
326
372
|
end
|
327
373
|
end
|
328
374
|
end
|
375
|
+
|
376
|
+
context 'when closing' do
|
377
|
+
it 'raises an exception before the connection is closed' do
|
378
|
+
connection.connect do
|
379
|
+
connection.once(:closing) do
|
380
|
+
expect { connection.connect }.to raise_error Ably::Exceptions::InvalidStateChange
|
381
|
+
stop_reactor
|
382
|
+
end
|
383
|
+
connection.close
|
384
|
+
end
|
385
|
+
end
|
386
|
+
end
|
329
387
|
end
|
330
388
|
|
331
389
|
describe '#serial connection serial' do
|
@@ -339,7 +397,6 @@ describe Ably::Realtime::Connection, :event_machine do
|
|
339
397
|
end
|
340
398
|
|
341
399
|
context 'when a message is sent but the ACK has not yet been received' do
|
342
|
-
|
343
400
|
it 'the sent message msgSerial is 0 but the connection serial remains at -1' do
|
344
401
|
channel.attach do
|
345
402
|
connection.__outgoing_protocol_msgbus__.subscribe(:protocol_message) do |protocol_message|
|
@@ -732,13 +789,13 @@ describe Ably::Realtime::Connection, :event_machine do
|
|
732
789
|
context 'when a state transition is unsupported' do
|
733
790
|
let(:client_options) { default_options.merge(log_level: :none) } # silence FATAL errors
|
734
791
|
|
735
|
-
it 'emits a
|
792
|
+
it 'emits a InvalidStateChange' do
|
736
793
|
connection.connect do
|
737
794
|
connection.transition_state_machine :initialized
|
738
795
|
end
|
739
796
|
|
740
797
|
connection.on(:error) do |error|
|
741
|
-
expect(error).to be_a(Ably::Exceptions::
|
798
|
+
expect(error).to be_a(Ably::Exceptions::InvalidStateChange)
|
742
799
|
stop_reactor
|
743
800
|
end
|
744
801
|
end
|
@@ -794,16 +851,41 @@ describe Ably::Realtime::Connection, :event_machine do
|
|
794
851
|
end
|
795
852
|
|
796
853
|
context 'when the Internet is up' do
|
854
|
+
let(:client_options) { default_options.merge(tls: false, use_token_auth: true) }
|
855
|
+
|
856
|
+
context 'with a TLS connection' do
|
857
|
+
let(:client_options) { default_options.merge(tls: true) }
|
858
|
+
|
859
|
+
it 'checks the Internet up URL over TLS' do
|
860
|
+
expect(EventMachine::HttpRequest).to receive(:new).with("https:#{Ably::INTERNET_CHECK.fetch(:url)}").and_return(double('request', get: EventMachine::DefaultDeferrable.new))
|
861
|
+
connection.internet_up?
|
862
|
+
stop_reactor
|
863
|
+
end
|
864
|
+
end
|
865
|
+
|
866
|
+
context 'with a non-TLS connection' do
|
867
|
+
let(:client_options) { default_options.merge(tls: false, use_token_auth: true) }
|
868
|
+
|
869
|
+
it 'checks the Internet up URL over TLS' do
|
870
|
+
expect(EventMachine::HttpRequest).to receive(:new).with("http:#{Ably::INTERNET_CHECK.fetch(:url)}").and_return(double('request', get: EventMachine::DefaultDeferrable.new))
|
871
|
+
connection.internet_up?
|
872
|
+
stop_reactor
|
873
|
+
end
|
874
|
+
end
|
875
|
+
|
797
876
|
it 'calls the block with true' do
|
798
877
|
connection.internet_up? do |result|
|
799
878
|
expect(result).to be_truthy
|
800
|
-
stop_reactor
|
879
|
+
EventMachine.add_timer(0.2) { stop_reactor }
|
801
880
|
end
|
802
881
|
end
|
803
882
|
|
804
883
|
it 'calls the success callback of the Deferrable' do
|
805
884
|
connection.internet_up?.callback do
|
806
|
-
stop_reactor
|
885
|
+
EventMachine.add_timer(0.2) { stop_reactor }
|
886
|
+
end
|
887
|
+
connection.internet_up?.errback do |error|
|
888
|
+
raise "Could not perform the Internet up check. Are you connected to the Internet? #{error}"
|
807
889
|
end
|
808
890
|
end
|
809
891
|
end
|
@@ -828,5 +910,74 @@ describe Ably::Realtime::Connection, :event_machine do
|
|
828
910
|
end
|
829
911
|
end
|
830
912
|
end
|
913
|
+
|
914
|
+
describe 'state change side effects' do
|
915
|
+
let(:channel) { client.channels.get(random_str) }
|
916
|
+
let(:client_options) { default_options.merge(:log_level => :error) }
|
917
|
+
|
918
|
+
context 'when connection enters the :disconnected state' do
|
919
|
+
it 'queues messages to be sent and all channels remain attached' do
|
920
|
+
channel.attach do
|
921
|
+
connection.once(:disconnected) do
|
922
|
+
expect(connection.__outgoing_message_queue__).to be_empty
|
923
|
+
channel.publish 'test'
|
924
|
+
|
925
|
+
EventMachine.add_timer(0.02) do
|
926
|
+
expect(connection.__outgoing_message_queue__).to_not be_empty
|
927
|
+
end
|
928
|
+
|
929
|
+
connection.once(:connected) do
|
930
|
+
EventMachine.add_timer(0.02) do
|
931
|
+
expect(connection.__outgoing_message_queue__).to be_empty
|
932
|
+
stop_reactor
|
933
|
+
end
|
934
|
+
end
|
935
|
+
end
|
936
|
+
|
937
|
+
connection.transport.close_connection_after_writing
|
938
|
+
end
|
939
|
+
end
|
940
|
+
end
|
941
|
+
|
942
|
+
context 'when connection enters the :suspended state' do
|
943
|
+
before do
|
944
|
+
# Reconfigure client library retry periods so that client stays in suspended state
|
945
|
+
stub_const 'Ably::Realtime::Connection::ConnectionManager::CONNECT_RETRY_CONFIG',
|
946
|
+
Ably::Realtime::Connection::ConnectionManager::CONNECT_RETRY_CONFIG.merge(
|
947
|
+
disconnected: { retry_every: 0.01, max_time_in_state: 0.05 },
|
948
|
+
suspended: { retry_every: 60, max_time_in_state: 60 }
|
949
|
+
)
|
950
|
+
end
|
951
|
+
|
952
|
+
it 'detaches the channels and prevents publishing of messages on those channels' do
|
953
|
+
channel.attach do
|
954
|
+
channel.once(:detached) do
|
955
|
+
expect { channel.publish 'test' }.to raise_error(Ably::Exceptions::ChannelInactive)
|
956
|
+
stop_reactor
|
957
|
+
end
|
958
|
+
|
959
|
+
# Keep disconnecting the websocket transport after it attempts reconnection
|
960
|
+
connection.transport.close_connection_after_writing
|
961
|
+
connection.on(:connecting) do
|
962
|
+
EventMachine.add_timer(0.03) do
|
963
|
+
connection.transport.close_connection_after_writing
|
964
|
+
end
|
965
|
+
end
|
966
|
+
end
|
967
|
+
end
|
968
|
+
end
|
969
|
+
|
970
|
+
context 'when connection enters the :failed state' do
|
971
|
+
let(:client_options) { default_options.merge(:key => 'will.not:authenticate', log_level: :none) }
|
972
|
+
|
973
|
+
it 'sets all channels to failed and prevents publishing of messages on those channels' do
|
974
|
+
channel.attach
|
975
|
+
channel.once(:failed) do
|
976
|
+
expect { channel.publish 'test' }.to raise_error(Ably::Exceptions::ChannelInactive)
|
977
|
+
stop_reactor
|
978
|
+
end
|
979
|
+
end
|
980
|
+
end
|
981
|
+
end
|
831
982
|
end
|
832
983
|
end
|
@@ -79,8 +79,8 @@ describe 'Ably::Realtime::Channel Message', :event_machine do
|
|
79
79
|
context 'Integer' do
|
80
80
|
let(:data) { 1 }
|
81
81
|
|
82
|
-
it 'is raises an
|
83
|
-
expect { channel.publish 'event', data }.to raise_error(Ably::Exceptions::
|
82
|
+
it 'is raises an UnsupportedDataType 40011 exception' do
|
83
|
+
expect { channel.publish 'event', data }.to raise_error(Ably::Exceptions::UnsupportedDataType)
|
84
84
|
stop_reactor
|
85
85
|
end
|
86
86
|
end
|
@@ -88,8 +88,8 @@ describe 'Ably::Realtime::Channel Message', :event_machine do
|
|
88
88
|
context 'Float' do
|
89
89
|
let(:data) { 1.1 }
|
90
90
|
|
91
|
-
it 'is raises an
|
92
|
-
expect { channel.publish 'event', data }.to raise_error(Ably::Exceptions::
|
91
|
+
it 'is raises an UnsupportedDataType 40011 exception' do
|
92
|
+
expect { channel.publish 'event', data }.to raise_error(Ably::Exceptions::UnsupportedDataType)
|
93
93
|
stop_reactor
|
94
94
|
end
|
95
95
|
end
|
@@ -97,8 +97,8 @@ describe 'Ably::Realtime::Channel Message', :event_machine do
|
|
97
97
|
context 'Boolean' do
|
98
98
|
let(:data) { true }
|
99
99
|
|
100
|
-
it 'is raises an
|
101
|
-
expect { channel.publish 'event', data }.to raise_error(Ably::Exceptions::
|
100
|
+
it 'is raises an UnsupportedDataType 40011 exception' do
|
101
|
+
expect { channel.publish 'event', data }.to raise_error(Ably::Exceptions::UnsupportedDataType)
|
102
102
|
stop_reactor
|
103
103
|
end
|
104
104
|
end
|
@@ -106,8 +106,8 @@ describe 'Ably::Realtime::Channel Message', :event_machine do
|
|
106
106
|
context 'False' do
|
107
107
|
let(:data) { false }
|
108
108
|
|
109
|
-
it 'is raises an
|
110
|
-
expect { channel.publish 'event', data }.to raise_error(Ably::Exceptions::
|
109
|
+
it 'is raises an UnsupportedDataType 40011 exception' do
|
110
|
+
expect { channel.publish 'event', data }.to raise_error(Ably::Exceptions::UnsupportedDataType)
|
111
111
|
stop_reactor
|
112
112
|
end
|
113
113
|
end
|
@@ -132,6 +132,7 @@ describe 'Ably::Realtime::Channel Message', :event_machine do
|
|
132
132
|
let(:client_options) { default_options.merge(client_id: client_id) }
|
133
133
|
|
134
134
|
it 'contains a #client_id attribute' do
|
135
|
+
skip 'Waiting for issue #256 to be resolved'
|
135
136
|
when_all(channel.attach, other_client_channel.attach) do
|
136
137
|
other_client_channel.subscribe('event') do |message|
|
137
138
|
expect(message.client_id).to eql(client_id)
|
@@ -22,6 +22,7 @@ describe Ably::Realtime::Presence, 'history', :event_machine do
|
|
22
22
|
presence_client_one.enter(data: data) do
|
23
23
|
presence_client_one.leave(data: leave_data) do
|
24
24
|
presence_client_one.history do |history_page|
|
25
|
+
expect(history_page).to be_a(Ably::Models::PaginatedResult)
|
25
26
|
expect(history_page.items.count).to eql(2)
|
26
27
|
|
27
28
|
expect(history_page.items[1].action).to eq(:enter)
|
@@ -45,7 +45,62 @@ describe Ably::Realtime::Presence, :event_machine do
|
|
45
45
|
setup_test(method_name, args, options) do
|
46
46
|
channel_client_one.attach do
|
47
47
|
channel_client_one.change_state state.to_sym
|
48
|
-
expect { presence_client_one.public_send(method_name, args) }.to raise_error Ably::Exceptions::
|
48
|
+
expect { presence_client_one.public_send(method_name, args) }.to raise_error Ably::Exceptions::InvalidStateChange, /Operation is not allowed when channel is in STATE.#{state}/i
|
49
|
+
stop_reactor
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
it 'implicitly attaches the channel' do
|
56
|
+
expect(channel_client_one).to_not be_attached
|
57
|
+
presence_client_one.public_send(method_name, args) do
|
58
|
+
expect(channel_client_one).to be_attached
|
59
|
+
stop_reactor
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
context 'when :queue_messages client option is false' do
|
64
|
+
let(:client_one) { Ably::Realtime::Client.new(default_options.merge(queue_messages: false, client_id: random_str)) }
|
65
|
+
|
66
|
+
context 'and connection state initialized' do
|
67
|
+
it 'raises an exception' do
|
68
|
+
expect { presence_client_one.public_send(method_name, args) }.to raise_error Ably::Exceptions::MessageQueueingDisabled
|
69
|
+
expect(client_one.connection).to be_initialized
|
70
|
+
stop_reactor
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
context 'and connection state connecting' do
|
75
|
+
it 'raises an exception' do
|
76
|
+
client_one.connect
|
77
|
+
EventMachine.next_tick do
|
78
|
+
expect { presence_client_one.public_send(method_name, args) }.to raise_error Ably::Exceptions::MessageQueueingDisabled
|
79
|
+
expect(client_one.connection).to be_connecting
|
80
|
+
stop_reactor
|
81
|
+
end
|
82
|
+
end
|
83
|
+
end
|
84
|
+
|
85
|
+
context 'and connection state disconnected' do
|
86
|
+
let(:client_one) { Ably::Realtime::Client.new(default_options.merge(queue_messages: false, client_id: random_str, :log_level => :error)) }
|
87
|
+
|
88
|
+
it 'raises an exception' do
|
89
|
+
client_one.connection.once(:connected) do
|
90
|
+
client_one.connection.once(:disconnected) do
|
91
|
+
expect { presence_client_one.public_send(method_name, args) }.to raise_error Ably::Exceptions::MessageQueueingDisabled
|
92
|
+
expect(client_one.connection).to be_disconnected
|
93
|
+
stop_reactor
|
94
|
+
end
|
95
|
+
client_one.connection.transition_state_machine :disconnected
|
96
|
+
end
|
97
|
+
end
|
98
|
+
end
|
99
|
+
|
100
|
+
context 'and connection state connected' do
|
101
|
+
it 'publishes the message' do
|
102
|
+
client_one.connection.once(:connected) do
|
103
|
+
presence_client_one.public_send(method_name, args)
|
49
104
|
stop_reactor
|
50
105
|
end
|
51
106
|
end
|
@@ -120,8 +175,8 @@ describe Ably::Realtime::Presence, :event_machine do
|
|
120
175
|
context 'Integer' do
|
121
176
|
let(:data) { 1 }
|
122
177
|
|
123
|
-
it 'raises an
|
124
|
-
expect { presence_action(method_name, data) }.to raise_error(Ably::Exceptions::
|
178
|
+
it 'raises an UnsupportedDataType 40011 exception' do
|
179
|
+
expect { presence_action(method_name, data) }.to raise_error(Ably::Exceptions::UnsupportedDataType)
|
125
180
|
stop_reactor
|
126
181
|
end
|
127
182
|
end
|
@@ -129,8 +184,8 @@ describe Ably::Realtime::Presence, :event_machine do
|
|
129
184
|
context 'Float' do
|
130
185
|
let(:data) { 1.1 }
|
131
186
|
|
132
|
-
it 'raises an
|
133
|
-
expect { presence_action(method_name, data) }.to raise_error(Ably::Exceptions::
|
187
|
+
it 'raises an UnsupportedDataType 40011 exception' do
|
188
|
+
expect { presence_action(method_name, data) }.to raise_error(Ably::Exceptions::UnsupportedDataType)
|
134
189
|
stop_reactor
|
135
190
|
end
|
136
191
|
end
|
@@ -138,8 +193,8 @@ describe Ably::Realtime::Presence, :event_machine do
|
|
138
193
|
context 'Boolean' do
|
139
194
|
let(:data) { true }
|
140
195
|
|
141
|
-
it 'raises an
|
142
|
-
expect { presence_action(method_name, data) }.to raise_error(Ably::Exceptions::
|
196
|
+
it 'raises an UnsupportedDataType 40011 exception' do
|
197
|
+
expect { presence_action(method_name, data) }.to raise_error(Ably::Exceptions::UnsupportedDataType)
|
143
198
|
stop_reactor
|
144
199
|
end
|
145
200
|
end
|
@@ -147,8 +202,8 @@ describe Ably::Realtime::Presence, :event_machine do
|
|
147
202
|
context 'False' do
|
148
203
|
let(:data) { false }
|
149
204
|
|
150
|
-
it 'raises an
|
151
|
-
expect { presence_action(method_name, data) }.to raise_error(Ably::Exceptions::
|
205
|
+
it 'raises an UnsupportedDataType 40011 exception' do
|
206
|
+
expect { presence_action(method_name, data) }.to raise_error(Ably::Exceptions::UnsupportedDataType)
|
152
207
|
stop_reactor
|
153
208
|
end
|
154
209
|
end
|
@@ -161,6 +216,14 @@ describe Ably::Realtime::Presence, :event_machine do
|
|
161
216
|
end
|
162
217
|
end
|
163
218
|
|
219
|
+
it 'allows a block to be passed in that is executed upon success' do
|
220
|
+
setup_test(method_name, args, options) do
|
221
|
+
presence_client_one.public_send(method_name, args) do
|
222
|
+
stop_reactor
|
223
|
+
end
|
224
|
+
end
|
225
|
+
end
|
226
|
+
|
164
227
|
it 'calls the Deferrable callback on success' do
|
165
228
|
setup_test(method_name, args, options) do
|
166
229
|
presence_client_one.public_send(method_name, args).callback do |presence|
|
@@ -1002,7 +1065,7 @@ describe Ably::Realtime::Presence, :event_machine do
|
|
1002
1065
|
it "raise an exception if the channel is #{state}" do
|
1003
1066
|
channel_client_one.attach do
|
1004
1067
|
channel_client_one.change_state state.to_sym
|
1005
|
-
expect { presence_client_one.get }.to raise_error Ably::Exceptions::
|
1068
|
+
expect { presence_client_one.get }.to raise_error Ably::Exceptions::InvalidStateChange, /Operation is not allowed when channel is in STATE.#{state}/i
|
1006
1069
|
stop_reactor
|
1007
1070
|
end
|
1008
1071
|
end
|
@@ -1218,6 +1281,36 @@ describe Ably::Realtime::Presence, :event_machine do
|
|
1218
1281
|
end
|
1219
1282
|
end
|
1220
1283
|
end
|
1284
|
+
|
1285
|
+
context 'with event name' do
|
1286
|
+
it 'calls the callback for specified presence event' do
|
1287
|
+
when_all(channel_client_one.attach, channel_client_two.attach) do
|
1288
|
+
presence_client_two.subscribe(:leave) do |presence_message|
|
1289
|
+
messages << presence_message
|
1290
|
+
next unless messages.count == 1
|
1291
|
+
|
1292
|
+
expect(messages.map(&:action).map(&:to_sym)).to contain_exactly(:leave)
|
1293
|
+
stop_reactor
|
1294
|
+
end
|
1295
|
+
|
1296
|
+
presence_client_one.enter do
|
1297
|
+
presence_client_one.update do
|
1298
|
+
presence_client_one.leave
|
1299
|
+
end
|
1300
|
+
end
|
1301
|
+
end
|
1302
|
+
end
|
1303
|
+
end
|
1304
|
+
|
1305
|
+
it 'implicitly attaches' do
|
1306
|
+
expect(client_one.connection).to be_initialized
|
1307
|
+
presence_client_one.subscribe { true }
|
1308
|
+
channel_client_one.on(:attached) do
|
1309
|
+
expect(client_one.connection).to be_connected
|
1310
|
+
expect(channel_client_one).to be_attached
|
1311
|
+
stop_reactor
|
1312
|
+
end
|
1313
|
+
end
|
1221
1314
|
end
|
1222
1315
|
|
1223
1316
|
context '#unsubscribe' do
|
@@ -1238,6 +1331,24 @@ describe Ably::Realtime::Presence, :event_machine do
|
|
1238
1331
|
end
|
1239
1332
|
end
|
1240
1333
|
end
|
1334
|
+
|
1335
|
+
context 'with event name' do
|
1336
|
+
it 'removes the callback for specified presence event' do
|
1337
|
+
when_all(channel_client_one.attach, channel_client_two.attach) do
|
1338
|
+
subscribe_callback = proc { raise 'Should not be called' }
|
1339
|
+
presence_client_two.subscribe :leave, &subscribe_callback
|
1340
|
+
presence_client_two.unsubscribe :leave, &subscribe_callback
|
1341
|
+
|
1342
|
+
presence_client_one.enter do
|
1343
|
+
presence_client_one.leave do
|
1344
|
+
EventMachine.add_timer(1) do
|
1345
|
+
stop_reactor
|
1346
|
+
end
|
1347
|
+
end
|
1348
|
+
end
|
1349
|
+
end
|
1350
|
+
end
|
1351
|
+
end
|
1241
1352
|
end
|
1242
1353
|
|
1243
1354
|
context 'REST #get' do
|