spec/acceptance/realtime/connection_spec.rb in ably-0.7.2 vs spec/acceptance/realtime/connection_spec.rb in ably-0.7.4
- old
+ new
@@ -1,7 +1,8 @@
# encoding: utf-8
require 'spec_helper'
+require 'ostruct'
describe Ably::Realtime::Connection, :event_machine do
let(:connection) { client.connection }
vary_by_protocol do
@@ -146,18 +147,16 @@
expect(original_token).to_not be_expired
connection.once(:connected) do
started_at = Time.now
connection.once(:disconnected) do |error|
- EventMachine.add_timer(1) do # allow 1 second
+ connection.once(:connected) do
+ expect(client.auth.current_token).to_not be_expired
expect(Time.now - started_at >= ttl)
expect(original_token).to be_expired
expect(error.code).to eql(40140) # token expired
- connection.once(:connected) do
- expect(client.auth.current_token).to_not be_expired
- stop_reactor
- end
+ stop_reactor
end
end
end
channel.attach
@@ -232,12 +231,12 @@
end
end
end
context '#connect' do
- it 'returns a Deferrable' do
- expect(connection.connect).to be_a(EventMachine::Deferrable)
+ it 'returns a SafeDeferrable that catches exceptions in callbacks and logs them' do
+ expect(connection.connect).to be_a(Ably::Util::SafeDeferrable)
stop_reactor
end
it 'calls the Deferrable callback on success' do
connection.connect.callback do |connection|
@@ -370,13 +369,13 @@
end
end
end
context '#close' do
- it 'returns a Deferrable' do
+ it 'returns a SafeDeferrable that catches exceptions in callbacks and logs them' do
connection.connect do
- expect(connection.close).to be_a(EventMachine::Deferrable)
+ expect(connection.close).to be_a(Ably::Util::SafeDeferrable)
stop_reactor
end
end
it 'calls the Deferrable callback on success' do
@@ -502,10 +501,21 @@
it 'raises an exception' do
expect { connection.ping }.to raise_error RuntimeError, /Cannot send a ping when connection/
stop_reactor
end
end
+
+ context 'with a success block that raises an exception' do
+ it 'catches the exception and logs the error' do
+ connection.on(:connected) do
+ expect(connection.logger).to receive(:error).with(/Forced exception/) do
+ stop_reactor
+ end
+ connection.ping { raise 'Forced exception' }
+ end
+ end
+ end
end
context 'recovery' do
let(:channel_name) { random_str }
let(:channel) { client.channel(channel_name) }
@@ -589,11 +599,11 @@
context "opening a new connection using a recently disconnected connection's #recovery_key" do
context 'connection#id and connection#key after recovery' do
let(:client_options) { default_options.merge(log_level: :none) }
- it 'remain the same' do
+ it 'remains the same' do
previous_connection_id = nil
previous_connection_key = nil
connection.once(:connected) do
previous_connection_id = connection.id
@@ -608,10 +618,26 @@
expect(recover_client.connection.id).to eql(previous_connection_id)
stop_reactor
end
end
end
+
+ it 'does not trigger a resume callback', api_private: true do
+ connection.once(:connected) do
+ connection.transition_state_machine! :failed
+ end
+
+ connection.once(:failed) do
+ recover_client = Ably::Realtime::Client.new(default_options.merge(recover: client.connection.recovery_key))
+ recover_client.connection.on_resume do
+ raise 'Should not trigger resume callback'
+ end
+ recover_client.connection.on(:connected) do
+ EventMachine.add_timer(0.5) { stop_reactor }
+ end
+ end
+ end
end
context 'when messages have been sent whilst the old connection is disconnected' do
describe 'the new connection' do
let(:client_options) { default_options.merge(log_level: :none) }
@@ -651,10 +677,11 @@
let(:client_options) { default_options.merge(recover: 'not-a-valid-connection-key:1', log_level: :none) }
it 'triggers a fatal error on the connection object, sets the #error_reason and disconnects' do
connection.once(:error) do |error|
expect(connection.state).to eq(:failed)
+ expect(error.message).to match(/Invalid connection key/)
expect(connection.error_reason.message).to match(/Invalid connection key/)
expect(connection.error_reason.code).to eql(40006)
expect(connection.error_reason).to eql(error)
stop_reactor
end
@@ -665,10 +692,11 @@
let(:client_options) { default_options.merge(recover: '0123456789abcdef:0', log_level: :fatal) }
it 'triggers an error on the connection object, sets the #error_reason, yet will connect anyway' do
connection.once(:error) do |error|
expect(connection.state).to eq(:connected)
+ expect(error.message).to match(/Invalid connection key/i)
expect(connection.error_reason.message).to match(/Invalid connection key/i)
expect(connection.error_reason.code).to eql(80008)
expect(connection.error_reason).to eql(error)
stop_reactor
end
@@ -712,9 +740,26 @@
stop_reactor
end
end
end
+ context 'protocol failure' do
+ let(:client_options) { default_options.merge(protocol: :json) }
+
+ context 'receiving an invalid ProtocolMessage' do
+ it 'emits an error on the connection and logs a fatal error message' do
+ connection.connect do
+ connection.transport.send(:driver).emit 'message', OpenStruct.new(data: { action: 500 }.to_json)
+ end
+
+ expect(client.logger).to receive(:fatal).with(/Invalid Protocol Message/)
+ connection.on(:error) do |error|
+ expect(error.message).to match(/Invalid Protocol Message/)
+ stop_reactor
+ end
+ end
+ end
+ end
context 'undocumented method' do
context '#internet_up?' do
it 'returns a Deferrable' do
expect(connection.internet_up?).to be_a(EventMachine::Deferrable)