spec/acceptance/rest/presence_spec.rb in ably-0.1.6 vs spec/acceptance/rest/presence_spec.rb in ably-0.2.0

- old
+ new

@@ -1,67 +1,86 @@ -require "spec_helper" -require "securerandom" +require 'spec_helper' +require 'securerandom' -describe "REST" do +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) end let(:fixtures) do TestApp::APP_SPEC['channels'].first['presence'].map do |fixture| - IdiomaticRubyWrapper(fixture, stop_at: [:client_data]) + IdiomaticRubyWrapper(fixture, stop_at: [:data]) end end - describe "fetching presence" do - let(:channel) { client.channel("persisted:presence_fixtures") } + describe '#get presence' 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' 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.client_data).to eq(fixture[:client_data]) + expect(presence_message.data).to eq(fixture[:data]) end end end - describe "presence history" do - let(:channel) { client.channel("persisted:presence_fixtures") } - let(:history) { channel.presence.history } + describe 'presence #history' do + let(:channel) { client.channel('persisted:presence_fixtures') } + let(:presence_history) { channel.presence.history } - it "returns recent presence activity" do - expect(history.size).to eql(4) + it 'returns recent presence activity' do + expect(presence_history.size).to eql(4) fixtures.each do |fixture| - presence_message = history.find { |client| client.client_id == fixture['clientId'] } - expect(presence_message.client_data).to eq(fixture[:client_data]) + presence_message = presence_history.find { |client| client.client_id == fixture['clientId'] } + expect(presence_message.data).to eq(fixture[:data]) end end context 'with options' do let(:page_size) { 2 } - let(:paged_history_forward) { channel.presence.history(limit: page_size, direction: :forwards) } - it "returns recent presence activity with options passsed to Ably" do - expect(paged_history_forward).to be_a(Ably::Models::PaginatedResource) - expect(paged_history_forward.size).to eql(2) + context 'forwards' do + let(:presence_history) { channel.presence.history(direction: :forwards) } + let(:paged_history_forward) { channel.presence.history(limit: page_size, direction: :forwards) } - next_page = paged_history_forward.next_page + it 'returns recent presence activity with options passed to Ably' do + expect(paged_history_forward).to be_a(Ably::Models::PaginatedResource) + expect(paged_history_forward.size).to eql(2) - expect(paged_history_forward.first.id).to eql(history.last.id) - expect(next_page.first.id).to eql(history[page_size].id) + 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 + 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 + 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 + + expect(paged_history_backward.first.id).to eql(presence_history.first.id) + expect(next_page.first.id).to eql(presence_history[page_size].id) + end + end end end - describe "options" do + describe 'options' do let(:channel_name) { "persisted:#{SecureRandom.hex(4)}" } let(:presence) { client.channel(channel_name).presence } let(:user) { 'appid.keyuid' } let(:secret) { SecureRandom.hex(8) } let(:endpoint) do @@ -100,9 +119,126 @@ let(:options) { { option => time } } specify 'are left unchanged' do expect(history_stub).to have_been_requested 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 + end + let(:client) do + Ably::Rest::Client.new(api_key: "#{user}:#{secret}", environment: environment, protocol: protocol) + 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(:crypto) { Ably::Util::Crypto.new(cipher_options) } + + 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 + 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 + 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 + + 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 + + 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 }) + } + + 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 + 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 + 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 }) + } + + after do + expect(get_stub).to have_been_requested + end + + it 'raises a cipher error' do + expect { presence.get }.to raise_error Ably::Exceptions::CipherError + end + 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 }) + } + + after do + expect(history_stub).to have_been_requested + end + + it 'raises a cipher error' do + expect { presence.history }.to raise_error Ably::Exceptions::CipherError end end end end end