spec/acceptance/rest/presence_spec.rb in ably-0.6.2 vs spec/acceptance/rest/presence_spec.rb in ably-0.7.0
- old
+ new
@@ -1,40 +1,59 @@
+# encoding: utf-8
require 'spec_helper'
-require 'securerandom'
describe Ably::Rest::Presence do
include Ably::Modules::Conversions
- [:msgpack, :json].each do |protocol|
- context "over #{protocol}" do
- let(:client) do
- Ably::Rest::Client.new(api_key: api_key, environment: environment, protocol: protocol)
+ vary_by_protocol do
+ let(:default_options) { { api_key: api_key, environment: environment, protocol: protocol } }
+ let(:client_options) { default_options }
+ let(:client) do
+ Ably::Rest::Client.new(client_options)
+ end
+
+ let(:fixtures) do
+ TestApp::APP_SPEC['channels'].first['presence'].map do |fixture|
+ IdiomaticRubyWrapper(fixture, stop_at: [:data])
end
+ end
- let(:fixtures) do
- TestApp::APP_SPEC['channels'].first['presence'].map do |fixture|
- IdiomaticRubyWrapper(fixture, stop_at: [:data])
- end
+ context 'tested against presence fixture data set up in test app' do
+ before(:context) do
+ # When this test is run as a part of a test suite, the presence data injected in the test app may have expired
+ WebMock.disable!
+ TestApp.reload
end
- describe '#get presence' do
+ describe '#get' do
let(:channel) { client.channel('persisted:presence_fixtures') }
let(:presence) { channel.presence.get }
- it 'returns current members on the channel' do
+ it 'returns current members on the channel with their action set to :present' do
expect(presence.size).to eql(4)
fixtures.each do |fixture|
presence_message = presence.find { |client| client.client_id == fixture[:client_id] }
expect(presence_message.data).to eq(fixture[:data])
+ expect(presence_message.action).to eq(:present)
end
end
- skip 'with options'
+ context 'with :limit option' do
+ let(:page_size) { 2 }
+ let(:presence) { channel.presence.get(limit: page_size) }
+
+ it 'returns a paged response limiting number of members per page' do
+ expect(presence.size).to eql(2)
+ next_page = presence.next_page
+ expect(next_page.size).to eql(2)
+ expect(next_page).to be_last_page
+ end
+ end
end
- describe 'presence #history' do
+ describe '#history' do
let(:channel) { client.channel('persisted:presence_fixtures') }
let(:presence_history) { channel.presence.history }
it 'returns recent presence activity' do
expect(presence_history.size).to eql(4)
@@ -46,30 +65,30 @@
end
context 'with options' do
let(:page_size) { 2 }
- context 'forwards' do
+ context 'direction: :forwards' do
let(:presence_history) { channel.presence.history(direction: :forwards) }
let(:paged_history_forward) { channel.presence.history(limit: page_size, direction: :forwards) }
- it 'returns recent presence activity with options passed to Ably' do
+ it 'returns recent presence activity forwards with most recent history last' do
expect(paged_history_forward).to be_a(Ably::Models::PaginatedResource)
expect(paged_history_forward.size).to eql(2)
next_page = paged_history_forward.next_page
expect(paged_history_forward.first.id).to eql(presence_history.first.id)
expect(next_page.first.id).to eql(presence_history[page_size].id)
end
end
- context 'backwards' do
+ context 'direction: :backwards' do
let(:presence_history) { channel.presence.history(direction: :backwards) }
let(:paged_history_backward) { channel.presence.history(limit: page_size, direction: :backwards) }
- it 'returns recent presence activity with options passed to Ably' do
+ it 'returns recent presence activity backwards with most recent history first' do
expect(paged_history_backward).to be_a(Ably::Models::PaginatedResource)
expect(paged_history_backward.size).to eql(2)
next_page = paged_history_backward.next_page
@@ -77,16 +96,18 @@
expect(next_page.first.id).to eql(presence_history[page_size].id)
end
end
end
end
+ end
- describe 'options' do
- let(:channel_name) { "persisted:#{SecureRandom.hex(4)}" }
+ describe '#history' do
+ context 'with time range options' do
+ let(:channel_name) { "persisted:#{random_str(4)}" }
let(:presence) { client.channel(channel_name).presence }
let(:user) { 'appid.keyuid' }
- let(:secret) { SecureRandom.hex(8) }
+ let(:secret) { random_str(8) }
let(:endpoint) do
client.endpoint.tap do |client_end_point|
client_end_point.user = user
client_end_point.password = secret
end
@@ -94,154 +115,172 @@
let(:client) do
Ably::Rest::Client.new(api_key: "#{user}:#{secret}")
end
[:start, :end].each do |option|
- describe ":{option}", webmock: true do
+ describe ":#{option}", :webmock do
let!(:history_stub) {
- stub_request(:get, "#{endpoint}/channels/#{CGI.escape(channel_name)}/presence/history?live=true&#{option}=#{milliseconds}").
+ stub_request(:get, "#{endpoint}/channels/#{CGI.escape(channel_name)}/presence/history?#{option}=#{milliseconds}").
to_return(:body => '{}', :headers => { 'Content-Type' => 'application/json' })
}
before do
presence.history(options)
end
- context 'with milliseconds since epoch' do
+ context 'with milliseconds since epoch value' do
let(:milliseconds) { as_since_epoch(Time.now) }
let(:options) { { option => milliseconds } }
- specify 'are left unchanged' do
+ it 'uses this value in the history request' do
expect(history_stub).to have_been_requested
end
end
- context 'with Time' do
+ context 'with Time object value' do
let(:time) { Time.now }
let(:milliseconds) { as_since_epoch(time) }
let(:options) { { option => time } }
- specify 'are left unchanged' do
+ it 'converts the value to milliseconds since epoch in the hisotry request' do
expect(history_stub).to have_been_requested
end
end
end
end
end
+ end
- describe 'decoding', webmock: true do
- let(:user) { 'appid.keyuid' }
- let(:secret) { SecureRandom.hex(8) }
- let(:endpoint) do
- client.endpoint.tap do |client_end_point|
- client_end_point.user = user
- client_end_point.password = secret
- end
+ describe 'decoding', :webmock do
+ let(:user) { 'appid.keyuid' }
+ let(:secret) { random_str(8) }
+ let(:endpoint) do
+ client.endpoint.tap do |client_end_point|
+ client_end_point.user = user
+ client_end_point.password = secret
end
- let(:client) do
- Ably::Rest::Client.new(api_key: "#{user}:#{secret}", environment: environment, protocol: protocol)
- end
+ end
+ let(:client) do
+ Ably::Rest::Client.new(client_options.merge(api_key: "#{user}:#{secret}"))
+ end
- let(:data) { SecureRandom.hex(32) }
- let(:channel_name) { "persisted:#{SecureRandom.hex(4)}" }
- let(:cipher_options) { { key: SecureRandom.hex(32), algorithm: 'aes', mode: 'cbc', key_length: 256 } }
- let(:presence) { client.channel(channel_name, encrypted: true, cipher_params: cipher_options).presence }
+ let(:data) { random_str(32) }
+ let(:channel_name) { "persisted:#{random_str(4)}" }
+ let(:cipher_options) { { key: random_str(32), algorithm: 'aes', mode: 'cbc', key_length: 256 } }
+ let(:presence) { client.channel(channel_name, encrypted: true, cipher_params: cipher_options).presence }
- let(:crypto) { Ably::Util::Crypto.new(cipher_options) }
+ let(:crypto) { Ably::Util::Crypto.new(cipher_options) }
- let(:content_type) do
+ let(:content_type) do
+ if protocol == :msgpack
+ 'application/x-msgpack'
+ else
+ 'application/json'
+ end
+ end
+
+ context 'valid decodeable content' do
+ let(:serialized_encoded_message) do
if protocol == :msgpack
- 'application/x-msgpack'
+ msg = Ably::Models::PresenceMessage.new({ action: :enter, data: crypto.encrypt(data), encoding: 'utf-8/cipher+aes-256-cbc' })
+ MessagePack.pack([msg.as_json])
else
- 'application/json'
+ msg = Ably::Models::PresenceMessage.new({ action: :enter, data: Base64.encode64(crypto.encrypt(data)), encoding: 'utf-8/cipher+aes-256-cbc/base64' })
+ [msg].to_json
end
end
- context 'valid decodeable content' do
- let(:serialized_encoded_message) do
- if protocol == :msgpack
- msg = Ably::Models::PresenceMessage.new({ action: :enter, data: crypto.encrypt(data), encoding: 'utf-8/cipher+aes-256-cbc' })
- MessagePack.pack([msg.as_json])
- else
- msg = Ably::Models::PresenceMessage.new({ action: :enter, data: Base64.encode64(crypto.encrypt(data)), encoding: 'utf-8/cipher+aes-256-cbc/base64' })
- [msg].to_json
- end
+ context '#get' do
+ let!(:get_stub) {
+ stub_request(:get, "#{endpoint}/channels/#{CGI.escape(channel_name)}/presence").
+ to_return(:body => serialized_encoded_message, :headers => { 'Content-Type' => content_type })
+ }
+
+ after do
+ expect(get_stub).to have_been_requested
end
- context '#get' do
- let!(:get_stub) {
- stub_request(:get, "#{endpoint}/channels/#{CGI.escape(channel_name)}/presence").
- to_return(:body => serialized_encoded_message, :headers => { 'Content-Type' => content_type })
- }
+ it 'automaticaly decodes presence messages' do
+ present = presence.get
+ expect(present.first.encoding).to be_nil
+ expect(present.first.data).to eql(data)
+ end
+ end
- after do
- expect(get_stub).to have_been_requested
- end
+ context '#history' do
+ let!(:history_stub) {
+ stub_request(:get, "#{endpoint}/channels/#{CGI.escape(channel_name)}/presence/history").
+ to_return(:body => serialized_encoded_message, :headers => { 'Content-Type' => content_type })
+ }
- it 'automaticaly decodes presence messages' do
- present = presence.get
- expect(present.first.encoding).to be_nil
- expect(present.first.data).to eql(data)
- end
+ after do
+ expect(history_stub).to have_been_requested
end
- context '#history' do
- let!(:history_stub) {
- stub_request(:get, "#{endpoint}/channels/#{CGI.escape(channel_name)}/presence/history?live=true").
- to_return(:body => serialized_encoded_message, :headers => { 'Content-Type' => content_type })
- }
+ it 'automaticaly decodes presence messages' do
+ history = presence.history
+ expect(history.first.encoding).to be_nil
+ expect(history.first.data).to eql(data)
+ end
+ end
+ end
- after do
- expect(history_stub).to have_been_requested
- end
-
- it 'automaticaly decodes presence messages' do
- history = presence.history
- expect(history.first.encoding).to be_nil
- expect(history.first.data).to eql(data)
- end
+ context 'invalid data' do
+ let(:serialized_encoded_message_with_invalid_encoding) do
+ if protocol == :msgpack
+ msg = Ably::Models::PresenceMessage.new({ action: :enter, data: crypto.encrypt(data), encoding: 'utf-8/cipher+aes-128-cbc' })
+ MessagePack.pack([msg.as_json])
+ else
+ msg = Ably::Models::PresenceMessage.new({ action: :enter, data: Base64.encode64(crypto.encrypt(data)), encoding: 'utf-8/cipher+aes-128-cbc/base64' })
+ [msg].to_json
end
end
- context 'invalid data' do
- let(:serialized_encoded_message_with_invalid_encoding) do
- if protocol == :msgpack
- msg = Ably::Models::PresenceMessage.new({ action: :enter, data: crypto.encrypt(data), encoding: 'utf-8/cipher+aes-128-cbc' })
- MessagePack.pack([msg.as_json])
- else
- msg = Ably::Models::PresenceMessage.new({ action: :enter, data: Base64.encode64(crypto.encrypt(data)), encoding: 'utf-8/cipher+aes-128-cbc/base64' })
- [msg].to_json
- end
+ context '#get' do
+ let(:client_options) { default_options.merge(log_level: :fatal) }
+ let!(:get_stub) {
+ stub_request(:get, "#{endpoint}/channels/#{CGI.escape(channel_name)}/presence").
+ to_return(:body => serialized_encoded_message_with_invalid_encoding, :headers => { 'Content-Type' => content_type })
+ }
+ let(:presence_message) { presence.get.first }
+
+ after do
+ expect(get_stub).to have_been_requested
end
- context '#get' do
- let!(:get_stub) {
- stub_request(:get, "#{endpoint}/channels/#{CGI.escape(channel_name)}/presence").
- to_return(:body => serialized_encoded_message_with_invalid_encoding, :headers => { 'Content-Type' => content_type })
- }
+ it 'returns the messages still encoded' do
+ expect(presence_message.encoding).to match(/cipher\+aes-128-cbc/)
+ end
- after do
- expect(get_stub).to have_been_requested
+ it 'logs a cipher error' do
+ expect(client.logger).to receive(:error) do |message|
+ expect(message).to match(/Cipher algorithm [\w-]+ does not match/)
end
+ presence.get
+ end
+ end
- it 'raises a cipher error' do
- expect { presence.get }.to raise_error Ably::Exceptions::CipherError
- end
+ context '#history' do
+ let(:client_options) { default_options.merge(log_level: :fatal) }
+ let!(:history_stub) {
+ stub_request(:get, "#{endpoint}/channels/#{CGI.escape(channel_name)}/presence/history").
+ to_return(:body => serialized_encoded_message_with_invalid_encoding, :headers => { 'Content-Type' => content_type })
+ }
+ let(:presence_message) { presence.history.first }
+
+ after do
+ expect(history_stub).to have_been_requested
end
- context '#history' do
- let!(:history_stub) {
- stub_request(:get, "#{endpoint}/channels/#{CGI.escape(channel_name)}/presence/history?live=true").
- to_return(:body => serialized_encoded_message_with_invalid_encoding, :headers => { 'Content-Type' => content_type })
- }
+ it 'returns the messages still encoded' do
+ expect(presence_message.encoding).to match(/cipher\+aes-128-cbc/)
+ end
- after do
- expect(history_stub).to have_been_requested
+ it 'logs a cipher error' do
+ expect(client.logger).to receive(:error) do |message|
+ expect(message).to match(/Cipher algorithm [\w-]+ does not match/)
end
-
- it 'raises a cipher error' do
- expect { presence.history }.to raise_error Ably::Exceptions::CipherError
- end
+ presence.history
end
end
end
end
end