lib/submodules/ably-ruby/spec/acceptance/realtime/channel_spec.rb in ably-rest-0.8.3 vs lib/submodules/ably-ruby/spec/acceptance/realtime/channel_spec.rb in ably-rest-0.8.5
- old
+ new
@@ -4,20 +4,20 @@
describe Ably::Realtime::Channel, :event_machine do
vary_by_protocol do
let(:default_options) { { key: api_key, environment: environment, protocol: protocol } }
let(:client_options) { default_options }
- let(:client) { Ably::Realtime::Client.new(client_options) }
+ let(:client) { auto_close Ably::Realtime::Client.new(client_options) }
let(:channel_name) { random_str }
let(:payload) { random_str }
let(:channel) { client.channel(channel_name) }
let(:messages) { [] }
describe 'initialization' do
context 'with :auto_connect option set to false on connection' do
let(:client) do
- Ably::Realtime::Client.new(default_options.merge(auto_connect: false))
+ auto_close Ably::Realtime::Client.new(default_options.merge(auto_connect: false))
end
it 'remains initialized when accessing a channel' do
client.channel('test')
EventMachine.add_timer(2) do
@@ -78,11 +78,11 @@
expect(channel.attach).to be_a(Ably::Util::SafeDeferrable)
stop_reactor
end
it 'calls the SafeDeferrable callback on success' do
- channel.attach.callback do |channel|
+ channel.attach.callback do
expect(channel).to be_a(Ably::Realtime::Channel)
expect(channel.state).to eq(:attached)
stop_reactor
end
end
@@ -90,11 +90,11 @@
context 'when state is :failed' do
let(:client_options) { default_options.merge(log_level: :fatal) }
it 'reattaches' do
channel.attach do
- channel.transition_state_machine :failed, RuntimeError.new
+ channel.transition_state_machine :failed, reason: RuntimeError.new
expect(channel).to be_failed
channel.attach do
expect(channel).to be_attached
stop_reactor
end
@@ -129,11 +129,11 @@
let(:permutation_count) { connection_count * channel_count }
let(:channel_connection_ids) { [] }
it 'attaches all channels', em_timeout: 15 do
connection_count.times.map do
- Ably::Realtime::Client.new(default_options)
+ auto_close Ably::Realtime::Client.new(default_options)
end.each do |client|
channel_count.times.map do |index|
client.channel("channel-#{index}").attach do
channel_connection_ids << "#{client.connection.id}:#{index}"
next unless channel_connection_ids.count == permutation_count
@@ -146,25 +146,25 @@
end
end
context 'failure as a result of insufficient key permissions' do
let(:restricted_client) do
- Ably::Realtime::Client.new(default_options.merge(key: restricted_api_key, log_level: :fatal))
+ auto_close Ably::Realtime::Client.new(default_options.merge(key: restricted_api_key, log_level: :fatal))
end
let(:restricted_channel) { restricted_client.channel("cannot_subscribe") }
it 'emits failed event' do
restricted_channel.attach
- restricted_channel.on(:failed) do |error|
+ restricted_channel.on(:failed) do |connection_state|
expect(restricted_channel.state).to eq(:failed)
- expect(error.status).to eq(401)
+ expect(connection_state.reason.status).to eq(401)
stop_reactor
end
end
it 'calls the errback of the returned Deferrable' do
- restricted_channel.attach.errback do |channel, error|
+ restricted_channel.attach.errback do |error|
expect(restricted_channel.state).to eq(:failed)
expect(error.status).to eq(401)
stop_reactor
end
end
@@ -190,11 +190,11 @@
it 'attaches to the channel successfully and resets the channel error_reason' do
restricted_channel.attach
restricted_channel.once(:failed) do
restricted_client.close do
# A direct call to #authorise is synchronous
- restricted_client.auth.authorise(key: api_key)
+ restricted_client.auth.authorise({}, key: api_key)
restricted_client.connect do
restricted_channel.once(:attached) do
expect(restricted_channel.error_reason).to be_nil
stop_reactor
@@ -218,13 +218,14 @@
end
end
end
it 'detaches from a channel and calls the provided block' do
- channel.attach do |chan|
- chan.detach do |detached_chan|
- expect(detached_chan.state).to eq(:detached)
+ channel.attach do
+ expect(channel.state).to eq(:attached)
+ channel.detach do
+ expect(channel.state).to eq(:detached)
stop_reactor
end
end
end
@@ -247,11 +248,11 @@
end
end
it 'calls the Deferrable callback on success' do
channel.attach do
- channel.detach.callback do |channel|
+ channel.detach.callback do
expect(channel).to be_a(Ably::Realtime::Channel)
expect(channel.state).to eq(:detached)
stop_reactor
end
end
@@ -260,11 +261,11 @@
context 'when state is :failed' do
let(:client_options) { default_options.merge(log_level: :fatal) }
it 'raises an exception' do
channel.attach do
- channel.transition_state_machine :failed, RuntimeError.new
+ channel.transition_state_machine :failed, reason: RuntimeError.new
expect(channel).to be_failed
expect { channel.detach }.to raise_error Ably::Exceptions::InvalidStateChange
stop_reactor
end
end
@@ -431,10 +432,23 @@
expect(page.items.first.data).to eql(data)
stop_reactor
end
end
end
+
+ context 'and additional attributes' do
+ let(:client_id) { random_str }
+
+ it 'publishes the message with the attributes and return true indicating success' do
+ channel.publish(name, data, client_id: client_id) do
+ channel.history do |page|
+ expect(page.items.first.client_id).to eql(client_id)
+ stop_reactor
+ end
+ end
+ end
+ end
end
context 'with an array of Hash objects with :name and :data attributes' do
let(:messages) do
10.times.map do |index|
@@ -548,11 +562,11 @@
let(:published) { [] }
let(:channel_name) { random_str }
it 'publishes all messages, all success callbacks are called, and a history request confirms all messages were published' do
connection_count.times.map do
- Ably::Realtime::Client.new(client_options)
+ auto_close Ably::Realtime::Client.new(client_options)
end.each do |client|
channel = client.channels.get(channel_name)
messages.each do |message|
channel.publish(message.fetch(:name), message.fetch(:data)) do
published << message
@@ -664,11 +678,12 @@
end
context 'an :attached channel' do
it 'transitions state to :failed' do
channel.attach do
- channel.on(:failed) do |error|
+ channel.on(:failed) do |connection_state_change|
+ error = connection_state_change.reason
expect(error).to be_a(Ably::Exceptions::ConnectionFailed)
expect(error.code).to eql(80002)
stop_reactor
end
fake_error connection_error
@@ -686,11 +701,12 @@
end
end
it 'updates the channel error_reason' do
channel.attach do
- channel.on(:failed) do |error|
+ channel.on(:failed) do |connection_state_change|
+ error = connection_state_change.reason
expect(error).to be_a(Ably::Exceptions::ConnectionFailed)
expect(error.code).to eql(80002)
stop_reactor
end
fake_error connection_error
@@ -732,11 +748,11 @@
end
fake_error connection_error
end
- channel.transition_state_machine :failed, original_error
+ channel.transition_state_machine :failed, reason: original_error
end
end
end
context 'a channel ATTACH request' do
@@ -781,12 +797,12 @@
end
end
end
context 'a :failed channel' do
- let(:original_error) { RuntimeError.new }
let(:client_options) { default_options.merge(log_level: :fatal) }
+ let(:original_error) { Ably::Models::ErrorInfo.new(message: 'Error') }
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' }
@@ -799,11 +815,11 @@
end
client.connection.close
end
- channel.transition_state_machine :failed, original_error
+ channel.transition_state_machine :failed, reason: original_error
end
end
end
context 'a channel ATTACH request when connection CLOSED' do
@@ -828,15 +844,146 @@
client.close
end
end
end
end
+
+ context ':suspended' do
+ context 'an :attached channel' do
+ let(:client_options) { default_options.merge(log_level: :fatal) }
+
+ it 'transitions state to :detached' do
+ channel.attach do
+ channel.on(:detached) do
+ stop_reactor
+ end
+ client.connection.transition_state_machine :suspended
+ end
+ end
+ end
+
+ context 'a :detached channel' do
+ it 'remains in the :detached state' do
+ channel.attach do
+ channel.detach do
+ channel.on(:detached) { raise 'Detached state should not have been reached' }
+ channel.on(:error) { raise 'Error should not have been emitted' }
+
+ EventMachine.add_timer(1) do
+ expect(channel).to be_detached
+ stop_reactor
+ end
+
+ client.connection.transition_state_machine :suspended
+ end
+ end
+ end
+ end
+
+ context 'a :failed channel' do
+ let(:original_error) { RuntimeError.new }
+ 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' }
+ channel.on(:error) { raise 'Error should not have been emitted' }
+
+ EventMachine.add_timer(1) do
+ expect(channel).to be_failed
+ expect(channel.error_reason).to eql(original_error)
+ stop_reactor
+ end
+
+ client.connection.transition_state_machine :suspended
+ end
+
+ channel.transition_state_machine :failed, reason: original_error
+ end
+ end
+ end
+
+ context 'a channel ATTACH request when connection SUSPENDED' do
+ it 'raises an exception' do
+ client.connect do
+ client.connection.once(:suspended) do
+ expect { channel.attach }.to raise_error Ably::Exceptions::InvalidStateChange
+ stop_reactor
+ end
+ client.connection.transition_state_machine :suspended
+ end
+ end
+ end
+ end
end
describe '#presence' do
it 'returns a Ably::Realtime::Presence object' do
expect(channel.presence).to be_a(Ably::Realtime::Presence)
stop_reactor
+ end
+ end
+
+ context 'channel state change' do
+ it 'emits a ChannelStateChange object' do
+ channel.on(:attached) do |channel_state_change|
+ expect(channel_state_change).to be_a(Ably::Models::ChannelStateChange)
+ stop_reactor
+ end
+ channel.attach
+ end
+
+ context 'ChannelStateChange object' do
+ it 'has current state' do
+ channel.on(:attached) do |channel_state_change|
+ expect(channel_state_change.current).to eq(:attached)
+ stop_reactor
+ end
+ channel.attach
+ end
+
+ it 'has a previous state' do
+ channel.on(:attached) do |channel_state_change|
+ expect(channel_state_change.previous).to eq(:attaching)
+ stop_reactor
+ end
+ channel.attach
+ end
+
+ it 'contains a private API protocol_message attribute that is used for special state change events', :api_private do
+ channel.on(:attached) do |channel_state_change|
+ expect(channel_state_change.protocol_message).to be_a(Ably::Models::ProtocolMessage)
+ expect(channel_state_change.reason).to be_nil
+ stop_reactor
+ end
+ channel.attach
+ end
+
+ it 'has an empty reason when there is no error' do
+ channel.on(:detached) do |channel_state_change|
+ expect(channel_state_change.reason).to be_nil
+ stop_reactor
+ end
+ channel.attach do
+ channel.detach
+ 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 channel' do
+ channel.on(:failed) do |channel_state_change|
+ expect(channel_state_change.reason).to be_a(Ably::Exceptions::BaseAblyException)
+ stop_reactor
+ end
+ channel.attach do
+ error = Ably::Exceptions::ConnectionFailed.new('forced failure', 500, 50000)
+ client.connection.manager.error_received_from_server error
+ end
+ end
+ end
end
end
end
end