diff --git a/Gemfile b/Gemfile index 08c09bf..b4e2a20 100644 --- a/Gemfile +++ b/Gemfile @@ -1,17 +1,3 @@ source "https://rubygems.org" -gem 'rake', '~> 11.1', '>= 11.1.2' - -group :test do - gem 'rspec' - gem 'simplecov', :require => false - gem "codeclimate-test-reporter", :require => false - gem 'coveralls', :require => false - gem 'scrutinizer-ocular', :require => false -end - -group :docs do - gem 'yard', :git => 'https://github.com/trevorrowe/yard.git', branch: 'frameless' - gem 'yard-sitemap', '~> 1.0' - gem 'rdiscount' -end +gemspec diff --git a/README.md b/README.md index 43e1471..ea4632d 100644 --- a/README.md +++ b/README.md @@ -64,6 +64,27 @@ response = wepay.call('/account/create', access_token, { }) ``` +## Configuration + +WePay can be configured in a block: + +ruby +``` +WePay.configure do |config| + # Switch Faraday web adapter (default Net::HTTP) + config.http_adapter = :patron +end +``` + +You can also access the configuration object: + +ruby +``` +config = WePay.configuration + +config.http_adapter = :patron +``` + ## Testing Firstly, run `bundle install` to download and install the dependencies. @@ -74,6 +95,13 @@ You can run the tests as follows: make test ``` +## Console + +Start a REPL with the WePay library and dependencies loaded: + +``` +bin/console +``` ## API Reference diff --git a/bin/console b/bin/console new file mode 100755 index 0000000..acf2215 --- /dev/null +++ b/bin/console @@ -0,0 +1,4 @@ +#!/usr/bin/env ruby +require 'wepay' +require 'irb' +IRB.start diff --git a/lib/we_pay/base_request.rb b/lib/we_pay/base_request.rb index 555ed54..d2ea742 100644 --- a/lib/we_pay/base_request.rb +++ b/lib/we_pay/base_request.rb @@ -1,7 +1,6 @@ require 'json' -require 'net/http' -require 'net/https' require 'uri' +require 'faraday' module WePay module BaseRequest @@ -29,36 +28,31 @@ def response private def raw_response - @raw_response ||= client.start do |c| - c.request(request) - end - end + @raw_response ||= client.post do |r| + r.url(uri.path) - def request - @request ||= Net::HTTP::Post.new(uri.path, default_headers).tap do |r| if params.any? r.body = params.to_json end if access_token - r.add_field('Authorization', "Bearer #{access_token}") + r.headers['Authorization'] = "Bearer #{access_token}" end if api_version - r.add_field('Api-Version', @api_version) + r.headers['Api-Version'] = api_version end end end def client - @client ||= Net::HTTP.new(uri.host, uri.port).tap do |c| - c.read_timeout = 30 - c.use_ssl = true - end - end - - def uri - @uri ||= URI.join(api_endpoint, normalized_path) + @client ||= Faraday.new( + uri, + headers: default_headers, + request: default_request_opts, + ssl: default_ssl_opts, + adapter: http_adapter + ) end def normalized_path @@ -67,11 +61,31 @@ def normalized_path path.prepend('/') end + def uri + URI.parse(api_endpoint + normalized_path) + end + def default_headers { - 'Content-Type' => 'application/json', - 'User-Agent' => 'WePay Ruby SDK' + content_type: 'application/json', + user_agent: 'WePay Ruby SDK' } end + + def default_request_opts + { + timeout: 30 + } + end + + def default_ssl_opts + { + verify: true + } + end + + def http_adapter + WePay.configuration.http_adapter + end end end diff --git a/lib/we_pay/client.rb b/lib/we_pay/client.rb index 80da507..e4505ed 100644 --- a/lib/we_pay/client.rb +++ b/lib/we_pay/client.rb @@ -1,13 +1,4 @@ -## -# Copyright (c) 2012-2016 WePay. -# -# http://opensource.org/licenses/Apache2.0 -## - require 'cgi' -require 'json' -require 'net/http' -require 'net/https' module WePay diff --git a/lib/we_pay/configuration.rb b/lib/we_pay/configuration.rb new file mode 100644 index 0000000..3cdb62e --- /dev/null +++ b/lib/we_pay/configuration.rb @@ -0,0 +1,19 @@ +require 'singleton' + +module WePay + class Configuration + include ::Singleton + + attr_writer :http_adapter + + def http_adapter + @http_adapter || default_http_adapter + end + + private + + def default_http_adapter + :net_http + end + end +end diff --git a/lib/wepay.rb b/lib/wepay.rb index febb5c2..3dbcf2b 100644 --- a/lib/wepay.rb +++ b/lib/wepay.rb @@ -8,9 +8,21 @@ # The root WePay namespace. ## module WePay - autoload :Client, 'we_pay/client' + autoload :Configuration, 'we_pay/configuration' + autoload :Client, 'we_pay/client' autoload :BaseRequest, 'we_pay/base_request' autoload :TestRequest, 'we_pay/test_request' autoload :ProductionRequest, 'we_pay/production_request' + + class << self + + def configure(&block) + block.call(configuration) + end + + def configuration + WePay::Configuration.instance + end + end end diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb index eaf1e54..11082a8 100644 --- a/spec/spec_helper.rb +++ b/spec/spec_helper.rb @@ -12,7 +12,9 @@ SimpleCov::Formatter::HTMLFormatter, Coveralls::SimpleCov::Formatter ] -SimpleCov.start +SimpleCov.start do + add_filter "/spec/" +end require 'wepay' diff --git a/spec/we_pay/configuration_spec.rb b/spec/we_pay/configuration_spec.rb new file mode 100644 index 0000000..5df7d76 --- /dev/null +++ b/spec/we_pay/configuration_spec.rb @@ -0,0 +1,34 @@ +require 'spec_helper' + +RSpec.describe WePay::Configuration do + + subject { described_class.instance } + + describe "as a singleton" do + it "returns an instance" do + expect(described_class.instance).to be_an_instance_of(described_class) + end + end + + describe "#http_adapter" do + context "by default" do + it "returns Net Http" do + expect(subject.http_adapter).to eq(:net_http) + end + end + + context "with an explicit adapter" do + before do + subject.http_adapter = :patron + end + + after do + subject.http_adapter = nil + end + + it "returns the adapter" do + expect(subject.http_adapter).to eq(:patron) + end + end + end +end diff --git a/spec/we_pay/production_request_spec.rb b/spec/we_pay/production_request_spec.rb index 9723b7b..8de431c 100644 --- a/spec/we_pay/production_request_spec.rb +++ b/spec/we_pay/production_request_spec.rb @@ -3,9 +3,30 @@ RSpec.describe WePay::ProductionRequest do describe "#response" do - let(:http_response) { double("net::http::response") } - let(:http_post) { double("net::http::post") } - let(:http_client) { double("net::http") } + let(:client) { double("faraday::connection") } + let(:request) { double("faraday::request") } + let(:response) { double("faraday::response") } + + let(:header_opts) do + { + content_type: 'application/json', + user_agent: 'WePay Ruby SDK' + } + end + + let(:request_opts) do + { + timeout: 30 + } + end + + let(:ssl_opts) do + { + verify: true + } + end + + let(:default_http_adapter) { :net_http } subject do described_class.new( @@ -19,31 +40,25 @@ end before do - allow(http_response).to receive(:body).and_return({ response: 'response' }.to_json) - - allow(Net::HTTP::Post).to receive(:new).with( - "/path", - 'Content-Type' => 'application/json', - 'User-Agent' => 'WePay Ruby SDK' - ).and_return(http_post) - - allow(http_post).to receive(:body=).with({ data: 'data' }.to_json) - allow(http_post).to receive(:add_field).with('Authorization', "Bearer access_token") - allow(http_post).to receive(:add_field).with('Api-Version', "api_version") - - allow(Net::HTTP).to receive(:new).with( - "wepayapi.com", - 443 - ).and_return(http_client) - - allow(http_client).to receive(:read_timeout=).with(30) - allow(http_client).to receive(:use_ssl=).with(true) - allow(http_client).to receive(:request).with(http_post).and_return(http_response) - allow(http_client).to receive(:start).and_yield(http_client) + allow(Faraday).to receive(:new).with( + URI.parse("https://wepayapi.com/v2/path"), + headers: header_opts, + request: request_opts, + ssl: ssl_opts, + adapter: default_http_adapter + ).and_return(client) + + allow(client).to receive(:post).and_yield(request).and_return(response) + + allow(request).to receive(:url).with("/v2/path") + allow(request).to receive(:body=).with({data: 'data'}.to_json) + allow(request).to receive(:headers).and_return({}) + + expect(response).to receive(:body).and_return({ status: :ok}.to_json) end it "returns response data" do - expect(subject.response).to eq({ 'response' => 'response' }) + expect(subject.response).to eq('status' => 'ok') end end end diff --git a/spec/we_pay/test_request_spec.rb b/spec/we_pay/test_request_spec.rb index b9cd340..43593ae 100644 --- a/spec/we_pay/test_request_spec.rb +++ b/spec/we_pay/test_request_spec.rb @@ -3,9 +3,32 @@ RSpec.describe WePay::TestRequest do describe "#response" do - let(:http_response) { double("net::http::response") } - let(:http_post) { double("net::http::post") } - let(:http_client) { double("net::http") } + let(:client) { double("faraday::connection") } + let(:request) { double("faraday::request") } + let(:response) { double("faraday::response") } + + let(:stage_url) { "https://stage.wepayapi.com/v2" } + + let(:header_opts) do + { + content_type: 'application/json', + user_agent: 'WePay Ruby SDK' + } + end + + let(:request_opts) do + { + timeout: 30 + } + end + + let(:ssl_opts) do + { + verify: true + } + end + + let(:default_http_adapter) { :net_http } subject do described_class.new( @@ -19,31 +42,25 @@ end before do - allow(http_response).to receive(:body).and_return({ response: 'response' }.to_json) - - allow(Net::HTTP::Post).to receive(:new).with( - "/path", - 'Content-Type' => 'application/json', - 'User-Agent' => 'WePay Ruby SDK' - ).and_return(http_post) - - allow(http_post).to receive(:body=).with({ data: 'data' }.to_json) - allow(http_post).to receive(:add_field).with('Authorization', "Bearer access_token") - allow(http_post).to receive(:add_field).with('Api-Version', "api_version") - - allow(Net::HTTP).to receive(:new).with( - "stage.wepayapi.com", - 443 - ).and_return(http_client) - - allow(http_client).to receive(:read_timeout=).with(30) - allow(http_client).to receive(:use_ssl=).with(true) - allow(http_client).to receive(:request).with(http_post).and_return(http_response) - allow(http_client).to receive(:start).and_yield(http_client) + allow(Faraday).to receive(:new).with( + URI.parse("https://stage.wepayapi.com/v2/path"), + headers: header_opts, + request: request_opts, + ssl: ssl_opts, + adapter: default_http_adapter + ).and_return(client) + + allow(client).to receive(:post).and_yield(request).and_return(response) + + allow(request).to receive(:url).with("/v2/path") + allow(request).to receive(:body=).with({data: 'data'}.to_json) + allow(request).to receive(:headers).and_return({}) + + expect(response).to receive(:body).and_return({ status: :ok}.to_json) end it "returns response data" do - expect(subject.response).to eq({ 'response' => 'response' }) + expect(subject.response).to eq('status' => 'ok') end end end diff --git a/spec/we_pay_spec.rb b/spec/we_pay_spec.rb new file mode 100644 index 0000000..8cd99f7 --- /dev/null +++ b/spec/we_pay_spec.rb @@ -0,0 +1,28 @@ +require 'spec_helper' + +RSpec.describe WePay do + + describe ".configure" do + before do + WePay.configuration.http_adapter = :net_http + end + + after do + WePay.configuration.http_adapter = :net_http + end + + it "yields the configuration to the block" do + described_class.configure do |config| + config.http_adapter = :patron + end + + expect(described_class.configuration.http_adapter).to eq(:patron) + end + end + + describe ".configuration" do + it "returns the WePay configuration" do + expect(described_class.configuration).to be_an_instance_of(WePay::Configuration) + end + end +end diff --git a/wepay.gemspec b/wepay.gemspec index 933e8bc..e537fc3 100644 --- a/wepay.gemspec +++ b/wepay.gemspec @@ -1,14 +1,30 @@ Gem::Specification.new do |s| - s.name = 'wepay' - s.version = '0.3.0' - s.date = '2016-06-11' + s.name = "wepay" + s.version = "0.3.0" + s.authors = ["WePay"] + s.email = "api@wepay.com" + s.date = "2016-06-11" s.summary = "WePay SDK for Ruby" s.description = "The WePay SDK for Ruby lets you easily make WePay API calls from Ruby." - s.authors = ["WePay"] - s.email = 'api@wepay.com' - s.homepage = 'https://github.com/wepay/Ruby-SDK' - s.license = 'Apache-2.0' + s.homepage = "https://github.com/wepay/Ruby-SDK" + s.license = "Apache-2.0" s.files = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) } + s.test_files = Dir["spec/**/*"] + + s.add_dependency "faraday", ">= 0.9.0" + + s.add_development_dependency "bundler", "~> 1.12" + s.add_development_dependency "rake", "~> 10.0" + s.add_development_dependency "rspec", "~> 3.0" + + s.add_development_dependency "simplecov" + s.add_development_dependency "codeclimate-test-reporter" + s.add_development_dependency "coveralls" + s.add_development_dependency "scrutinizer-ocular" + + s.add_development_dependency "yard" + s.add_development_dependency "yard-sitemap" + s.add_development_dependency "rdiscount" end