spec/acceptance/rest/auth_spec.rb in ably-0.1.6 vs spec/acceptance/rest/auth_spec.rb in ably-0.2.0
- old
+ new
@@ -1,21 +1,47 @@
-require "spec_helper"
-require "securerandom"
+require 'spec_helper'
+require 'securerandom'
-describe "REST" do
+describe Ably::Auth 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(:auth) { client.auth }
+ let(:content_type) do
+ if protocol == :msgpack
+ 'application/x-msgpack'
+ else
+ 'application/json'
+ end
+ end
+ def request_body_includes(request, protocol, key, val)
+ body = if protocol == :msgpack
+ MessagePack.unpack(request.body)
+ else
+ JSON.parse(request.body)
+ end
+ body[key.to_s].to_s == val.to_s
+ end
+
+ def serialize(object, protocol)
+ if protocol == :msgpack
+ MessagePack.pack(token_response)
+ else
+ JSON.dump(token_response)
+ end
+ end
+
describe "#request_token" do
let(:ttl) { 30 * 60 }
- let(:capability) { { :foo => ["publish"] } }
+ let(:capability) { { :foo => ['publish'] } }
- it "returns the requested token" do
+ it 'returns the requested token' do
actual_token = auth.request_token(
ttl: ttl,
capability: capability
)
@@ -23,20 +49,25 @@
expect(actual_token.key_id).to match(/^#{key_id}$/)
expect(actual_token.issued_at).to be_within(2).of(Time.now)
expect(actual_token.expires_at).to be_within(2).of(Time.now + ttl)
end
- %w(client_id ttl timestamp capability nonce).each do |option|
+ %w(client_id capability nonce timestamp ttl).each do |option|
context "option :#{option}", webmock: true do
let(:random) { SecureRandom.random_number(1_000_000_000).to_s }
let(:options) { { option.to_sym => random } }
- let(:token_response) { { access_token: {} }.to_json }
+ let(:token_response) { { access_token: {} } }
let!(:request_token_stub) do
stub_request(:post, "#{client.endpoint}/keys/#{key_id}/requestToken").
- with(:body => hash_including({ option => random })).
- to_return(:status => 201, :body => token_response, :headers => { 'Content-Type' => 'application/json' })
+ with do |request|
+ request_body_includes(request, protocol, option, random)
+ end.to_return(
+ :status => 201,
+ :body => serialize(token_response, protocol),
+ :headers => { 'Content-Type' => content_type }
+ )
end
before { auth.request_token options }
it 'overrides default' do
@@ -53,46 +84,50 @@
let(:token_request) { auth.create_token_request(token_options) }
let(:mac) do
hmac_for(token_request, key_secret)
end
- let(:token_response) { { access_token: {} }.to_json }
+ let(:token_response) { { access_token: {} } }
let!(:request_token_stub) do
stub_request(:post, "#{client.endpoint}/keys/#{key_id}/requestToken").
- with(:body => hash_including({ 'mac' => mac })).
- to_return(:status => 201, :body => token_response, :headers => { 'Content-Type' => 'application/json' })
+ with do |request|
+ request_body_includes(request, protocol, 'mac', mac)
+ end.to_return(
+ :status => 201,
+ :body => serialize(token_response, protocol),
+ :headers => { 'Content-Type' => content_type })
end
let!(:token) { auth.request_token(token_options) }
specify 'key_id is used in request and signing uses key_secret' do
expect(request_token_stub).to have_been_requested
end
end
- context "with :query_time option" do
+ context 'with :query_time option' do
let(:options) { { query_time: true } }
it 'queries the server for the time' do
expect(client).to receive(:time).and_call_original
auth.request_token(options)
end
end
- context "without :query_time option" do
+ context 'without :query_time option' do
let(:options) { { query_time: false } }
it 'queries the server for the time' do
expect(client).to_not receive(:time)
auth.request_token(options)
end
end
context 'with :auth_url option', webmock: true do
let(:auth_url) { 'https://www.fictitious.com/get_token' }
- let(:token_request) { { id: key_id }.to_json }
- let(:token_response) { { access_token: { } }.to_json }
+ let(:token_request) { { id: key_id } }
+ let(:token_response) { { access_token: { } } }
let(:query_params) { nil }
let(:headers) { nil }
let(:auth_method) { :get }
let(:options) do
{
@@ -103,19 +138,28 @@
}
end
let!(:auth_url_request_stub) do
stub = stub_request(auth_method, auth_url)
- stub.with(:query => hash_including(query_params)) unless query_params.nil?
- stub.with(:header => hash_including(headers)) unless headers.nil?
- stub.to_return(:status => 201, :body => token_request, :headers => { 'Content-Type' => 'application/json' })
+ stub.with(:query => query_params) unless query_params.nil?
+ stub.with(:headers => headers) unless headers.nil?
+ stub.to_return(
+ :status => 201,
+ :body => token_request.to_json,
+ :headers => { 'Content-Type' => 'application/json' }
+ )
end
let!(:request_token_stub) do
stub_request(:post, "#{client.endpoint}/keys/#{key_id}/requestToken").
- with(:body => hash_including({ 'id' => key_id })).
- to_return(:status => 201, :body => token_response, :headers => { 'Content-Type' => 'application/json' })
+ with do |request|
+ request_body_includes(request, protocol, 'id', key_id)
+ end.to_return(
+ :status => 201,
+ :body => serialize(token_response, protocol),
+ :headers => { 'Content-Type' => content_type }
+ )
end
context 'valid' do
before { auth.request_token options }
@@ -242,34 +286,34 @@
expect { auth.authorise(force: true) }.to change { auth.current_token }
end
end
end
- describe "#create_token_request" do
+ describe '#create_token_request' do
let(:ttl) { 60 * 60 }
let(:capability) { { :foo => ["publish"] } }
let(:options) { Hash.new }
subject { auth.create_token_request(options) }
- it "uses the key ID from the client" do
+ it 'uses the key ID from the client' do
expect(subject[:id]).to eql(key_id)
end
- it "uses the default TTL" do
+ it 'uses the default TTL' do
expect(subject[:ttl]).to eql(Ably::Models::Token::DEFAULTS[:ttl])
end
- it "uses the default capability" do
+ it 'uses the default capability' do
expect(subject[:capability]).to eql(Ably::Models::Token::DEFAULTS[:capability].to_json)
end
- it "has a unique nonce" do
+ it 'has a unique nonce' do
unique_nonces = 100.times.map { auth.create_token_request[:nonce] }
expect(unique_nonces.uniq.length).to eql(100)
end
- it "has a nonce of at least 16 characters" do
+ it 'has a nonce of at least 16 characters' do
expect(subject[:nonce].length).to be >= 16
end
%w(ttl capability nonce timestamp client_id).each do |attribute|
context "with option :#{attribute}" do
@@ -281,51 +325,51 @@
expect(subject[attribute.to_sym]).to eql(option_value)
end
end
end
- context "invalid attributes" do
+ context 'invalid attributes' do
let(:options) { { nonce: 'valid', is_not_used_by_token_request: 'invalid' } }
specify 'are ignored' do
expect(subject.keys).to_not include(:is_not_used_by_token_request)
expect(subject.keys).to include(:nonce)
expect(subject[:nonce]).to eql('valid')
end
end
- context "missing key ID and/or secret" do
+ context 'missing key ID and/or secret' do
let(:client) { Ably::Rest::Client.new(auth_url: 'http://example.com', protocol: protocol) }
- it "should raise an exception if key secret is missing" do
+ it 'should raise an exception if key secret is missing' do
expect { auth.create_token_request(key_id: 'id') }.to raise_error Ably::Exceptions::TokenRequestError
end
- it "should raise an exception if key id is missing" do
+ it 'should raise an exception if key id is missing' do
expect { auth.create_token_request(key_secret: 'secret') }.to raise_error Ably::Exceptions::TokenRequestError
end
end
- context "with :query_time option" do
+ context 'with :query_time option' do
let(:time) { Time.now - 30 }
let(:options) { { query_time: true } }
it 'queries the server for the time' do
expect(client).to receive(:time).and_return(time)
expect(subject[:timestamp]).to eql(time.to_i)
end
end
- context "with :timestamp option" do
+ context 'with :timestamp option' do
let(:token_request_time) { Time.now + 5 }
let(:options) { { timestamp: token_request_time } }
it 'uses the provided timestamp' do
expect(subject[:timestamp]).to eql(token_request_time.to_i)
end
end
- context "signing" do
+ context 'signing' do
let(:options) do
{
id: SecureRandom.hex,
ttl: SecureRandom.hex,
capability: SecureRandom.hex,
@@ -340,11 +384,11 @@
expect(subject[:mac]).to eql(hmac)
end
end
end
- context "client with token authentication" do
+ context 'client with token authentication' do
let(:capability) { { :foo => ["publish"] } }
describe "with token_id argument" do
let(:ttl) { 60 * 60 }
let(:token) do
@@ -356,32 +400,32 @@
let(:token_id) { token.id }
let(:token_auth_client) do
Ably::Rest::Client.new(token_id: token_id, environment: environment, protocol: protocol)
end
- it "authenticates successfully" do
- expect(token_auth_client.channel("foo").publish("event", "data")).to be_truthy
+ it 'authenticates successfully' do
+ expect(token_auth_client.channel('foo').publish('event', 'data')).to be_truthy
end
- it "disallows publishing on unspecified capability channels" do
- expect { token_auth_client.channel("bar").publish("event", "data") }.to raise_error do |error|
+ it 'disallows publishing on unspecified capability channels' do
+ expect { token_auth_client.channel('bar').publish('event', 'data') }.to raise_error do |error|
expect(error).to be_a(Ably::Exceptions::InvalidToken)
expect(error.status).to eql(401)
expect(error.code).to eql(40160)
end
end
- it "fails if timestamp is invalid" do
+ it 'fails if timestamp is invalid' do
expect { auth.request_token(timestamp: Time.now - 180) }.to raise_error do |error|
expect(error).to be_a(Ably::Exceptions::InvalidToken)
expect(error.status).to eql(401)
expect(error.code).to eql(40101)
end
end
end
- describe "implicit through client id" do
+ describe 'implicit through client id' do
let(:client_id) { '999' }
let(:client) do
Ably::Rest::Client.new(api_key: api_key, client_id: client_id, environment: environment, protocol: protocol)
end
let(:token_id) { 'unique-token-id' }
@@ -402,28 +446,28 @@
stub_request(:post, "#{client.endpoint}/channels/foo/publish").
with(headers: { 'Authorization' => "Bearer #{encode64(token_id)}" }).
to_return(status: 201, body: '{}', headers: { 'Content-Type' => 'application/json' })
end
- it "will create a token request" do
- client.channel("foo").publish("event", "data")
+ it 'will create a token request' do
+ client.channel('foo').publish('event', 'data')
expect(request_token_stub).to have_been_requested
end
end
- context "will create a token" do
+ context 'will create a token' do
let(:token) { client.auth.current_token }
- it "before a request is made" do
+ it 'before a request is made' do
expect(token).to be_nil
end
- it "when a message is published" do
- expect(client.channel("foo").publish("event", "data")).to be_truthy
+ it 'when a message is published' do
+ expect(client.channel('foo').publish('event', 'data')).to be_truthy
end
- it "with capability and TTL defaults" do
- client.channel("foo").publish("event", "data")
+ it 'with capability and TTL defaults' do
+ client.channel('foo').publish('event', 'data')
expect(token).to be_a(Ably::Models::Token)
capability_with_str_key = Ably::Models::Token::DEFAULTS[:capability]
capability = Hash[capability_with_str_key.keys.map(&:to_sym).zip(capability_with_str_key.values)]
expect(token.capability).to eq(capability)