Skip to content

Instantly share code, notes, and snippets.

@pmashchak
Last active May 4, 2016 00:13
Show Gist options
  • Save pmashchak/751f6cf4c5b3b7bbc1b3e84caff77007 to your computer and use it in GitHub Desktop.
Save pmashchak/751f6cf4c5b3b7bbc1b3e84caff77007 to your computer and use it in GitHub Desktop.
HTTP request wapper test + DynamoDB data class
require 'rails_helper'
describe HTTPRequest do
let(:logger) { ->(params) { } }
let(:api_context) { ParentalControls.new('', '', logger: logger) }
let(:subject) { HTTPRequest.new(api_context: api_context, headers: { 'Accept' => 'application/xml' }) }
let(:response) { double(:response, code: 200, body: {}.to_json) }
before do
allow_any_instance_of(ParentalControls).to receive(:get).and_return({})
allow_any_instance_of(Manticore::Client).to receive(:get).and_return(response)
end
context 'Set defaults' do
let(:api_options) { Rails.configuration.api.send(ParentalControls.api_name) }
it 'raises error if api is blank' do
expect { HTTPRequest.new() }.to raise_error('API not found')
end
it 'sets default options' do
options = subject.options
expect(options[:request_timeout]).to eql(5)
expect(options[:connect_timeout]).to eql(5)
expect(options[:socket_timeout]).to eql(5)
expect(options[:headers]).to eql('Accept' => 'application/xml')
end
it 'sets default api_options' do
expect(subject.api_config_get(:codebig_key)).to eql(api_options[:codebig_key])
expect(subject.api_config_get(:codebig_secret)).to eql(api_options[:codebig_secret])
expect(subject.api_config_get(:base)).to eql(api_options[:base])
expect(subject.api_config_get(:timeout)).to eql(api_options[:timeout])
end
end
context '.get' do
let(:oauth) { { consumer_key: subject.api_config_get(:codebig_key),
consumer_secret: subject.api_config_get(:codebig_secret)} }
let(:oauth_header) { SimpleOAuth::Header.new(:get, subject.endpoint, {}, oauth).to_s }
it 'should do get request' do
expect(subject).to receive(:request).with(:get, {})
subject.get({})
end
it 'should set oauth header' do
allow_any_instance_of(SimpleOAuth::Header).to receive(:to_s).and_return(oauth_header)
subject.get
headers = subject.options[:headers]
expect(headers['Accept']).to eql('application/json')
expect(headers['Content-Type']).to eql('application/json')
expect(headers['Authorization']).to eql(oauth_header)
end
it 'should not set oauth header if key and secret blank' do
api_config = subject.api_context.api_config.clone
api_config[:codebig_key] = nil
allow(subject.api_context).to receive(:api_config).and_return(api_config)
subject.get
headers = subject.options[:headers]
expect(headers['Authorization']).to be_blank
end
end
context '.post' do
let(:params) { { user_name: 'John' } }
before do
allow_any_instance_of(Manticore::Client).to receive(:post).and_return(response)
end
it 'should do post request' do
expect(subject).to receive(:request).with(:post, {})
subject.post({})
end
it 'should post body params' do
expect(subject.post(body: params)).to eql({})
expect(subject.options[:body]).to eql(params)
end
end
context 'Fails on Exception' do
it 'fails on default exception' do
expect(subject.client).to receive(:get).exactly(3).times.and_raise(Manticore::Timeout)
expect(logger).to receive(:call).exactly(2).times
expect { subject.get }.to raise_error(Manticore::Timeout)
end
it 'fails on custom exception' do
subject = HTTPRequest.new(api_context: api_context, exceptions: [RuntimeError])
expect(subject.client).to receive(:get).exactly(3).times.and_raise(RuntimeError)
expect(logger).to receive(:call).exactly(2).times
expect { subject.get }.to raise_error(RuntimeError)
expect(subject.exceptions).to include(RuntimeError)
expect(subject.exceptions).to include(Manticore::Timeout)
end
it 'should retry number of times' do
expect(subject.client).to receive(:post).exactly(2).times.and_raise(Manticore::Timeout)
expect(logger).to receive(:call).exactly(1).times
expect { subject.post({ retries: 1 }) }.to raise_error(Manticore::Timeout)
end
end
context 'Fails on code' do
let(:response) { double(:response, code: 422, body: {}.to_json) }
it 'fails on 422 code' do
expect(subject.client).to receive(:get).exactly(3).times.and_raise(Manticore::ResponseCodeException)
expect(logger).to receive(:call).exactly(2).times
expect { subject.get }.to raise_error(Manticore::ResponseCodeException)
end
it 'should not retry on 422 code' do
expect(subject.get(fails_on_code: false)).to eql({})
end
it 'should raise exception on code' do
expect { subject.get }.to raise_error(Manticore::ResponseCodeException)
end
end
end
require 'rails_helper'
describe Pair do
let(:client) { double(:client) }
let(:ip_lease_expires) { 5.seconds.from_now.to_i * 1000 }
let(:timestamp) { 5.seconds.from_now.to_i * 1000 }
let(:item) { double(:item, item: { "id"=>"4453964", "bucket"=>"3",
"data"=>"{ \"925820377533335645\": { \"appId\":\"tvxapps.games.dev\",
\"deviceId\":\"925820377533335645\", \"comcastSessionId\":\"6fd28a49-7748-4a19-9651-9cd7b8ab897c\",
\"billingAccountId\":\"8499101410225087\", \"xboAccountId\":\"7866179556106550654\",
\"zip3\":\"191\", \"ipLeaseExpires\":\"#{ip_lease_expires}\", \"cstAuthGuid\":\"109056040722102015Comcast.RTVE\",
\"stbFriendlyName\":\"DEV2 XG2V2\", \"gameId\":\"monopoly\",\"whitelisted\":false,\"hsi\":true,
\"timestamp\": \"#{timestamp}\" } }" }) }
let(:parsed_item) { JSON.parse(item.item['data']).values.first.merge(item.item.slice('id')) }
let(:no_item) { double(:item, item: nil) }
let(:logger) { ->(params) { params[:retried]; params[:trace]} }
let(:items) { double(:items, items: [item.item]) }
let(:no_items) { double(:items, items: []) }
subject { Pair.new(parsed_item) }
before do
allow(Pair).to receive(:client).and_return(client)
allow(subject).to receive(:client).and_return(client)
end
context '#delete' do
it 'should delete item' do
expect(client).to receive(:delete_item).with(table_name: Pair::TABLE_NAME, key: { 'id' => subject.id })
subject.delete
end
end
context '.new' do
it 'should parse data item' do
expect(subject).to be_a(Pair)
expect(subject).to_not be_expired
expect(subject.id).to eq('4453964')
expect(subject.device_id).to eq('925820377533335645')
expect(subject.app_id).to eq('tvxapps.games.dev')
expect(subject.comcast_session_id).to eq('6fd28a49-7748-4a19-9651-9cd7b8ab897c')
expect(subject.account_number).to eq('8499101410225087')
expect(subject.auth_guid).to eq('109056040722102015Comcast.RTVE')
expect(subject.xbo_account_id).to eq('7866179556106550654')
expect(subject.zip3).to eq('191')
expect(subject.stb_friendly_name).to eq('DEV2 XG2V2')
expect(subject.ip_lease_expires).to eq(ip_lease_expires.to_s)
expect(subject.game_id).to eq('monopoly')
expect(subject.whitelisted).to eq(false)
expect(subject.hsi).to eq(true)
expect(subject.timestamp).to eq(timestamp.to_s)
expect(subject).to_not be_collection
expect(subject.to_json).to eq("{\"device_id\":\"925820377533335645\",\"stb_friendly_name\":\"DEV2 XG2V2\"}")
end
it 'should not parse data item' do
subject = Pair.new('id'=>'4453964')
expect(subject).to_not be_valid
end
end
context '.where' do
let(:collection) { Pair.where(ip_address: item.item['id']) }
it 'should find item by ip' do
expect(client).to receive(:get_item).with(table_name: Pair::TABLE_NAME, key: { 'id' => item.item['id'] }).and_return(item)
expect(collection).to be_a(Pair::Collection)
expect(collection).to be_valid
expect(collection.to_json).to eq("[{\"device_id\":\"925820377533335645\",\"stb_friendly_name\":\"DEV2 XG2V2\"}]")
expect(subject).to be_valid
expect(collection.item.id).to eq(subject.id)
expect(collection).to be_can_pair_device
end
it 'should return nil' do
expect(client).to receive(:get_item).with(table_name: Pair::TABLE_NAME, key: { 'id' => item.item['id'] }).and_return(no_item)
expect(collection).to be_a(Pair::Collection)
expect(collection).to be_blank
expect(collection).to_not be_valid
expect(collection).to_not be_collection
end
it 'should retry and return item' do
expect(client).to receive(:get_item).and_raise(Timeout::Error).once
expect(logger).to receive(:call).with(retried: 1, trace: Timeout::Error.new.inspect).once
expect(client).to receive(:get_item).and_return(item).once
collection = Pair.where(ip_address: item.item['id'], logger: logger)
expect(collection).to be_a(Pair::Collection)
expect(collection).to be_valid
end
it 'should retry and raise error' do
expect(client).to receive(:get_item).and_raise(Timeout::Error).twice
expect(logger).to receive(:call).with(retried: 1, trace: Timeout::Error.new.inspect).once
expect { Pair.where(ip_address: item.item['id'], logger: logger) }.to raise_error(Timeout::Error)
end
it 'should detect device' do
expect(client).to receive(:get_item).and_return(item)
pair = collection.detect_device('925820377533335645')
expect(pair).to be_a(Pair)
expect(pair).to be_valid
expect(pair).to be_can_pair_device
end
context 'timestamp expires' do
let(:timestamp) { 5.minutes.ago.to_i * 1000 }
it 'should expire if timestamp is expired' do
expect(client).to receive(:get_item).and_return(item)
subject = Pair.where(ip_address: item.item['id'])
expect(subject).to_not be_valid
expect(subject).to be_blank
end
end
context 'ip_lease_expires' do
let(:ip_lease_expires) { 5.seconds.ago.to_i * 1000 }
it 'should be expired' do
expect(client).to receive(:get_item).and_return(item)
subject = Pair.where(ip_address: item.item['id'])
expect(subject).to_not be_valid
expect(subject).to be_blank
end
end
end
context '.find_by_pairing_code' do
before do
expect(client).to receive(:get_item).with(table_name: Pair::TABLE_NAME, key: { 'id' => item.item['id'] }).and_return(item)
end
it 'should find by pairing code' do
subject = Pair.find_by_pairing_code(item.item['id'])
expect(subject).to be_a(Pair)
expect(subject).to be_valid
end
it 'should return nil' do
expect(JSON).to receive(:parse).and_raise(JSON::ParserError)
expect(Rails.logger).to receive(:error)
subject = Pair.find_by_pairing_code(item.item['id'])
expect(subject).to be(nil)
end
context 'timestamp' do
let(:timestamp) { 5.minutes.ago.to_i * 1000 }
it 'should be expired' do
subject = Pair.find_by_pairing_code(item.item['id'])
expect(subject).to_not be_valid
expect(subject.errors[:base]).to be_present
expect(subject.conditions).to_not include(:ip_address)
expect(subject.conditions).to include(:pairing_code)
end
end
end
context '.all' do
let(:bulk_items) { double(:bulk_items, items: [item.item], last_evaluated_key: { 'id' => '1' }) }
it 'should find all records' do
expect(client).to receive(:scan).with(table_name: Pair::TABLE_NAME).and_return(items)
subject = Pair.all.first
expect(subject).to be_a(Pair)
expect(subject).to be_valid
end
it 'should return blank array' do
expect(client).to receive(:scan).with(table_name: Pair::TABLE_NAME).and_return(no_items)
items = Pair.all
expect(items).to be_blank
end
it 'should eager load all records' do
expect(client).to receive(:scan).with(table_name: Pair::TABLE_NAME).and_return(bulk_items)
expect(client).to receive(:scan).with(table_name: Pair::TABLE_NAME, exclusive_start_key: { id: '1' }).and_return(items)
expect(items).to receive(:last_evaluated_key).and_return(nil)
expect(Pair.all(true).count).to eq(2)
end
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment