lib/submodules/ably-ruby/spec/acceptance/realtime/presence_spec.rb in ably-rest-0.8.6 vs lib/submodules/ably-ruby/spec/acceptance/realtime/presence_spec.rb in ably-rest-0.8.9
- old
+ new
@@ -131,13 +131,13 @@
end
context 'with supported data payload content type' do
def register_presence_and_check_data(method_name, data)
if method_name.to_s.match(/_client/)
- presence_client_one.public_send(method_name, client_id, data: data)
+ presence_client_one.public_send(method_name, client_id, data)
else
- presence_client_one.public_send(method_name, data: data)
+ presence_client_one.public_send(method_name, data)
end
presence_client_one.subscribe do |presence_message|
expect(presence_message.data).to eql(data)
stop_reactor
@@ -186,13 +186,13 @@
end
context 'with unsupported data payload content type' do
def presence_action(method_name, data)
if method_name.to_s.match(/_client/)
- presence_client_one.public_send(method_name, client_id, data: data)
+ presence_client_one.public_send(method_name, client_id, data)
else
- presence_client_one.public_send(method_name, data: data)
+ presence_client_one.public_send(method_name, data)
end
end
context 'Integer' do
let(:data) { 1 }
@@ -507,28 +507,31 @@
end
end
end
context '250 existing (present) members on a channel (3 SYNC pages)' do
- context 'requires at least 3 SYNC ProtocolMessages' do
+ context 'requires at least 3 SYNC ProtocolMessages', em_timeout: 30 do
let(:enter_expected_count) { 250 }
let(:present) { [] }
let(:entered) { [] }
let(:sync_pages_received) { [] }
let(:client_one) { auto_close Ably::Realtime::Client.new(client_options.merge(auth_callback: wildcard_token)) }
def setup_members_on(presence)
enter_expected_count.times do |index|
- presence.enter_client("client:#{index}") do |message|
- entered << message
- next unless entered.count == enter_expected_count
- yield
+ # 10 messages per second max rate on simulation accounts
+ EventMachine.add_timer(index / 10) do
+ presence.enter_client("client:#{index}") do |message|
+ entered << message
+ next unless entered.count == enter_expected_count
+ yield
+ end
end
end
end
- context 'when a client attaches to the presence channel', em_timeout: 10 do
+ context 'when a client attaches to the presence channel' do
it 'emits :present for each member' do
setup_members_on(presence_client_one) do
presence_anonymous_client.subscribe(:present) do |present_message|
expect(present_message.action).to eq(:present)
present << present_message
@@ -672,38 +675,42 @@
end
end
context '#get' do
context 'with :wait_for_sync option set to true' do
- it 'waits until sync is complete', em_timeout: 15 do
+ it 'waits until sync is complete', em_timeout: 30 do # allow for slow connections and lots of messages
enter_expected_count.times do |index|
- presence_client_one.enter_client("client:#{index}") do |message|
- entered << message
- next unless entered.count == enter_expected_count
+ EventMachine.add_timer(index / 10) do
+ presence_client_one.enter_client("client:#{index}") do |message|
+ entered << message
+ next unless entered.count == enter_expected_count
- presence_anonymous_client.get(wait_for_sync: true) do |members|
- expect(members.map(&:client_id).uniq.count).to eql(enter_expected_count)
- expect(members.count).to eql(enter_expected_count)
- stop_reactor
+ presence_anonymous_client.get(wait_for_sync: true) do |members|
+ expect(members.map(&:client_id).uniq.count).to eql(enter_expected_count)
+ expect(members.count).to eql(enter_expected_count)
+ stop_reactor
+ end
end
end
end
end
end
context 'by default' do
- it 'it does not wait for sync', em_timeout: 15 do
+ it 'it does not wait for sync', em_timeout: 30 do # allow for slow connections and lots of messages
enter_expected_count.times do |index|
- presence_client_one.enter_client("client:#{index}") do |message|
- entered << message
- next unless entered.count == enter_expected_count
+ EventMachine.add_timer(index / 10) do
+ presence_client_one.enter_client("client:#{index}") do |message|
+ entered << message
+ next unless entered.count == enter_expected_count
- channel_anonymous_client.attach do
- presence_anonymous_client.get do |members|
- expect(presence_anonymous_client.members).to_not be_in_sync
- expect(members.count).to eql(0)
- stop_reactor
+ channel_anonymous_client.attach do
+ presence_anonymous_client.get do |members|
+ expect(presence_anonymous_client.members).to_not be_in_sync
+ expect(members.count).to eql(0)
+ stop_reactor
+ end
end
end
end
end
end
@@ -736,33 +743,24 @@
end
end
end
context '#enter' do
- it 'allows client_id to be set on enter for anonymous clients' do
- channel_anonymous_client.presence.enter client_id: "123"
-
- channel_anonymous_client.presence.subscribe do |presence|
- expect(presence.client_id).to eq("123")
- stop_reactor
- end
- end
-
context 'data attribute' do
context 'when provided as argument option to #enter' do
- it 'remains intact following #leave' do
+ it 'changes to value provided in #leave' do
leave_callback_called = false
- presence_client_one.enter(data: 'stored') do
+ presence_client_one.enter('stored') do
expect(presence_client_one.data).to eql('stored')
presence_client_one.leave do |presence|
leave_callback_called = true
end
presence_client_one.on(:left) do
- expect(presence_client_one.data).to eql('stored')
+ expect(presence_client_one.data).to eql(nil)
EventMachine.next_tick do
expect(leave_callback_called).to eql(true)
stop_reactor
end
@@ -783,24 +781,19 @@
stop_reactor
end
end
end
- it 'raises an exception if client_id is not set' do
- expect { channel_anonymous_client.presence.enter }.to raise_error(Ably::Exceptions::IncompatibleClientId, /without a client_id/)
- stop_reactor
- end
-
context 'without necessary capabilities to join presence' do
let(:restricted_client) do
auto_close Ably::Realtime::Client.new(default_options.merge(key: restricted_api_key, log_level: :fatal))
end
let(:restricted_channel) { restricted_client.channel("cansubscribe:channel") }
let(:restricted_presence) { restricted_channel.presence }
it 'calls the Deferrable errback on capabilities failure' do
- restricted_presence.enter(client_id: 'clientId').tap do |deferrable|
+ restricted_presence.enter_client('bob').tap do |deferrable|
deferrable.callback { raise "Should not succeed" }
deferrable.errback { stop_reactor }
end
end
end
@@ -808,11 +801,11 @@
it_should_behave_like 'a public presence method', :enter, :entered, {}
end
context '#update' do
it 'without previous #enter automatically enters' do
- presence_client_one.update(data: data_payload) do
+ presence_client_one.update(data_payload) do
EventMachine.add_timer(1) do
expect(presence_client_one.state).to eq(:entered)
stop_reactor
end
end
@@ -821,11 +814,11 @@
context 'when ENTERED' do
it 'has no effect on the state' do
presence_client_one.enter do
presence_client_one.once_state_changed { fail 'State should not have changed ' }
- presence_client_one.update(data: data_payload) do
+ presence_client_one.update(data_payload) do
EventMachine.add_timer(1) do
expect(presence_client_one.state).to eq(:entered)
presence_client_one.off
stop_reactor
end
@@ -833,21 +826,21 @@
end
end
end
it 'updates the data if :data argument provided' do
- presence_client_one.enter(data: 'prior') do
- presence_client_one.update(data: data_payload)
+ presence_client_one.enter('prior') do
+ presence_client_one.update(data_payload)
end
presence_client_one.subscribe(:update) do |message|
expect(message.data).to eql(data_payload)
stop_reactor
end
end
it 'updates the data to nil if :data argument is not provided (assumes nil value)' do
- presence_client_one.enter(data: 'prior') do
+ presence_client_one.enter('prior') do
presence_client_one.update
end
presence_client_one.subscribe(:update) do |message|
expect(message.data).to be_nil
stop_reactor
@@ -862,37 +855,37 @@
let(:data) { random_str }
let(:enter_data) { random_str }
context 'when set to a string' do
it 'emits the new data for the leave event' do
- presence_client_one.enter data: enter_data do
- presence_client_one.leave data: data
+ presence_client_one.enter enter_data do
+ presence_client_one.leave data
end
presence_client_one.subscribe(:leave) do |presence_message|
expect(presence_message.data).to eql(data)
stop_reactor
end
end
end
context 'when set to nil' do
- it 'emits a nil value for the data attribute when leaving' do
- presence_client_one.enter data: enter_data do
- presence_client_one.leave data: nil
+ it 'emits the last value for the data attribute when leaving' do
+ presence_client_one.enter enter_data do
+ presence_client_one.leave nil
end
presence_client_one.subscribe(:leave) do |presence_message|
expect(presence_message.data).to eql(enter_data)
stop_reactor
end
end
end
- context 'when not passed as an argument' do
- it 'emits the previously defined value as a convenience' do
- presence_client_one.enter data: enter_data do
+ context 'when not passed as an argument (i.e. nil)' do
+ it 'emits the previous value for the data attribute when leaving' do
+ presence_client_one.enter enter_data do
presence_client_one.leave
end
presence_client_one.subscribe(:leave) do |presence_message|
expect(presence_message.data).to eql(enter_data)
@@ -901,14 +894,14 @@
end
end
context 'and sync is complete' do
it 'does not cache members that have left' do
- presence_client_one.enter data: enter_data do
+ presence_client_one.enter enter_data do
expect(presence_client_one.members).to be_in_sync
expect(presence_client_one.members.send(:members).count).to eql(1)
- presence_client_one.leave data: data
+ presence_client_one.leave data
end
presence_client_one.subscribe(:leave) do |presence_message|
expect(presence_message.data).to eql(data)
expect(presence_client_one.members.send(:members).count).to eql(0)
@@ -926,23 +919,23 @@
it_should_behave_like 'a public presence method', :leave, :left, {}, enter_first: true
end
context ':left event' do
it 'emits the data defined in enter' do
- channel_client_one.presence.enter(data: 'data') do
+ channel_client_one.presence.enter('data') do
channel_client_one.presence.leave
end
channel_client_two.presence.subscribe(:leave) do |message|
expect(message.data).to eql('data')
stop_reactor
end
end
it 'emits the data defined in update' do
- channel_client_one.presence.enter(data: 'something else') do
- channel_client_one.presence.update(data: 'data') do
+ channel_client_one.presence.enter('something else') do
+ channel_client_one.presence.update('data') do
channel_client_one.presence.leave
end
end
channel_client_two.presence.subscribe(:leave) do |message|
@@ -975,11 +968,11 @@
end
end
it 'enters a channel and sets the data based on the provided :data option' do
client_count.times do |client_id|
- presence_client_one.enter_client("client:#{client_id}", data: data)
+ presence_client_one.enter_client("client:#{client_id}", data)
end
presence_anonymous_client.subscribe(:enter) do |presence|
expect(presence.data).to eql(data)
clients << presence
@@ -1031,11 +1024,11 @@
it 'updates the data attribute for the member when :data option provided' do
updated_callback_count = 0
client_count.times do |client_id|
presence_client_one.enter_client("client:#{client_id}") do
- presence_client_one.update_client("client:#{client_id}", data: data) do
+ presence_client_one.update_client("client:#{client_id}", data) do
updated_callback_count += 1
end
end
end
@@ -1066,11 +1059,11 @@
it 'enters if not already entered' do
updated_callback_count = 0
client_count.times do |client_id|
- presence_client_one.update_client("client:#{client_id}", data: data) do
+ presence_client_one.update_client("client:#{client_id}", data) do
updated_callback_count += 1
end
end
presence_anonymous_client.subscribe(:enter) do |presence|
@@ -1096,12 +1089,12 @@
context 'multiple times on the same channel with different client_ids' do
it 'emits the :leave event for each client_id' do
left_callback_count = 0
client_count.times do |client_id|
- presence_client_one.enter_client("client:#{client_id}", data: random_str) do
- presence_client_one.leave_client("client:#{client_id}", data: data) do
+ presence_client_one.enter_client("client:#{client_id}", random_str) do
+ presence_client_one.leave_client("client:#{client_id}", data) do
left_callback_count += 1
end
end
end
@@ -1141,12 +1134,12 @@
end
end
context 'with a new value in :data option' do
it 'emits the leave event with the new data value' do
- presence_client_one.enter_client("client:unique", data: random_str) do
- presence_client_one.leave_client("client:unique", data: data)
+ presence_client_one.enter_client("client:unique", random_str) do
+ presence_client_one.leave_client("client:unique", data)
end
presence_client_one.subscribe(:leave) do |presence_message|
expect(presence_message.data).to eql(data)
stop_reactor
@@ -1154,12 +1147,12 @@
end
end
context 'with a nil value in :data option' do
it 'emits the leave event with the previous value as a convenience' do
- presence_client_one.enter_client("client:unique", data: data) do
- presence_client_one.leave_client("client:unique", data: nil)
+ presence_client_one.enter_client("client:unique", data) do
+ presence_client_one.leave_client("client:unique", nil)
end
presence_client_one.subscribe(:leave) do |presence_message|
expect(presence_message.data).to eql(data)
stop_reactor
@@ -1167,11 +1160,11 @@
end
end
context 'with no :data option' do
it 'emits the leave event with the previous value as a convenience' do
- presence_client_one.enter_client("client:unique", data: data) do
+ presence_client_one.enter_client("client:unique", data) do
presence_client_one.leave_client("client:unique")
end
presence_client_one.subscribe(:leave) do |presence_message|
expect(presence_message.data).to eql(data)
@@ -1223,20 +1216,28 @@
expect { presence_client_one.get }.to raise_error Ably::Exceptions::InvalidStateChange, /Operation is not allowed when channel is in STATE.failed/i
stop_reactor
end
end
- context 'during a sync' do
+ context 'during a sync', em_timeout: 30 do
let(:pages) { 2 }
let(:members_per_page) { 100 }
let(:sync_pages_received) { [] }
let(:client_one) { auto_close Ably::Realtime::Client.new(client_options.merge(auth_callback: wildcard_token)) }
let(:client_options) { default_options.merge(log_level: :none) }
def connect_members_deferrables
(members_per_page * pages + 1).times.map do |index|
- presence_client_one.enter_client("client:#{index}")
+ # rate limit to 10 per second
+ EventMachine::DefaultDeferrable.new.tap do |deferrable|
+ EventMachine.add_timer(index / 10) do
+ presence_client_one.enter_client("client:#{index}").tap do |enter_deferrable|
+ enter_deferrable.callback { |*args| deferrable.succeed *args }
+ enter_deferrable.errback { |*args| deferrable.fail *args }
+ end
+ end
+ end
end
end
context 'when :wait_for_sync is true' do
it 'fails if the connection fails' do
@@ -1314,13 +1315,13 @@
presence_client_one.get(connection_id: client_one.connection.id) do |members|
expect(members.count).to eq(1)
expect(members.first.connection_id).to eql(client_one.connection.id)
- presence_client_one.get(connection_id: client_two.connection.id) do |members|
- expect(members.count).to eq(1)
- expect(members.first.connection_id).to eql(client_two.connection.id)
+ presence_client_one.get(connection_id: client_two.connection.id) do |members_two|
+ expect(members_two.count).to eq(1)
+ expect(members_two.first.connection_id).to eql(client_two.connection.id)
stop_reactor
end
end
end
end
@@ -1337,14 +1338,14 @@
presence_client_one.get(client_id: client_one_id) do |members|
expect(members.count).to eq(1)
expect(members.first.client_id).to eql(client_one_id)
expect(members.first.connection_id).to eql(client_one.connection.id)
- presence_client_one.get(client_id: client_two_id) do |members|
- expect(members.count).to eq(1)
- expect(members.first.client_id).to eql(client_two_id)
- expect(members.first.connection_id).to eql(client_two.connection.id)
+ presence_client_one.get(client_id: client_two_id) do |members_two|
+ expect(members_two.count).to eq(1)
+ expect(members_two.first.client_id).to eql(client_two_id)
+ expect(members_two.first.connection_id).to eql(client_two.connection.id)
stop_reactor
end
end
end
end
@@ -1467,12 +1468,12 @@
context '#unsubscribe' do
context 'with no arguments' do
it 'removes the callback for all presence events' do
when_all(channel_client_one.attach, channel_client_two.attach) do
subscribe_callback = proc { raise 'Should not be called' }
- presence_client_two.subscribe &subscribe_callback
- presence_client_two.unsubscribe &subscribe_callback
+ presence_client_two.subscribe(&subscribe_callback)
+ presence_client_two.unsubscribe(&subscribe_callback)
presence_client_one.enter
presence_client_one.update
presence_client_one.leave do
EventMachine.add_timer(1) do
@@ -1502,11 +1503,11 @@
end
end
context 'REST #get' do
it 'returns current members' do
- presence_client_one.enter(data: data_payload) do
+ presence_client_one.enter(data_payload) do
members_page = channel_rest_client_one.presence.get
this_member = members_page.items.first
expect(this_member).to be_a(Ably::Models::PresenceMessage)
expect(this_member.client_id).to eql(client_one.client_id)
@@ -1515,11 +1516,11 @@
stop_reactor
end
end
it 'returns no members once left' do
- presence_client_one.enter(data: data_payload) do
+ presence_client_one.enter(data_payload) do
presence_client_one.leave do
members_page = channel_rest_client_one.presence.get
expect(members_page.items.count).to eql(0)
stop_reactor
end
@@ -1545,36 +1546,38 @@
context 'in channel options' do
let(:client_one) { auto_close Ably::Realtime::Client.new(default_options) }
it 'is converted into UTF_8' do
- presence_client_one.enter(client_id: client_id)
- presence_client_one.on(:entered) do |presence|
- expect(presence.client_id.encoding).to eql(Encoding::UTF_8)
- expect(presence.client_id.encode(Encoding::ASCII_8BIT)).to eql(client_id)
- stop_reactor
+ channel_client_one.attach do
+ presence_client_one.subscribe(:enter) do |presence|
+ expect(presence.client_id.encoding).to eql(Encoding::UTF_8)
+ expect(presence.client_id.encode(Encoding::ASCII_8BIT)).to eql(client_id)
+ stop_reactor
+ end
+ presence_anonymous_client.enter_client(client_id)
end
end
end
end
context 'encoding and decoding of presence message data' do
- let(:secret_key) { random_str }
+ let(:secret_key) { Ably::Util::Crypto.generate_random_key(256) }
let(:cipher_options) { { key: secret_key, algorithm: 'aes', mode: 'cbc', key_length: 256 } }
let(:channel_name) { random_str }
- let(:encrypted_channel) { client_one.channel(channel_name, encrypted: true, cipher_params: cipher_options) }
- let(:channel_rest_client_one) { client_one.rest_client.channel(channel_name, encrypted: true, cipher_params: cipher_options) }
+ let(:encrypted_channel) { client_one.channel(channel_name, cipher: cipher_options) }
+ let(:channel_rest_client_one) { client_one.rest_client.channel(channel_name, cipher: cipher_options) }
let(:crypto) { Ably::Util::Crypto.new(cipher_options) }
- let(:data) { { 'key' => random_str } }
+ let(:data) { { 'hash_id' => random_str } }
let(:data_as_json) { data.to_json }
let(:data_as_cipher) { crypto.encrypt(data.to_json) }
it 'encrypts presence message data' do
encrypted_channel.attach do
- encrypted_channel.presence.enter data: data
+ encrypted_channel.presence.enter data
end
encrypted_channel.presence.__incoming_msgbus__.unsubscribe(:presence) # remove all subscribe callbacks that could decrypt the message
encrypted_channel.presence.__incoming_msgbus__.subscribe(:presence) do |presence|
if protocol == :json
@@ -1589,11 +1592,11 @@
end
context '#subscribe' do
it 'emits decrypted enter events' do
encrypted_channel.attach do
- encrypted_channel.presence.enter data: data
+ encrypted_channel.presence.enter data
end
encrypted_channel.presence.subscribe(:enter) do |presence_message|
expect(presence_message.encoding).to be_nil
expect(presence_message.data).to eql(data)
@@ -1601,12 +1604,12 @@
end
end
it 'emits decrypted update events' do
encrypted_channel.attach do
- encrypted_channel.presence.enter(data: 'to be updated') do
- encrypted_channel.presence.update data: data
+ encrypted_channel.presence.enter('to be updated') do
+ encrypted_channel.presence.update data
end
end
encrypted_channel.presence.subscribe(:update) do |presence_message|
expect(presence_message.encoding).to be_nil
@@ -1615,11 +1618,11 @@
end
end
it 'emits previously set data for leave events' do
encrypted_channel.attach do
- encrypted_channel.presence.enter(data: data) do
+ encrypted_channel.presence.enter(data) do
encrypted_channel.presence.leave
end
end
encrypted_channel.presence.subscribe(:leave) do |presence_message|
@@ -1630,11 +1633,11 @@
end
end
context '#get' do
it 'returns a list of members with decrypted data' do
- encrypted_channel.presence.enter(data: data) do
+ encrypted_channel.presence.enter(data) do
encrypted_channel.presence.get do |members|
member = members.first
expect(member.encoding).to be_nil
expect(member.data).to eql(data)
stop_reactor
@@ -1643,26 +1646,26 @@
end
end
context 'REST #get' do
it 'returns a list of members with decrypted data' do
- encrypted_channel.presence.enter(data: data) do
+ encrypted_channel.presence.enter(data) do
member = channel_rest_client_one.presence.get.items.first
expect(member.encoding).to be_nil
expect(member.data).to eql(data)
stop_reactor
end
end
end
context 'when cipher settings do not match publisher' do
let(:client_options) { default_options.merge(log_level: :fatal) }
- let(:incompatible_cipher_options) { { key: secret_key, algorithm: 'aes', mode: 'cbc', key_length: 128 } }
- let(:incompatible_encrypted_channel) { client_two.channel(channel_name, encrypted: true, cipher_params: incompatible_cipher_options) }
+ let(:incompatible_cipher_options) { { key: Ably::Util::Crypto.generate_random_key(128), algorithm: 'aes', mode: 'cbc', key_length: 128 } }
+ let(:incompatible_encrypted_channel) { client_two.channel(channel_name, cipher: incompatible_cipher_options) }
it 'delivers an unencoded presence message left with encoding value' do
- encrypted_channel.presence.enter data: data
+ encrypted_channel.presence.enter data
incompatible_encrypted_channel.presence.subscribe(:enter) do
incompatible_encrypted_channel.presence.get do |members|
member = members.first
expect(member.encoding).to match(/cipher\+aes-256-cbc/)
@@ -1679,11 +1682,11 @@
expect(error.message).to match(/Cipher algorithm AES-128-CBC does not match/)
stop_reactor
end
encrypted_channel.attach do
- encrypted_channel.presence.enter data: data
+ encrypted_channel.presence.enter data
end
end
end
end
end
@@ -1705,18 +1708,18 @@
expect(members.count).to eq(0)
expect(message.data).to eql(data_payload)
stop_reactor
end
end
- presence_client_one.enter(data: data_payload) do
+ presence_client_one.enter(data_payload) do
presence_client_one.leave
end
end
end
context 'connection failure mid-way through a large member sync' do
- let(:members_count) { 400 }
+ let(:members_count) { 250 }
let(:sync_pages_received) { [] }
let(:client_options) { default_options.merge(log_level: :error) }
it 'resumes the SYNC operation', em_timeout: 15 do
when_all(*members_count.times.map do |index|
@@ -1724,10 +1727,10 @@
end) do
channel_client_two.attach do
client_two.connection.transport.__incoming_protocol_msgbus__.subscribe(:protocol_message) do |protocol_message|
if protocol_message.action == :sync
sync_pages_received << protocol_message
- force_connection_failure client_two if sync_pages_received.count == 2
+ force_connection_failure client_two if sync_pages_received.count == 1
end
end
end
presence_client_two.get(wait_for_sync: true) do |members|