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)