Created
July 15, 2020 14:47
-
-
Save lucashour/c8442ca35b1e8b422390afb7851035c0 to your computer and use it in GitHub Desktop.
Integrando una API en Rails
This file contains hidden or 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
gem 'faraday' | |
gem 'faraday_middleware' | |
group :test do | |
gem 'rspec-rails' | |
gem 'webmock' | |
end |
This file contains hidden or 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
# app/services/external/holidays_fetcher.rb | |
class External::HolidaysFetcher | |
URL = 'http://nolaborables.com.ar'.freeze | |
def initialize | |
@connection = Faraday.new(url: URL) do |faraday| | |
faraday.request :url_encoded | |
faraday.response :json, content_type: 'application/json' | |
faraday.adapter Faraday.default_adapter | |
end | |
end | |
def call(year: Date.current.year, with_optional: true) | |
parameters = with_optional ? {incluir: :opcional} : {} | |
response = @connection.get("/api/v2/feriados/#{year}", parameters) | |
return false unless response.success? | |
build_holidays(response) | |
end | |
private | |
def build_holidays(response) | |
response.body.map do |holiday| | |
External::Holiday.new(holiday) | |
end | |
end | |
end |
This file contains hidden or 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
# spec/services/external/holidays_fetcher_spec.rb | |
require 'rails_helper' | |
require 'mocks/holidays_mock' | |
describe External::HolidaysFetcher do | |
subject(:fetcher) { described_class.new } | |
describe '#call' do | |
shared_examples 'External::Holiday builder' do | |
it 'returns External::Holiday records' do | |
holidays = subject | |
expect(holidays).not_to be_empty | |
holidays.each do |holiday| | |
expect(holiday).to be_an_instance_of(External::Holiday) | |
end | |
end | |
end | |
shared_examples 'Optional External::Holiday builder' do | |
it 'builds optional External::Holiday' do | |
expect(subject.any?(&:optional?)).to be true | |
end | |
end | |
shared_examples 'HTTP connection to external API' do | |
it 'makes an HTTP request to the external API' do | |
subject | |
expect(api_mock).to have_been_requested | |
end | |
end | |
shared_examples 'Current year holidays fetcher' do | |
it 'uses current year as part of the URI' do | |
subject | |
uri_regex = /nolaborables\.com\.ar\/api\/v2\/feriados\/#{Date.current.year}/ | |
expect(WebMock.stub_request(:get, uri_regex)) | |
.to have_been_requested | |
end | |
end | |
context "when 'with_optional' argument is not received" do | |
let!(:api_mock) { HolidaysMock.mock(:all) } | |
subject { fetcher.call } | |
it_behaves_like 'External::Holiday builder' | |
it_behaves_like 'Optional External::Holiday builder' | |
it_behaves_like 'HTTP connection to external API' | |
it_behaves_like 'Current year holidays fetcher' | |
end | |
context "when 'year' argument is received" do | |
let(:year) { Date.current.year - 1 } | |
let!(:api_mock) do | |
HolidaysMock.mock( | |
:all, | |
/nolaborables\.com\.ar\/api\/v2\/feriados\/#{year}/ | |
) | |
end | |
subject { fetcher.call(year: year) } | |
it_behaves_like 'External::Holiday builder' | |
it_behaves_like 'Optional External::Holiday builder' | |
it_behaves_like 'HTTP connection to external API' | |
end | |
context 'when requesting holidays with optional ones' do | |
let!(:api_mock) { HolidaysMock.mock(:all) } | |
subject { fetcher.call(with_optional: true) } | |
it_behaves_like 'External::Holiday builder' | |
it_behaves_like 'Optional External::Holiday builder' | |
it_behaves_like 'HTTP connection to external API' | |
it_behaves_like 'Current year holidays fetcher' | |
end | |
context 'when requesting holidays without optional ones' do | |
let!(:api_mock) { HolidaysMock.mock(:all_except_optional) } | |
subject { fetcher.call(with_optional: false) } | |
it_behaves_like 'External::Holiday builder' | |
it_behaves_like 'HTTP connection to external API' | |
it_behaves_like 'Current year holidays fetcher' | |
it 'does not build any optional External::Holiday' do | |
expect(subject.any?(&:optional?)).to be false | |
end | |
end | |
context 'when there is a connection error' do | |
let!(:api_mock) { HolidaysMock.mock(:connection_error) } | |
subject { fetcher.call } | |
it { is_expected.to be false } | |
end | |
end | |
end |
This file contains hidden or 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
# spec/mocks/holidays_mock.rb | |
require 'webmock' | |
class HolidaysMock | |
include WebMock::API | |
URI = /nolaborables\.com\.ar\/api\/v2\/feriados\/\d{4}/.freeze | |
URI_WITHOUT_OPTIONAL = /nolaborables\.com\.ar\/api\/v2\/feriados\/\d{4}$/.freeze | |
URI_WITH_OPTIONAL = /nolaborables\.com\.ar\/api\/v2\/feriados\/\d{4}\?incluir=opcional$/.freeze | |
def self.mock(method, *args) | |
mock_object.send(method, *args) | |
end | |
def all(uri = nil) | |
stub_holidays( | |
uri || URI_WITH_OPTIONAL, | |
File.read('spec/mocks/data/holidays_with_optional.json') | |
) | |
end | |
def all_except_optional | |
stub_holidays( | |
URI_WITHOUT_OPTIONAL, | |
File.read('spec/mocks/data/holidays_without_optional.json') | |
) | |
end | |
def connection_error | |
stub_request(:get, URI).to_return( | |
body: '{"error": "Error de conexión"}', | |
status: 500, | |
headers: {'Content-Type' => 'application/json'} | |
) | |
end | |
class << self | |
private | |
def mock_object | |
@mock_object ||= HolidaysMock.new | |
end | |
end | |
private | |
def stub_holidays(uri, response) | |
stub_request(:get, uri) | |
.to_return( | |
body: response, | |
status: 200, | |
headers: {'Content-Type' => 'application/json'} | |
) | |
end | |
end |
This file contains hidden or 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
# spec/spec_helper.rb | |
require 'webmock/rspec' | |
RSpec.configure do |config| | |
# ... | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment