spec/acceptance/realtime/connection_spec.rb in ably-0.8.3 vs spec/acceptance/realtime/connection_spec.rb in ably-0.8.4
- old
+ new
@@ -125,12 +125,12 @@
let(:ttl) { 0.001 }
it 'renews the token on connect, and only makes one subsequent attempt to obtain a new token' do
expect(client.rest_client.auth).to receive(:authorise).at_least(:twice).and_call_original
connection.once(:disconnected) do
- connection.once(:failed) do |error|
- expect(error.code).to eql(40140) # token expired
+ connection.once(:failed) do |connection_state_change|
+ expect(connection_state_change.reason.code).to eql(40140) # token expired
stop_reactor
end
end
end
@@ -165,22 +165,21 @@
original_token = client.auth.current_token_details
expect(original_token).to_not be_expired
connection.once(:connected) do
started_at = Time.now
- connection.once(:disconnected) do |error|
- expect(error.code).to eq(40140) # Token expired
+ connection.once(:disconnected) do |connection_state_change|
+ expect(connection_state_change.reason.code).to eq(40140) # Token expired
# Token has expired, so now ensure it is not used again
stub_const 'Ably::Models::TokenDetails::TOKEN_EXPIRY_BUFFER', original_token_expiry_buffer
stub_const 'Ably::Auth::TOKEN_DEFAULTS', Ably::Auth::TOKEN_DEFAULTS.merge(renew_token_buffer: original_renew_token_buffer)
connection.once(:connected) do
expect(client.auth.current_token_details).to_not be_expired
expect(Time.now - started_at >= ttl)
expect(original_token).to be_expired
- expect(error.code).to eql(40140) # token expired
stop_reactor
end
end
end
@@ -920,16 +919,16 @@
channel.attach do
connection.once(:disconnected) do
expect(connection.__outgoing_message_queue__).to be_empty
channel.publish 'test'
- EventMachine.add_timer(0.02) do
+ EventMachine.next_tick do
expect(connection.__outgoing_message_queue__).to_not be_empty
end
connection.once(:connected) do
- EventMachine.add_timer(0.02) do
+ EventMachine.add_timer(0.1) do
expect(connection.__outgoing_message_queue__).to be_empty
stop_reactor
end
end
end
@@ -938,10 +937,12 @@
end
end
end
context 'when connection enters the :suspended state' do
+ let(:client_options) { default_options.merge(:log_level => :fatal) }
+
before do
# Reconfigure client library retry periods so that client stays in suspended state
stub_const 'Ably::Realtime::Connection::ConnectionManager::CONNECT_RETRY_CONFIG',
Ably::Realtime::Connection::ConnectionManager::CONNECT_RETRY_CONFIG.merge(
disconnected: { retry_every: 0.01, max_time_in_state: 0.05 },
@@ -954,17 +955,25 @@
channel.once(:detached) do
expect { channel.publish 'test' }.to raise_error(Ably::Exceptions::ChannelInactive)
stop_reactor
end
+ close_connection_proc = Proc.new do
+ EventMachine.add_timer(0.001) do
+ if connection.transport.nil?
+ close_connection_proc.call
+ else
+ connection.transport.close_connection_after_writing
+ end
+ end
+ end
+
# Keep disconnecting the websocket transport after it attempts reconnection
- connection.transport.close_connection_after_writing
connection.on(:connecting) do
- EventMachine.add_timer(0.03) do
- connection.transport.close_connection_after_writing
- end
+ close_connection_proc.call
end
+ close_connection_proc.call
end
end
end
context 'when connection enters the :failed state' do
@@ -973,9 +982,111 @@
it 'sets all channels to failed and prevents publishing of messages on those channels' do
channel.attach
channel.once(:failed) do
expect { channel.publish 'test' }.to raise_error(Ably::Exceptions::ChannelInactive)
stop_reactor
+ end
+ end
+ end
+ end
+
+ context 'connection state change' do
+ it 'emits a ConnectionStateChange object' do
+ connection.on(:connected) do |connection_state_change|
+ expect(connection_state_change).to be_a(Ably::Models::ConnectionStateChange)
+ stop_reactor
+ end
+ end
+
+ context 'ConnectionStateChange object' do
+ it 'has current state' do
+ connection.on(:connected) do |connection_state_change|
+ expect(connection_state_change.current).to eq(:connected)
+ stop_reactor
+ end
+ end
+
+ it 'has a previous state' do
+ connection.on(:connected) do |connection_state_change|
+ expect(connection_state_change.previous).to eq(:connecting)
+ stop_reactor
+ end
+ end
+
+ it 'contains a private API protocol_message attribute that is used for special state change events', :api_private do
+ connection.on(:connected) do |connection_state_change|
+ expect(connection_state_change.protocol_message).to be_a(Ably::Models::ProtocolMessage)
+ expect(connection_state_change.reason).to be_nil
+ stop_reactor
+ end
+ end
+
+ it 'has an empty reason when there is no error' do
+ connection.on(:closed) do |connection_state_change|
+ expect(connection_state_change.reason).to be_nil
+ stop_reactor
+ end
+ connection.connect do
+ connection.close
+ end
+ end
+
+ context 'on failure' do
+ let(:client_options) { default_options.merge(log_level: :none) }
+
+ it 'has a reason Error object when there is an error on the connection' do
+ connection.on(:failed) do |connection_state_change|
+ expect(connection_state_change.reason).to be_a(Ably::Exceptions::BaseAblyException)
+ stop_reactor
+ end
+ connection.connect do
+ error = Ably::Exceptions::ConnectionFailed.new('forced failure', 500, 50000)
+ client.connection.manager.error_received_from_server error
+ end
+ end
+ end
+
+ context 'retry_in' do
+ let(:client_options) { default_options.merge(log_level: :debug) }
+
+ it 'is nil when a retry is not required' do
+ connection.on(:connected) do |connection_state_change|
+ expect(connection_state_change.retry_in).to be_nil
+ stop_reactor
+ end
+ end
+
+ it 'is 0 when first attempt to connect fails' do
+ connection.once(:connecting) do
+ connection.once(:disconnected) do |connection_state_change|
+ expect(connection_state_change.retry_in).to eql(0)
+ stop_reactor
+ end
+ EventMachine.add_timer(0.001) { connection.transport.unbind }
+ end
+ end
+
+ it 'is 0 when an immediate reconnect will occur' do
+ connection.once(:connected) do
+ connection.once(:disconnected) do |connection_state_change|
+ expect(connection_state_change.retry_in).to eql(0)
+ stop_reactor
+ end
+ connection.transport.unbind
+ end
+ end
+
+ it 'contains the next retry period when an immediate reconnect will not occur' do
+ connection.once(:connected) do
+ connection.once(:connecting) do
+ connection.once(:disconnected) do |connection_state_change|
+ expect(connection_state_change.retry_in).to be > 0
+ stop_reactor
+ end
+ EventMachine.add_timer(0.001) { connection.transport.unbind }
+ end
+ connection.transport.unbind
+ end
end
end
end
end
end