Last active
July 8, 2020 20:43
-
-
Save dudo/c3dae539d7d803b620b69dc16c36e1b3 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
RSpec.describe Api::ClientBase do | |
subject(:api) { described_class.new(config) } | |
let(:scheme) { 'https' } | |
let(:host) { Faker::Internet.domain_name } | |
let(:port) { 3000 } | |
let(:config) do | |
{ | |
'scheme' => scheme, | |
'host' => host, | |
'port' => port | |
} | |
end | |
describe '.new' do | |
it { expect(api.path).to eq '/' } | |
it { expect(api.request_method).to eq :get } | |
context 'when no host is provided' do | |
let(:host) { nil } | |
it { expect { api }.to raise_error(ArgumentError, '`host` must be provided within configuration') } | |
end | |
end | |
describe '#call!' do | |
let(:body) { {} } | |
let(:response) { OpenStruct.new(code: code, body: body.to_json) } | |
before { allow(api).to receive(:response).and_return(response) } | |
context 'when 2xx' do | |
let(:code) { [*200..299].sample } | |
before { api.call! } | |
it { expect(api.call!).to eq response } | |
it { expect(api.response).to eq response } | |
it { expect(api.response_body).to eq({}) } | |
context 'when body is present' do | |
let(:body) { { 'foo' => 'bar' } } | |
it { expect(api.response_body).to eq(body) } | |
end | |
end | |
context 'when NOT 2xx' do | |
let(:code) { [*300..599].sample } | |
it { expect { api.call! }.to raise_error(RuntimeError, "Received non-2xx status: #{code}") } | |
end | |
end | |
describe '#base_uri' do | |
it { expect(api.base_uri).to eq "#{scheme}://#{host}:#{port}" } | |
context 'when no scheme is provided' do | |
let(:scheme) { nil } | |
it { expect(api.base_uri).to eq "http://#{host}:#{port}" } | |
end | |
context 'when no port is provided' do | |
let(:port) { nil } | |
it { expect(api.base_uri).to eq "#{scheme}://#{host}" } | |
end | |
end | |
describe '#uri' do | |
it { expect(api.uri.to_s).to eq "#{api.base_uri}/" } | |
end | |
describe '#headers' do | |
it { expect(api.headers).to eq({}) } | |
end | |
describe '#body' do | |
it { expect(api.body).to eq({}) } | |
end | |
describe '#query' do | |
it { expect(api.query).to eq({}) } | |
end | |
describe '#options' do | |
it { expect(api.options).to eq({}) } | |
end | |
describe '#response' do | |
before do | |
stub_request(:get, "#{scheme}://#{host}:#{port}").to_return(status: 200, body: '') | |
end | |
it { expect(api.response).to be_kind_of HTTParty::Response } | |
end | |
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# frozen_string_literal: true | |
# frozen_string_literal: true | |
module Api | |
class ClientBase | |
include HTTParty | |
attr_reader :config, :path, :request_method | |
def initialize(config) | |
@config = config | |
@path ||= '/' | |
@request_method ||= :get | |
raise ArgumentError, '`host` must be provided within configuration' if config['host'].blank? | |
end | |
def call! | |
# This will typically be overridden in the subclass to act on the response | |
case response.code.to_i | |
when 200..299 | |
response | |
else | |
raise "Received non-2xx status: #{response.code}" | |
end | |
end | |
def base_uri | |
@base_uri ||= [scheme, '://', host].join | |
end | |
def uri | |
URI(base_uri).tap do |uri| | |
uri.path = path | |
end | |
end | |
def headers | |
{} | |
end | |
def body | |
{} | |
end | |
def query | |
{} | |
end | |
def options | |
{} | |
end | |
def response | |
@response ||= self.class.send( | |
request_method, | |
uri, | |
headers: headers, | |
body: body, | |
query: query, | |
**options | |
) | |
end | |
def response_body | |
@response_body ||= response.body.blank? ? {} : JSON.parse(response.body).with_indifferent_access | |
end | |
private | |
def scheme | |
@scheme ||= config['scheme'] || 'http' | |
end | |
def host | |
@host ||= [config['host'], config['port']].compact.join(':') | |
end | |
end | |
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
module Api | |
module Example | |
class Base < ClientBase | |
def initialize | |
super(Rails.application.config_for(:example)) | |
end | |
def headers | |
{ | |
Authorization: "Bearer #{auth_token}", | |
content_type: 'application/json' | |
} | |
end | |
end | |
end | |
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
module Api | |
module Example | |
module Things | |
class Fetch < Base | |
def initialize(id:) | |
@path = "/v1/things/#{id}" | |
super() | |
end | |
end | |
end | |
end | |
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
default: &default | |
scheme: https | |
host: sandbox.example.com | |
port: 9443 | |
development: &development | |
<<: *default | |
test: | |
<<: *development | |
production: | |
host: api.example.com | |
port: 10443 |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment