Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add support for Faraday and refactored/beautified the code #147

Open
wants to merge 16 commits into
base: master
Choose a base branch
from
Open
2 changes: 2 additions & 0 deletions airborne.gemspec
Original file line number Diff line number Diff line change
Expand Up @@ -15,5 +15,7 @@ Gem::Specification.new do |s|
s.add_runtime_dependency 'rack-test', '~> 0.6', '>= 0.6.2'
s.add_runtime_dependency 'rack'
s.add_runtime_dependency 'activesupport'
s.add_runtime_dependency 'faraday', '~> 0.13'
s.add_development_dependency 'webmock', '~> 0'
s.add_development_dependency 'pry'
end
36 changes: 19 additions & 17 deletions lib/airborne.rb
Original file line number Diff line number Diff line change
@@ -1,27 +1,29 @@
require 'airborne/rspec_settings'
require 'airborne/optional_hash_type_expectations'
require 'airborne/path_matcher'
require 'airborne/request_expectations'
require 'airborne/rest_client_requester'
require 'airborne/rack_test_requester'
require 'airborne/faraday_requester'
require 'airborne/base'

RSpec.configure do |config|
config.add_setting :base_url
config.add_setting :match_expected
config.add_setting :match_actual
config.add_setting :match_expected_default, default: true
config.add_setting :match_actual_default, default: false
config.add_setting :headers
config.add_setting :rack_app
config.add_setting :requester_type
config.add_setting :requester_module
config.before do |example|
config.match_expected = example.metadata[:match_expected].nil? ?
Airborne.configuration.match_expected_default? : example.metadata[:match_expected]
config.match_actual = example.metadata[:match_actual].nil? ?
Airborne.configuration.match_actual_default? : example.metadata[:match_actual]

module Airborne
class << self
def configuration
RSpec.configuration
end

def configure
RSpec.configure do |config|
yield config
end
end
end
end

# Include last since it depends on the configuration already being added
config.include Airborne
Airborne.configure do |config|
config.include Airborne::Base
config.filter_run_when_matching :focus
config.order = :random
end
118 changes: 59 additions & 59 deletions lib/airborne/base.rb
Original file line number Diff line number Diff line change
@@ -1,82 +1,82 @@
require 'json'
require 'active_support'
require 'active_support/core_ext/hash/indifferent_access'
require 'base64'

module Airborne
class InvalidJsonError < StandardError; end

include RequestExpectations

attr_reader :response, :headers, :body

def self.configure
RSpec.configure do |config|
yield config
module Base
class InvalidJsonError < StandardError; end

include RequestExpectations

attr_reader :response, :headers, :body

def self.included(base)
if Airborne.configuration.use_faraday
base.send(:include, Airborne::FaradayRequester)
elsif Airborne.configuration.requester_module
base.send(:include, Airborne.configuration.requester_module)
elsif Airborne.configuration.rack_app
base.send(:include, RackTestRequester)
else
base.send(:include, RestClientRequester)
end
end
end

def self.included(base)
if !Airborne.configuration.requester_module.nil?
base.send(:include, Airborne.configuration.requester_module)
elsif !Airborne.configuration.rack_app.nil?
base.send(:include, RackTestRequester)
else
base.send(:include, RestClientRequester)
def get(path, body = nil, headers = nil, &block)
@response = make_request(:get, path, body, headers, &block)
end
end

def self.configuration
RSpec.configuration
end

def get(url, headers = nil)
@response = make_request(:get, url, headers: headers)
end
def post(path, post_body = nil, headers = nil, &block)
@response = make_request(:post, path, post_body, headers, &block)
end

def post(url, post_body = nil, headers = nil)
@response = make_request(:post, url, body: post_body, headers: headers)
end
def patch(path, patch_body = nil, headers = nil, &block)
@response = make_request(:patch, path, patch_body, headers, &block)
end

def patch(url, patch_body = nil, headers = nil)
@response = make_request(:patch, url, body: patch_body, headers: headers)
end
def put(path, put_body = nil, headers = nil, &block)
@response = make_request(:put, path, put_body, headers, &block)
end

def put(url, put_body = nil, headers = nil)
@response = make_request(:put, url, body: put_body, headers: headers)
end
def delete(path, delete_body = nil, headers = nil, &block)
@response = make_request(:delete, path, delete_body, headers, &block)
end

def delete(url, delete_body = nil, headers = nil)
@response = make_request(:delete, url, body: delete_body, headers: headers)
end
def head(path, body = nil, headers = nil, &block)
@response = make_request(:head, path, body, headers, &block)
end

def head(url, headers = nil)
@response = make_request(:head, url, headers: headers)
end
def options(path, body = nil, headers = nil, &block)
@response = make_request(:options, path, body, headers, &block)
end

def options(url, headers = nil)
@response = make_request(:options, url, headers: headers)
end
def response
@response
end

def response
@response
end
def headers
HashWithIndifferentAccess.new(response.headers)
end

def headers
HashWithIndifferentAccess.new(response.headers)
end
def basic_auth(login, pass)
val = Base64.encode64([login, pass].join(':')).gsub!("\n", '')
"Basic #{val}"
end

def body
response.body
end
def body
response.body
end

def json_body
JSON.parse(response.body, symbolize_names: true) rescue fail InvalidJsonError, 'Api request returned invalid json'
end
def json_body
JSON.parse(response.body, symbolize_names: true) rescue fail InvalidJsonError, 'Api request returned invalid json'
end

private
private

