spec/acceptance/realtime/connection_spec.rb in ably-0.1.6 vs spec/acceptance/realtime/connection_spec.rb in ably-0.2.0

- old
+ new

@@ -1,23 +1,47 @@ require 'spec_helper' describe Ably::Realtime::Connection do include RSpec::EventMachine - [:msgpack, :json].each do |protocol| + let(:connection) { client.connection } + + [:json, :msgpack].each do |protocol| context "over #{protocol}" do + let(:default_options) do + { api_key: api_key, environment: environment, protocol: protocol } + end + let(:client) do - Ably::Realtime::Client.new(api_key: api_key, environment: environment, protocol: protocol) + Ably::Realtime::Client.new(default_options) end - subject { client.connection } + context 'with API key' do + it 'connects automatically' do + run_reactor do + connection.on(:connected) do + expect(connection.state).to eq(:connected) + expect(client.auth.auth_params[:key_id]).to_not be_nil + expect(client.auth.auth_params[:access_token]).to be_nil + stop_reactor + end + end + end + end - it 'connects automatically' do - run_reactor do - subject.on(:connected) do - expect(subject.state).to eq(:connected) - stop_reactor + context 'with client_id resulting in token auth' do + let(:default_options) do + { api_key: api_key, environment: environment, protocol: protocol, client_id: SecureRandom.hex, log_level: :debug } + end + it 'connects automatically' do + run_reactor do + connection.on(:connected) do + expect(connection.state).to eq(:connected) + expect(client.auth.auth_params[:access_token]).to_not be_nil + expect(client.auth.auth_params[:key_id]).to be_nil + stop_reactor + end end end end context 'initialization phases' do @@ -30,52 +54,124 @@ stop_reactor end run_reactor do phases.each do |phase| - subject.on(phase) do + connection.on(phase) do events_triggered << phase test_expectation.call if events_triggered.length == phases.length end end end end end - skip '#closed disconnects and closes the connection once timeout is reached' + skip '#close disconnects, closes the connection immediately and changes the connection state to closed' - specify '#closed disconnects and closes the connection gracefully' do + specify '#close(graceful: true) gracefully waits for the server to close the connection' do run_reactor(8) do - subject.close - subject.on(:closed) do - expect(subject.state).to eq(:closed) + connection.close + connection.on(:closed) do + expect(connection.state).to eq(:closed) stop_reactor end end end - it 'receives a heart beat' do - run_reactor(20) do - subject.on(:connected) do - subject.__incoming_protocol_msgbus__.subscribe(:message) do |protocol_message| - if protocol_message.action == :heartbeat - expect(protocol_message.action).to eq(:heartbeat) + it 'echoes a heart beat with #ping' do + run_reactor do + connection.on(:connected) do + connection.ping do |time_elapsed| + expect(time_elapsed).to be > 0 + stop_reactor + end + end + end + end + + skip 'connects, closes gracefully and reconnects on #connect' + + it 'connects, closes the connection, and then reconnects with a new connection ID' do + run_reactor(15) do + connection.connect do + connection_id = connection.id + connection.close do + connection.connect do + expect(connection.id).to_not eql(connection_id) stop_reactor end end end end end - skip 'connects, closes gracefully and reconnects on #connect' + context 'failures' do + context 'with invalid app part of the key' do + let(:missing_key) { 'not_an_app.invalid_key_id:invalid_key_value' } + let(:client) do + Ably::Realtime::Client.new(default_options.merge(api_key: missing_key)) + end - it 'connects, closes then connection when timeout is reaached and reconnects on #connect' do + it 'enters the failed state and returns a not found error' do + run_reactor do + connection.on(:failed) do |error| + expect(connection.state).to eq(:failed) + expect(error.status).to eq(404) + stop_reactor + end + end + end + end + + context 'with invalid key ID part of the key' do + let(:invalid_key) { "#{app_id}.invalid_key_id:invalid_key_value" } + let(:client) do + Ably::Realtime::Client.new(default_options.merge(api_key: invalid_key)) + end + + it 'enters the failed state and returns an authorization error' do + run_reactor do + connection.on(:failed) do |error| + expect(connection.state).to eq(:failed) + expect(error.status).to eq(401) + stop_reactor + end + end + end + end + + context 'with invalid WebSocket host' do + let(:client) do + Ably::Realtime::Client.new(default_options.merge(ws_host: 'non.existent.host')) + end + + it 'enters the failed state and returns an authorization error' do + run_reactor do + connection.on(:failed) do |error| + expect(connection.state).to eq(:failed) + expect(error.code).to eq(80000) + expect(error.status).to be_nil + stop_reactor + end + end + end + end + end + + it 'opens many connections simultaneously' do run_reactor(15) do - subject.connect do - connection_id = subject.id - subject.close do - subject.connect do - expect(subject.id).to_not eql(connection_id) + count, connected_ids = 25, [] + + clients = count.times.map do + Ably::Realtime::Client.new(default_options) + end + + clients.each do |client| + client.connection.on(:connected) do + connected_ids << client.connection.id + + if connected_ids.count == 25 + expect(connected_ids.uniq.count).to eql(25) stop_reactor end end end end