lib/submodules/ably-ruby/spec/acceptance/realtime/channel_spec.rb in ably-rest-0.8.5 vs lib/submodules/ably-ruby/spec/acceptance/realtime/channel_spec.rb in ably-rest-0.8.6

- old
+ new

@@ -502,59 +502,147 @@ end end end end + context 'nil attributes' do + context 'when name is nil' do + let(:data) { random_str } + + it 'publishes the message without a name attribute in the payload' do + published = false + channel.publish(nil, data) do + published = true + end + + channel.subscribe do |message| + expect(message.name).to be_nil + channel.history do |page| + expect(page.items.first.name).to be_nil + expect(page.items.first.data).to eql(data) + EM.add_timer(0.5) do + expect(published).to eql(true) + stop_reactor + end + end + end + end + end + + context 'when data is nil' do + let(:name) { random_str } + + it 'publishes the message without a data attribute in the payload' do + published = false + channel.publish(name, nil) do + published = true + end + + channel.subscribe do |message| + expect(message.data).to be_nil + channel.history do |page| + expect(page.items.first.name).to eql(name) + expect(page.items.first.data).to be_nil + EM.add_timer(0.5) do + expect(published).to eql(true) + stop_reactor + end + end + end + end + end + + context 'with neither name or data attributes' do + let(:name) { random_str } + + it 'publishes the message without any attributes in the payload' do + channel.publish(nil) do + channel.history do |page| + expect(page.items.first.name).to be_nil + expect(page.items.first.data).to be_nil + stop_reactor + end + end + end + end + end + context 'with two invalid message out of 12' do - let(:client_options) { default_options.merge(client_id: 'valid') } + let(:rest_client) { Ably::Rest::Client.new(default_options.merge(client_id: 'valid')) } + let(:invalid_messages) do 2.times.map do |index| Ably::Models::Message(name: index.to_s, data: { "index" => index + 10 }, client_id: 'prohibited') end end - it 'calls the errback once' do - skip 'Waiting for issue #256 to be resolved' - channel.publish(messages + invalid_messages).tap do |deferrable| - deferrable.callback do - raise 'Publish should have failed' - end + context 'before client_id is known (validated)' do + let(:client_options) { default_options.merge(token: rest_client.auth.request_token.token, log_level: :error) } - deferrable.errback do |error, message| - # TODO: Review whether we should fail once or multiple times - channel.history do |page| - expect(page.items.count).to eql(0) - stop_reactor + it 'calls the errback once' do + channel.publish(messages + invalid_messages).tap do |deferrable| + deferrable.callback do + raise 'Publish should have failed' end + + deferrable.errback do |error, message| + # TODO: Review whether we should fail once or multiple times + channel.history do |page| + expect(page.items.count).to eql(0) + stop_reactor + end + end end end end + + context 'when client_id is known (validated)' do + let(:client_options) { default_options.merge(client_id: 'valid') } + + it 'raises an exception' do + expect { channel.publish(messages + invalid_messages) }.to raise_error Ably::Exceptions::IncompatibleClientId + stop_reactor + end + end end context 'only invalid messages' do - let(:client_options) { default_options.merge(client_id: 'valid') } + let(:rest_client) { Ably::Rest::Client.new(default_options.merge(client_id: 'valid')) } + let(:invalid_messages) do 10.times.map do |index| Ably::Models::Message(name: index.to_s, data: { "index" => index + 10 }, client_id: 'prohibited') end end - it 'calls the errback once' do - skip 'Waiting for issue #256 to be resolved' - channel.publish(invalid_messages).tap do |deferrable| - deferrable.callback do - raise 'Publish should have failed' - end + context 'before client_id is known (validated)' do + let(:client_options) { default_options.merge(token: rest_client.auth.request_token.token, log_level: :error) } - deferrable.errback do |error, message| - channel.history do |page| - expect(page.items.count).to eql(0) - stop_reactor + it 'calls the errback once' do + channel.publish(invalid_messages).tap do |deferrable| + deferrable.callback do + raise 'Publish should have failed' end + + deferrable.errback do |error, message| + channel.history do |page| + expect(page.items.count).to eql(0) + stop_reactor + end + end end end end + + context 'when client_id is known (validated)' do + let(:client_options) { default_options.merge(client_id: 'valid') } + + it 'raises an exception' do + expect { channel.publish(invalid_messages) }.to raise_error Ably::Exceptions::IncompatibleClientId + stop_reactor + end + end end end context 'with many many messages and many connections simultaneously' do let(:connection_count) { 5 } @@ -579,10 +667,212 @@ end end end end end + + context 'identified clients' do + context 'when authenticated with a wildcard client_id' do + let(:token) { Ably::Rest::Client.new(default_options).auth.request_token(client_id: '*') } + let(:client_options) { default_options.merge(key: nil, token: token) } + let(:client) { auto_close Ably::Realtime::Client.new(client_options) } + let(:channel) { client.channels.get(channel_name) } + + context 'with a valid client_id in the message' do + it 'succeeds' do + channel.publish([name: 'event', client_id: 'validClient']).tap do |deferrable| + deferrable.errback { raise 'Should have succeeded' } + end + channel.subscribe('event') do |message| + expect(message.client_id).to eql('validClient') + EM.add_timer(0.5) { stop_reactor } + end + end + end + + context 'with a wildcard client_id in the message' do + it 'throws an exception' do + expect { channel.publish([name: 'event', client_id: '*']) }.to raise_error Ably::Exceptions::IncompatibleClientId + stop_reactor + end + end + + context 'with an empty client_id in the message' do + it 'succeeds and publishes without a client_id' do + channel.publish([name: 'event', client_id: nil]).tap do |deferrable| + deferrable.errback { raise 'Should have succeeded' } + end + channel.subscribe('event') do |message| + expect(message.client_id).to be_nil + EM.add_timer(0.5) { stop_reactor } + end + end + end + end + + context 'when authenticated with a Token string with an implicit client_id' do + let(:token) { Ably::Rest::Client.new(default_options).auth.request_token(client_id: 'valid').token } + let(:client_options) { default_options.merge(key: nil, token: token) } + let(:client) { auto_close Ably::Realtime::Client.new(client_options) } + let(:channel) { client.channels.get(channel_name) } + + context 'before the client is CONNECTED and the client\'s identity has been obtained' do + context 'with a valid client_id in the message' do + it 'succeeds' do + channel.publish([name: 'event', client_id: 'valid']).tap do |deferrable| + deferrable.errback { raise 'Should have succeeded' } + end + channel.subscribe('event') do |message| + expect(message.client_id).to eql('valid') + EM.add_timer(0.5) { stop_reactor } + end + end + end + + context 'with an invalid client_id in the message' do + let(:client_options) { default_options.merge(key: nil, token: token, log_level: :error) } + it 'succeeds in the client library but then fails when delivered to Ably' do + channel.publish([name: 'event', client_id: 'invalid']).tap do |deferrable| + EM.add_timer(0.5) { stop_reactor } + end + channel.subscribe('event') do |message| + raise 'Message should not have been published' + end + end + end + + context 'with an empty client_id in the message' do + it 'succeeds and publishes with an implicit client_id' do + channel.publish([name: 'event', client_id: nil]).tap do |deferrable| + deferrable.errback { raise 'Should have succeeded' } + end + channel.subscribe('event') do |message| + expect(message.client_id).to eql('valid') + EM.add_timer(0.5) { stop_reactor } + end + end + end + end + + context 'after the client is CONNECTED and the client\'s identity is known' do + context 'with a valid client_id in the message' do + it 'succeeds' do + client.connection.once(:connected) do + channel.publish([name: 'event', client_id: 'valid']).tap do |deferrable| + deferrable.errback { raise 'Should have succeeded' } + end + channel.subscribe('event') do |message| + expect(message.client_id).to eql('valid') + EM.add_timer(0.5) { stop_reactor } + end + end + end + end + + context 'with an invalid client_id in the message' do + it 'throws an exception' do + client.connection.once(:connected) do + expect { channel.publish([name: 'event', client_id: 'invalid']) }.to raise_error Ably::Exceptions::IncompatibleClientId + stop_reactor + end + end + end + + context 'with an empty client_id in the message' do + it 'succeeds and publishes with an implicit client_id' do + client.connection.once(:connected) do + channel.publish([name: 'event', client_id: nil]).tap do |deferrable| + deferrable.errback { raise 'Should have succeeded' } + end + channel.subscribe('event') do |message| + expect(message.client_id).to eql('valid') + EM.add_timer(0.5) { stop_reactor } + end + end + end + end + end + end + + context 'when authenticated with a valid client_id' do + let(:token) { Ably::Rest::Client.new(default_options).auth.request_token(client_id: 'valid') } + let(:client_options) { default_options.merge(key: nil, token: token) } + let(:client) { auto_close Ably::Realtime::Client.new(client_options) } + let(:channel) { client.channels.get(channel_name) } + + context 'with a valid client_id' do + it 'succeeds' do + channel.publish([name: 'event', client_id: 'valid']).tap do |deferrable| + deferrable.errback { raise 'Should have succeeded' } + end + channel.subscribe('event') do |message| + expect(message.client_id).to eql('valid') + EM.add_timer(0.5) { stop_reactor } + end + end + end + + context 'with a wildcard client_id in the message' do + it 'throws an exception' do + expect { channel.publish([name: 'event', client_id: '*']) }.to raise_error Ably::Exceptions::IncompatibleClientId + stop_reactor + end + end + + context 'with an invalid client_id in the message' do + it 'throws an exception' do + expect { channel.publish([name: 'event', client_id: 'invalid']) }.to raise_error Ably::Exceptions::IncompatibleClientId + stop_reactor + end + end + + context 'with an empty client_id in the message' do + it 'succeeds and publishes with an implicit client_id' do + channel.publish([name: 'event', client_id: nil]).tap do |deferrable| + deferrable.errback { raise 'Should have succeeded' } + end + channel.subscribe('event') do |message| + expect(message.client_id).to eql('valid') + EM.add_timer(0.5) { stop_reactor } + end + end + end + end + + context 'when anonymous and no client_id' do + let(:token) { Ably::Rest::Client.new(default_options).auth.request_token(client_id: nil) } + let(:client_options) { default_options.merge(key: nil, token: token) } + let(:client) { auto_close Ably::Realtime::Client.new(client_options) } + let(:channel) { client.channels.get(channel_name) } + + context 'with a client_id in the message' do + it 'throws an exception' do + expect { channel.publish([name: 'event', client_id: 'invalid']) }.to raise_error Ably::Exceptions::IncompatibleClientId + stop_reactor + end + end + + context 'with a wildcard client_id in the message' do + it 'throws an exception' do + expect { channel.publish([name: 'event', client_id: '*']) }.to raise_error Ably::Exceptions::IncompatibleClientId + stop_reactor + end + end + + context 'with an empty client_id in the message' do + it 'succeeds and publishes with an implicit client_id' do + channel.publish([name: 'event', client_id: nil]).tap do |deferrable| + deferrable.errback { raise 'Should have succeeded' } + end + channel.subscribe('event') do |message| + expect(message.client_id).to be_nil + EM.add_timer(0.5) { stop_reactor } + end + end + end + end + end end describe '#subscribe' do context 'with an event argument' do it 'subscribes for a single event' do @@ -879,11 +1169,11 @@ end end context 'a :failed channel' do let(:original_error) { RuntimeError.new } - let(:client_options) { default_options.merge(log_level: :fatal) } + let(:client_options) { default_options.merge(log_level: :fatal) } it 'remains in the :failed state and retains the error_reason' do channel.attach do channel.once(:error) do channel.on(:detached) { raise 'Detached state should not have been reached' } @@ -902,9 +1192,11 @@ end end end context 'a channel ATTACH request when connection SUSPENDED' do + let(:client_options) { default_options.merge(log_level: :fatal) } + it 'raises an exception' do client.connect do client.connection.once(:suspended) do expect { channel.attach }.to raise_error Ably::Exceptions::InvalidStateChange stop_reactor