def get_url(url)
base = Airborne.configuration.base_url || ''
base + url
def get_url(url)
base = Airborne.configuration.base_url || ''
base + url
end
end
end
35 changes: 35 additions & 0 deletions lib/airborne/faraday_requester.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
require 'faraday'

module Airborne
module FaradayRequester
def conn
@conn ||= Faraday.new do |c|
c.request :url_encoded
c.adapter Faraday.default_adapter
end
end

def make_request(method_name, path, body = {}, headers ={}, &block)
conn.send(method_name, path, body) do |req|
conn.url_prefix = base_url
req.path = path
req.headers.merge!(headers)
yield req, conn if block_given?
req.headers.merge!(conn.headers)
end
end

private
def base_url
Airborne.configuration.base_url
end
end
end

module FaradayResponse
def code
status
end
end

Faraday::Response.send(:include, FaradayResponse)
8 changes: 3 additions & 5 deletions lib/airborne/rack_test_requester.rb
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,11 @@

module Airborne
module RackTestRequester
def make_request(method, url, options = {})
headers = options[:headers] || {}
base_headers = Airborne.configuration.headers || {}
headers = base_headers.merge(headers)
def make_request(method, url, body = {}, headers = {}, &block)
headers = (Airborne.configuration.headers || {}).merge(headers || {})
browser = Rack::Test::Session.new(Rack::MockSession.new(Airborne.configuration.rack_app))
headers.each { |name, value| browser.header(name, value) }
browser.send(method, url, options[:body] || {}, headers)
browser.send(method, url, body || {}, headers)
Rack::MockResponse.class_eval do
alias_method :code, :status
end
Expand Down
8 changes: 4 additions & 4 deletions lib/airborne/rest_client_requester.rb
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,12 @@

module Airborne
module RestClientRequester
def make_request(method, url, options = {})
headers = base_headers.merge(options[:headers] || {})
def make_request(method, url, body, headers, &block)
headers = base_headers.merge(headers || {})
res = if method == :post || method == :patch || method == :put
begin
request_body = options[:body].nil? ? '' : options[:body]
request_body = request_body.to_json if options[:body].is_a?(Hash)
request_body = body || ''
request_body = request_body.to_json if request_body.is_a?(Hash)
RestClient.send(method, get_url(url), request_body, headers)
rescue RestClient::Exception => e
e.response
Expand Down
22 changes: 22 additions & 0 deletions lib/airborne/rspec_settings.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
RSpec.configure do |config|
config.add_setting :base_url
config.add_setting :match_expected_default, default: true
config.add_setting :match_actual_default, default: false
config.add_setting :match_expected, default: config.match_expected_default
config.add_setting :match_actual, default: config.match_actual_default
config.add_setting :headers
config.add_setting :rack_app
config.add_setting :requester_type
config.add_setting :requester_module
config.add_setting :use_faraday, default: true
config.around(:example, match_expected: !config.match_expected_default) do |example|
config.match_expected = !config.match_expected_default
example.run
config.match_expected = config.match_expected_default
end
config.around(:example, match_actual: !config.match_actual_default) do |example|
config.match_actual = !config.match_actual_default
example.run
config.match_actual = config.match_actual_default
end
end
62 changes: 62 additions & 0 deletions spec/airborne/base_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -52,4 +52,66 @@
post '/simple_post', {}
expect(json_body).to_not be(nil)
end

context 'when using faraday instead of RestClient' do
before do
Airborne.configure do |c|
c.use_faraday = true
end
end

context 'when sucessful request is made' do

before { mock_get('simple_get') }

it 'response should be set' do
get '/simple_get'
expect(response).to_not be(nil)
end

it 'headers should be set' do
get '/simple_get'
expect(headers).to_not be(nil)
end

it 'headers should be hash with indifferent access' do
mock_get('simple_get', 'Content-Type' => 'application/json')
get '/simple_get'
expect(headers).to be_kind_of(Hash)
expect(headers[:content_type]).to eq('application/json')
expect(headers['content_type']).to eq('application/json')
end

it 'body should be set' do
get '/simple_get'
expect(body).to_not be(nil)
end

it 'json body should be symbolized hash' do
get '/simple_get'
expect(json_body).to be_kind_of(Hash)
expect(json_body.first[0]).to be_kind_of(Symbol)
end
end

it 'should throw an InvalidJsonError when accessing json_body on invalid json' do
mock_get('invalid_json')
get '/invalid_json'
expect(body).to eq('invalid1234')
expect { json_body }.to raise_error(InvalidJsonError)
end

it 'should handle a 500 error on get' do
mock_get('simple_get', {}, [500, 'Internal Server Error'])
get '/simple_get'
expect(json_body).to_not be(nil)
end

it 'should handle a 500 error on post' do
mock_post('simple_post', {}, [500, 'Internal Server Error'])
post '/simple_post', {}
expect(json_body).to_not be(nil)
end

end
end
4 changes: 1 addition & 3 deletions spec/airborne/client_requester_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,9 @@
describe 'client requester' do
before do
allow(RestClient).to receive(:send)
RSpec::Mocks.space.proxy_for(self).remove_stub_if_present(:get)
end

after do
allow(RestClient).to receive(:send).and_call_original
Airborne.configure { |config| config.headers = {} }
end

Expand All @@ -19,7 +17,7 @@
end

it 'should override headers with option[:headers]' do
get '/foo', { content_type: 'application/x-www-form-urlencoded' }
get '/foo', {} ,{ content_type: 'application/x-www-form-urlencoded' }

expect(RestClient).to have_received(:send)
.with(:get, 'http://www.example.com/foo', { content_type: 'application/x-www-form-urlencoded' })
Expand Down
Loading