shipping_easy 0.0.1 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.rspec +2 -0
- data/Rakefile +3 -0
- data/lib/shipping_easy.rb +39 -2
- data/lib/shipping_easy/configuration.rb +29 -0
- data/lib/shipping_easy/http.rb +2 -0
- data/lib/shipping_easy/http/faraday_adapter.rb +30 -0
- data/lib/shipping_easy/http/request.rb +51 -0
- data/lib/shipping_easy/http/response_handler.rb +27 -0
- data/lib/shipping_easy/resources.rb +2 -0
- data/lib/shipping_easy/resources/base.rb +16 -0
- data/lib/shipping_easy/resources/cancellation.rb +7 -0
- data/lib/shipping_easy/resources/order.rb +7 -0
- data/lib/shipping_easy/signature.rb +2 -1
- data/lib/shipping_easy/version.rb +1 -1
- data/shipping_easy.gemspec +4 -1
- data/spec/authenticator_spec.rb +76 -0
- data/spec/configuration_spec.rb +31 -0
- data/spec/http/faraday_adapter_spec.rb +42 -0
- data/spec/http/request_spec.rb +81 -0
- data/spec/http/response_handler_spec.rb +33 -0
- data/spec/resources/base_spec.rb +39 -0
- data/spec/signature_spec.rb +40 -0
- data/spec/spec_helper.rb +20 -0
- metadata +79 -14
- data/lib/shipping_easy/resources/cancellations.rb +0 -0
- data/lib/shipping_easy/resources/store.rb +0 -0
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: b51569e520e425f916ee5b73f0fcd9086ec23aa1
|
4
|
+
data.tar.gz: 5c9bf4c89f508e002327c37b3670fd3ac3fdd0b8
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 0d2f8ce7d601b671c76186ab78eebe8fc2ccc886abf7af13c2adcc3a5071f10a134ea4511db8749ba97854d196dc59547d31918da9ac389711ff2832744c20fe
|
7
|
+
data.tar.gz: e7c656651793f6fc67c5883e44b09e1d33397383ce5be7e87b7edc39fb65b129662846942363efc9311128b1b8651574ea6e1824c5667966d1433ef9078e28fe
|
data/.rspec
ADDED
data/Rakefile
CHANGED
data/lib/shipping_easy.rb
CHANGED
@@ -1,10 +1,47 @@
|
|
1
|
-
|
1
|
+
|
2
|
+
require "faraday"
|
3
|
+
require "rack"
|
4
|
+
require "json"
|
5
|
+
require "shipping_easy/authenticator"
|
6
|
+
require "shipping_easy/configuration"
|
7
|
+
require "shipping_easy/signature"
|
8
|
+
require "shipping_easy/http"
|
9
|
+
require "shipping_easy/http/faraday_adapter"
|
10
|
+
require "shipping_easy/http/request"
|
11
|
+
require "shipping_easy/http/response_handler"
|
12
|
+
require "shipping_easy/resources"
|
13
|
+
require "shipping_easy/resources/base"
|
14
|
+
require "shipping_easy/resources/order"
|
15
|
+
require "shipping_easy/resources/cancellation"
|
2
16
|
require "shipping_easy/version"
|
3
17
|
|
4
18
|
module ShippingEasy
|
5
19
|
|
6
|
-
class
|
20
|
+
class << self
|
21
|
+
|
22
|
+
attr_accessor :configuration
|
23
|
+
|
24
|
+
def configure
|
25
|
+
configuration = ShippingEasy::Configuration.new
|
26
|
+
yield(configuration)
|
27
|
+
self.configuration = configuration
|
28
|
+
end
|
29
|
+
|
30
|
+
def api_secret
|
31
|
+
configuration.api_secret
|
32
|
+
end
|
7
33
|
|
34
|
+
def api_key
|
35
|
+
configuration.api_key
|
36
|
+
end
|
37
|
+
|
38
|
+
def base_url
|
39
|
+
configuration.base_url
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
class Error < StandardError; end
|
44
|
+
class ResourceNotFoundError < Error; end
|
8
45
|
class RequestExpiredError < Error
|
9
46
|
def initialize(msg = "The request has expired.")
|
10
47
|
super(msg)
|
@@ -0,0 +1,29 @@
|
|
1
|
+
# Configuration class that stores configuration options for the ShippingEasy API.
|
2
|
+
#
|
3
|
+
# ShippingEasy requires an API key and secret combination to authenticate against its API. At the very least these must be
|
4
|
+
# supplied in the configuration.
|
5
|
+
#
|
6
|
+
# Configuration options are typically set via the ShippingEasy.config method.
|
7
|
+
# @see ShippingEasy.configure
|
8
|
+
# @example
|
9
|
+
# ShippingEasy.configure do |config|
|
10
|
+
# config.api_key = "12345"
|
11
|
+
# config.api_secret = "XXXXXXXXXXXXXXXXXXXXXXXX"
|
12
|
+
# end
|
13
|
+
#
|
14
|
+
module ShippingEasy
|
15
|
+
class Configuration
|
16
|
+
|
17
|
+
attr_accessor :api_key,
|
18
|
+
:api_secret,
|
19
|
+
:api_version,
|
20
|
+
:base_url,
|
21
|
+
:http_adapter
|
22
|
+
|
23
|
+
# Creates a configuration object, setting the default attributes.
|
24
|
+
def initialize
|
25
|
+
@http_adapter = ShippingEasy::Http::FaradayAdapter
|
26
|
+
@base_url = "https://app.shippingeasy.com"
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
class ShippingEasy::Http::FaradayAdapter
|
2
|
+
|
3
|
+
extend Forwardable
|
4
|
+
|
5
|
+
def_delegators :request, :body, :params, :base_url, :http_method, :uri
|
6
|
+
|
7
|
+
attr_reader :request
|
8
|
+
|
9
|
+
def initialize(request)
|
10
|
+
@request = request
|
11
|
+
end
|
12
|
+
|
13
|
+
def connect!
|
14
|
+
send(http_method)
|
15
|
+
end
|
16
|
+
|
17
|
+
def post
|
18
|
+
connection.post do |req|
|
19
|
+
req.url uri, params
|
20
|
+
req.body = request.body
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
def connection
|
25
|
+
@connection ||= Faraday.new(url: base_url) do |faraday|
|
26
|
+
faraday.adapter Faraday.default_adapter
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
end
|
@@ -0,0 +1,51 @@
|
|
1
|
+
class ShippingEasy::Http::Request
|
2
|
+
|
3
|
+
attr_accessor :http_method, :body, :params, :relative_path
|
4
|
+
|
5
|
+
def initialize(options = {})
|
6
|
+
@http_method = options.fetch(:http_method, :get)
|
7
|
+
@params = options.fetch(:params, {})
|
8
|
+
@body = options.fetch(:payload, {}).to_json
|
9
|
+
@relative_path = options.delete(:relative_path)
|
10
|
+
end
|
11
|
+
|
12
|
+
def self.connect!(options = {})
|
13
|
+
new(options).connect!
|
14
|
+
end
|
15
|
+
|
16
|
+
def connect!
|
17
|
+
sign_request!
|
18
|
+
adapter.connect!
|
19
|
+
end
|
20
|
+
|
21
|
+
def sign_request!
|
22
|
+
params[:api_key] = api_key
|
23
|
+
params[:api_timestamp] = Time.now.to_i
|
24
|
+
params[:api_signature] = signature.to_s
|
25
|
+
end
|
26
|
+
|
27
|
+
def uri
|
28
|
+
"/api#{relative_path}"
|
29
|
+
end
|
30
|
+
|
31
|
+
def signature
|
32
|
+
ShippingEasy::Signature.new(api_secret: api_secret, method: http_method, path: uri, params: params, body: body)
|
33
|
+
end
|
34
|
+
|
35
|
+
def adapter
|
36
|
+
ShippingEasy.configuration.http_adapter.new(self)
|
37
|
+
end
|
38
|
+
|
39
|
+
def api_secret
|
40
|
+
ShippingEasy.api_secret
|
41
|
+
end
|
42
|
+
|
43
|
+
def api_key
|
44
|
+
ShippingEasy.api_key
|
45
|
+
end
|
46
|
+
|
47
|
+
def base_url
|
48
|
+
ShippingEasy.base_url
|
49
|
+
end
|
50
|
+
|
51
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
class ShippingEasy::Http::ResponseHandler
|
2
|
+
|
3
|
+
extend Forwardable
|
4
|
+
|
5
|
+
def_delegators :response, :status, :body
|
6
|
+
|
7
|
+
attr_reader :response
|
8
|
+
|
9
|
+
def initialize(response)
|
10
|
+
@response = response
|
11
|
+
end
|
12
|
+
|
13
|
+
def self.run(response)
|
14
|
+
new(response).run
|
15
|
+
end
|
16
|
+
|
17
|
+
def run
|
18
|
+
case status
|
19
|
+
when 401 then raise ShippingEasy::AccessDeniedError, response.body
|
20
|
+
when 404 then raise ShippingEasy::ResourceNotFoundError, response.body
|
21
|
+
when 200, 201 then JSON.parse(response.body)
|
22
|
+
else
|
23
|
+
raise ShippingEasy::Error, response.body
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
class ShippingEasy::Resources::Base
|
2
|
+
|
3
|
+
def self.command(name, command_options, &block)
|
4
|
+
define_singleton_method name do |options = {}|
|
5
|
+
options[:relative_path] = command_options.fetch(:relative_path, block.call(options))
|
6
|
+
options[:http_method] = command_options.fetch(:http_method, :get)
|
7
|
+
execute_request!(options)
|
8
|
+
end
|
9
|
+
end
|
10
|
+
|
11
|
+
def self.execute_request!(options = {})
|
12
|
+
response = ShippingEasy::Http::Request.connect!(options)
|
13
|
+
ShippingEasy::Http::ResponseHandler.run(response)
|
14
|
+
end
|
15
|
+
|
16
|
+
end
|
@@ -64,7 +64,8 @@ module ShippingEasy
|
|
64
64
|
# Returns true if the supplied string or signature object matches the current object.
|
65
65
|
def ==(other_signature)
|
66
66
|
expected_signature, supplied_signature = self.to_s, other_signature.to_s
|
67
|
-
return false if expected_signature.
|
67
|
+
return false if expected_signature.nil? || supplied_signature.nil? || expected_signature.empty? || supplied_signature.empty?
|
68
|
+
return false if expected_signature.bytesize != supplied_signature.bytesize
|
68
69
|
l = expected_signature.unpack "C#{expected_signature.bytesize}"
|
69
70
|
res = 0
|
70
71
|
supplied_signature.each_byte { |byte| res |= byte ^ l.shift }
|
data/shipping_easy.gemspec
CHANGED
@@ -18,6 +18,9 @@ Gem::Specification.new do |spec|
|
|
18
18
|
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
19
19
|
spec.require_paths = ["lib"]
|
20
20
|
|
21
|
+
spec.add_dependency('faraday', '>= 0.8.7')
|
22
|
+
spec.add_dependency('rack', ">= 1.4.5")
|
23
|
+
spec.add_dependency('json', "~> 1.8.0")
|
21
24
|
spec.add_development_dependency "bundler", "~> 1.3"
|
22
|
-
spec.add_development_dependency "
|
25
|
+
spec.add_development_dependency "rspec"
|
23
26
|
end
|
@@ -0,0 +1,76 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe ShippingEasy::Authenticator, api: true do
|
4
|
+
let(:api_secret) { "ABC12345" }
|
5
|
+
let(:method) { :post }
|
6
|
+
let(:path) { "/api/orders" }
|
7
|
+
let(:api_signature) { signature.to_s }
|
8
|
+
let(:api_timestamp) { (Time.now - (60 * 5)).to_i }
|
9
|
+
let(:params) { { test_param: "ABCDE", api_key: "123", api_timestamp: api_timestamp } }
|
10
|
+
let(:params_with_signature) { params[:api_signature] = api_signature; params }
|
11
|
+
let(:request_body) { { orders: { name: "Flip flops", cost: "10.00", shipping_cost: "2.00" } }.to_json.to_s }
|
12
|
+
let(:method) { :post }
|
13
|
+
let(:signature) { ShippingEasy::Signature.new(api_secret: api_secret, method: method, path: path, params: params, body: request_body) }
|
14
|
+
subject { ShippingEasy::Authenticator.new(api_secret: api_secret, method: method, path: path, params: params_with_signature, body: request_body) }
|
15
|
+
|
16
|
+
describe "#initialize" do
|
17
|
+
specify { subject.api_secret.should == api_secret }
|
18
|
+
specify { subject.method.should == :post }
|
19
|
+
specify { subject.path.should == path }
|
20
|
+
specify { subject.body.should == request_body }
|
21
|
+
specify { subject.params.should == params_with_signature }
|
22
|
+
specify { subject.params[:api_signature].should be_nil }
|
23
|
+
specify { subject.expected_signature.should be_a(ShippingEasy::Signature) }
|
24
|
+
end
|
25
|
+
|
26
|
+
describe "#request_expires_at" do
|
27
|
+
specify { subject.request_expires_at.to_s.should == (Time.now - ShippingEasy::Authenticator::EXPIRATION_INTERVAL).to_s }
|
28
|
+
end
|
29
|
+
|
30
|
+
describe "#request_expired?" do
|
31
|
+
specify { subject.request_expired?.should be_false }
|
32
|
+
|
33
|
+
context "when expired" do
|
34
|
+
let(:api_timestamp) { (Time.now - (ShippingEasy::Authenticator::EXPIRATION_INTERVAL * 2)).to_i }
|
35
|
+
specify { subject.request_expired?.should be_true }
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
describe "#signatures_match?" do
|
40
|
+
specify { subject.signatures_match?.should be_true }
|
41
|
+
|
42
|
+
context "when they don't match" do
|
43
|
+
let(:api_signature) { "XXX" }
|
44
|
+
specify { subject.signatures_match?.should be_false }
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
describe "#parsed_timestamp" do
|
49
|
+
specify { subject.parsed_timestamp.should be_a(Time) }
|
50
|
+
context "when date string is invalid" do
|
51
|
+
let(:api_timestamp) { "xxxx" }
|
52
|
+
specify { expect{ subject.parsed_timestamp }.to raise_error(ShippingEasy::TimestampFormatError) }
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
describe "#authenticate" do
|
57
|
+
context "when everything is ok" do
|
58
|
+
before do
|
59
|
+
subject.stub(:request_expired?).and_return(false)
|
60
|
+
subject.stub(:signatures_match?).and_return(true)
|
61
|
+
end
|
62
|
+
specify { subject.authenticate.should be_true }
|
63
|
+
end
|
64
|
+
|
65
|
+
context "when request has expired" do
|
66
|
+
before { subject.stub(:request_expired?).and_return(true) }
|
67
|
+
specify { expect{ subject.authenticate }.to raise_error(ShippingEasy::RequestExpiredError)}
|
68
|
+
end
|
69
|
+
|
70
|
+
context "when signatures do not match" do
|
71
|
+
before { subject.stub(:signatures_match?).and_return(false) }
|
72
|
+
specify { expect{ subject.authenticate }.to raise_error(ShippingEasy::AccessDeniedError) }
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
76
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
|
3
|
+
describe ShippingEasy::Configuration do
|
4
|
+
subject { ShippingEasy::Configuration.new }
|
5
|
+
|
6
|
+
specify { subject.should respond_to(:api_key) }
|
7
|
+
specify { subject.should respond_to(:api_secret) }
|
8
|
+
specify { subject.should respond_to(:base_url) }
|
9
|
+
|
10
|
+
describe "http_adapter" do
|
11
|
+
it "gets set to a default" do
|
12
|
+
subject.http_adapter.should == ShippingEasy::Http::FaradayAdapter
|
13
|
+
end
|
14
|
+
|
15
|
+
it "can be overidden" do
|
16
|
+
subject.http_adapter = String
|
17
|
+
subject.http_adapter.should == String
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
describe "base_url" do
|
22
|
+
it "gets set to a default" do
|
23
|
+
subject.base_url.should == "https://app.shippingeasy.com"
|
24
|
+
end
|
25
|
+
|
26
|
+
it "can be overidden" do
|
27
|
+
subject.base_url = String
|
28
|
+
subject.base_url.should == String
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
@@ -0,0 +1,42 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
|
3
|
+
describe ShippingEasy::Http::FaradayAdapter do
|
4
|
+
|
5
|
+
let(:http_method) { "post" }
|
6
|
+
let(:params) { { "page" => 1 } }
|
7
|
+
let(:base_url) { "https://www.test.com" }
|
8
|
+
let(:uri) { "/api/orders" }
|
9
|
+
let(:body) { { order_number: "1234" }.to_json }
|
10
|
+
|
11
|
+
let(:request) do
|
12
|
+
double("request",
|
13
|
+
http_method: http_method,
|
14
|
+
params: params,
|
15
|
+
base_url: base_url,
|
16
|
+
uri: uri,
|
17
|
+
body: body)
|
18
|
+
end
|
19
|
+
|
20
|
+
subject { ShippingEasy::Http::FaradayAdapter.new(request) }
|
21
|
+
|
22
|
+
[:http_method, :params, :base_url, :uri, :body].each do |m|
|
23
|
+
it "delegates #{m} to request" do
|
24
|
+
subject.send(m).should == request.send(m)
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
describe "#connect!" do
|
29
|
+
it "calls the correct http method as specified by the request" do
|
30
|
+
subject.stub(:post)
|
31
|
+
subject.should_receive(:post).once
|
32
|
+
subject.connect!
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
describe "#connection" do
|
37
|
+
it "instantiates a faraday connection" do
|
38
|
+
subject.connection.should be_a(Faraday::Connection)
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
end
|
@@ -0,0 +1,81 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
|
3
|
+
describe ShippingEasy::Http::Request do
|
4
|
+
|
5
|
+
let(:http_method) { "post" }
|
6
|
+
let(:params) { { :page => 1 } }
|
7
|
+
let(:base_url) { "https://www.test.com" }
|
8
|
+
let(:relative_path) { "/orders" }
|
9
|
+
let(:body) { { order_number: "1234" } }
|
10
|
+
let(:api_key) { "12345678ASGHSGHJ" }
|
11
|
+
let(:api_secret) { "12345678ASGHSGHJ123213321312" }
|
12
|
+
let(:signature) { ShippingEasy::Signature.new(api_secret: api_secret, method: http_method, path: "/api#{relative_path}", params: params.dup, body: body.to_json) }
|
13
|
+
|
14
|
+
before do
|
15
|
+
ShippingEasy.configure do |config|
|
16
|
+
config.api_key = api_key
|
17
|
+
config.api_secret = api_secret
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
subject { ShippingEasy::Http::Request.new(http_method: http_method, params: params, relative_path: relative_path, payload: body) }
|
22
|
+
|
23
|
+
[:http_method, :params, :relative_path].each do |m|
|
24
|
+
it "parses and sets the option named #{m}" do
|
25
|
+
subject.send(m).should == send(m)
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
describe "#api_secret" do
|
30
|
+
it "delegates the api_secret to the config" do
|
31
|
+
subject.api_secret.should == ShippingEasy.api_secret
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
describe "#api_key" do
|
36
|
+
it "delegates the api_key to the config" do
|
37
|
+
subject.api_key.should == ShippingEasy.api_key
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
describe "#adpater" do
|
42
|
+
it "instantiates a new adapter" do
|
43
|
+
subject.adapter.should be_a(ShippingEasy::Http::FaradayAdapter)
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
describe "#signature" do
|
48
|
+
it "returns a calculated sigature object" do
|
49
|
+
subject.signature.to_s.should == signature.to_s
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
describe "#sign_request!" do
|
54
|
+
before { subject.sign_request! }
|
55
|
+
|
56
|
+
it "adds the api signature parameter to the params hash" do
|
57
|
+
subject.params[:api_signature].should_not be_nil
|
58
|
+
end
|
59
|
+
|
60
|
+
it "adds the api timestamp parameter to the params hash" do
|
61
|
+
subject.params[:api_timestamp].should_not be_nil
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
describe "#connect" do
|
66
|
+
before do
|
67
|
+
subject.stub(:sign_request!)
|
68
|
+
subject.stub_chain(:adapter, :connect!).and_return("connected!")
|
69
|
+
end
|
70
|
+
|
71
|
+
it "signs the request" do
|
72
|
+
subject.should_receive(:sign_request!).once
|
73
|
+
subject.connect!
|
74
|
+
end
|
75
|
+
|
76
|
+
it "connects via the adapter" do
|
77
|
+
subject.connect!.should == "connected!"
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
81
|
+
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
|
3
|
+
describe ShippingEasy::Http::ResponseHandler do
|
4
|
+
|
5
|
+
let(:status) { 200 }
|
6
|
+
let(:body) { { "order_number" => "12345" }}
|
7
|
+
let(:response) do
|
8
|
+
double("response",
|
9
|
+
status: status,
|
10
|
+
body: body.to_json)
|
11
|
+
end
|
12
|
+
|
13
|
+
subject { ShippingEasy::Http::ResponseHandler.new(response) }
|
14
|
+
|
15
|
+
describe "#run" do
|
16
|
+
context "when success" do
|
17
|
+
specify { subject.run.should == body }
|
18
|
+
end
|
19
|
+
context "when authentication fails" do
|
20
|
+
let(:status) { 401 }
|
21
|
+
specify { expect { subject.run }.to raise_error(ShippingEasy::AccessDeniedError) }
|
22
|
+
end
|
23
|
+
context "when resource cannot be found" do
|
24
|
+
let(:status) { 404 }
|
25
|
+
specify { expect { subject.run }.to raise_error(ShippingEasy::ResourceNotFoundError) }
|
26
|
+
end
|
27
|
+
context "when unexpected error occurs" do
|
28
|
+
let(:status) { 500 }
|
29
|
+
specify { expect { subject.run }.to raise_error(ShippingEasy::Error) }
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
end
|
@@ -0,0 +1,39 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
|
3
|
+
describe ShippingEasy::Resources::Base do
|
4
|
+
|
5
|
+
class GenericResource < ShippingEasy::Resources::Base; end
|
6
|
+
|
7
|
+
describe ".command" do
|
8
|
+
before { GenericResource.command(:create, method: :post) }
|
9
|
+
|
10
|
+
it "defines a method on the class" do
|
11
|
+
GenericResource.should respond_to(:create)
|
12
|
+
end
|
13
|
+
|
14
|
+
it "extracts options to send to a request" do
|
15
|
+
|
16
|
+
end
|
17
|
+
|
18
|
+
context "when a block is provided" do
|
19
|
+
it "uses it as the value for the path" do
|
20
|
+
GenericResource.command(:create, method: :post) do |args|
|
21
|
+
"/this/is/the/path"
|
22
|
+
end
|
23
|
+
GenericResource.should_receive(:execute_request!).with({:relative_path=>"/this/is/the/path", :http_method=>:get})
|
24
|
+
GenericResource.create
|
25
|
+
end
|
26
|
+
|
27
|
+
context "and an argument is passed in" do
|
28
|
+
it "interpolates it" do
|
29
|
+
GenericResource.command(:create, method: :post) do |args|
|
30
|
+
"/this/is/the/#{args.delete(:name)}"
|
31
|
+
end
|
32
|
+
GenericResource.should_receive(:execute_request!).with({:relative_path=>"/this/is/the/ABC123", :http_method=>:get})
|
33
|
+
GenericResource.create(name: "ABC123")
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
end
|
@@ -0,0 +1,40 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe ShippingEasy::Signature do
|
4
|
+
let(:api_secret) { "ABC12345" }
|
5
|
+
let(:method) { :post }
|
6
|
+
let(:path) { "/api/orders" }
|
7
|
+
let(:params) { { test_param: "ABCDE", api_key: "123", api_signature: "XXX" } }
|
8
|
+
let(:request_body) { { orders: { name: "Flip flops", cost: "10.00", shipping_cost: "2.00" } }.to_json.to_s }
|
9
|
+
let(:method) { :post }
|
10
|
+
|
11
|
+
subject { ShippingEasy::Signature.new(api_secret: api_secret, method: method, path: path, params: params, body: request_body) }
|
12
|
+
|
13
|
+
describe "#initialize" do
|
14
|
+
specify { subject.api_secret.should == api_secret }
|
15
|
+
specify { subject.method.should == "POST" }
|
16
|
+
specify { subject.path.should == path }
|
17
|
+
specify { subject.body.should == request_body }
|
18
|
+
specify { subject.params.should == params }
|
19
|
+
specify { subject.params[:api_signature].should be_nil }
|
20
|
+
end
|
21
|
+
|
22
|
+
describe "#plaintext" do
|
23
|
+
specify { subject.plaintext.should == "POST&/api/orders&api_key=123&test_param=ABCDE&{\"orders\":{\"name\":\"Flip flops\",\"cost\":\"10.00\",\"shipping_cost\":\"2.00\"}}"}
|
24
|
+
end
|
25
|
+
|
26
|
+
describe "#encrypted" do
|
27
|
+
specify { subject.encrypted.should == OpenSSL::HMAC::hexdigest("sha256", api_secret, subject.plaintext)}
|
28
|
+
end
|
29
|
+
|
30
|
+
describe "#to_s" do
|
31
|
+
specify { subject.to_s.should == subject.encrypted}
|
32
|
+
end
|
33
|
+
|
34
|
+
describe "#==" do
|
35
|
+
let(:duplicate_signature) { ShippingEasy::Signature.new(api_secret: api_secret, method: method, path: path, params: params, body: request_body) }
|
36
|
+
specify { (subject == OpenSSL::HMAC::hexdigest("sha256", api_secret, subject.plaintext)).should be_true }
|
37
|
+
specify { (subject == OpenSSL::HMAC::hexdigest("sha256", "BADSECRET", subject.plaintext)).should be_false }
|
38
|
+
specify { (subject == duplicate_signature).should be_true }
|
39
|
+
end
|
40
|
+
end
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
require 'bundler/setup'
|
2
|
+
require 'shipping_easy'
|
3
|
+
|
4
|
+
# This file was generated by the `rspec --init` command. Conventionally, all
|
5
|
+
# specs live under a `spec` directory, which RSpec adds to the `$LOAD_PATH`.
|
6
|
+
# Require this file using `require "spec_helper"` to ensure that it is only
|
7
|
+
# loaded once.
|
8
|
+
#
|
9
|
+
# See http://rubydoc.info/gems/rspec-core/RSpec/Core/Configuration
|
10
|
+
RSpec.configure do |config|
|
11
|
+
config.treat_symbols_as_metadata_keys_with_true_values = true
|
12
|
+
config.run_all_when_everything_filtered = true
|
13
|
+
config.filter_run :focus
|
14
|
+
|
15
|
+
# Run specs in random order to surface order dependencies. If you find an
|
16
|
+
# order dependency and want to debug it, you can fix the order by providing
|
17
|
+
# the seed, which is printed after each run.
|
18
|
+
# --seed 1234
|
19
|
+
config.order = 'random'
|
20
|
+
end
|
metadata
CHANGED
@@ -1,41 +1,83 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: shipping_easy
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0
|
4
|
+
version: 0.2.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- ShippingEasy
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2014-
|
11
|
+
date: 2014-03-03 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: faraday
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - ">="
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: 0.8.7
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - ">="
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: 0.8.7
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: rack
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - ">="
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: 1.4.5
|
34
|
+
type: :runtime
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - ">="
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: 1.4.5
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: json
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - "~>"
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: 1.8.0
|
48
|
+
type: :runtime
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - "~>"
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: 1.8.0
|
13
55
|
- !ruby/object:Gem::Dependency
|
14
56
|
name: bundler
|
15
57
|
requirement: !ruby/object:Gem::Requirement
|
16
58
|
requirements:
|
17
|
-
- - ~>
|
59
|
+
- - "~>"
|
18
60
|
- !ruby/object:Gem::Version
|
19
61
|
version: '1.3'
|
20
62
|
type: :development
|
21
63
|
prerelease: false
|
22
64
|
version_requirements: !ruby/object:Gem::Requirement
|
23
65
|
requirements:
|
24
|
-
- - ~>
|
66
|
+
- - "~>"
|
25
67
|
- !ruby/object:Gem::Version
|
26
68
|
version: '1.3'
|
27
69
|
- !ruby/object:Gem::Dependency
|
28
|
-
name:
|
70
|
+
name: rspec
|
29
71
|
requirement: !ruby/object:Gem::Requirement
|
30
72
|
requirements:
|
31
|
-
- -
|
73
|
+
- - ">="
|
32
74
|
- !ruby/object:Gem::Version
|
33
75
|
version: '0'
|
34
76
|
type: :development
|
35
77
|
prerelease: false
|
36
78
|
version_requirements: !ruby/object:Gem::Requirement
|
37
79
|
requirements:
|
38
|
-
- -
|
80
|
+
- - ">="
|
39
81
|
- !ruby/object:Gem::Version
|
40
82
|
version: '0'
|
41
83
|
description: The official ShippingEasy API client for Ruby.
|
@@ -45,19 +87,34 @@ executables: []
|
|
45
87
|
extensions: []
|
46
88
|
extra_rdoc_files: []
|
47
89
|
files:
|
48
|
-
- .gitignore
|
90
|
+
- ".gitignore"
|
91
|
+
- ".rspec"
|
49
92
|
- Gemfile
|
50
93
|
- LICENSE.txt
|
51
94
|
- README.md
|
52
95
|
- Rakefile
|
53
96
|
- lib/shipping_easy.rb
|
54
97
|
- lib/shipping_easy/authenticator.rb
|
55
|
-
- lib/shipping_easy/
|
98
|
+
- lib/shipping_easy/configuration.rb
|
99
|
+
- lib/shipping_easy/http.rb
|
100
|
+
- lib/shipping_easy/http/faraday_adapter.rb
|
101
|
+
- lib/shipping_easy/http/request.rb
|
102
|
+
- lib/shipping_easy/http/response_handler.rb
|
103
|
+
- lib/shipping_easy/resources.rb
|
104
|
+
- lib/shipping_easy/resources/base.rb
|
105
|
+
- lib/shipping_easy/resources/cancellation.rb
|
56
106
|
- lib/shipping_easy/resources/order.rb
|
57
|
-
- lib/shipping_easy/resources/store.rb
|
58
107
|
- lib/shipping_easy/signature.rb
|
59
108
|
- lib/shipping_easy/version.rb
|
60
109
|
- shipping_easy.gemspec
|
110
|
+
- spec/authenticator_spec.rb
|
111
|
+
- spec/configuration_spec.rb
|
112
|
+
- spec/http/faraday_adapter_spec.rb
|
113
|
+
- spec/http/request_spec.rb
|
114
|
+
- spec/http/response_handler_spec.rb
|
115
|
+
- spec/resources/base_spec.rb
|
116
|
+
- spec/signature_spec.rb
|
117
|
+
- spec/spec_helper.rb
|
61
118
|
homepage: https://github.com/ShippingEasy/shipping_easy-ruby
|
62
119
|
licenses:
|
63
120
|
- MIT
|
@@ -68,18 +125,26 @@ require_paths:
|
|
68
125
|
- lib
|
69
126
|
required_ruby_version: !ruby/object:Gem::Requirement
|
70
127
|
requirements:
|
71
|
-
- -
|
128
|
+
- - ">="
|
72
129
|
- !ruby/object:Gem::Version
|
73
130
|
version: '0'
|
74
131
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
75
132
|
requirements:
|
76
|
-
- -
|
133
|
+
- - ">="
|
77
134
|
- !ruby/object:Gem::Version
|
78
135
|
version: '0'
|
79
136
|
requirements: []
|
80
137
|
rubyforge_project:
|
81
|
-
rubygems_version: 2.
|
138
|
+
rubygems_version: 2.2.0
|
82
139
|
signing_key:
|
83
140
|
specification_version: 4
|
84
141
|
summary: The official ShippingEasy API client for Ruby.
|
85
|
-
test_files:
|
142
|
+
test_files:
|
143
|
+
- spec/authenticator_spec.rb
|
144
|
+
- spec/configuration_spec.rb
|
145
|
+
- spec/http/faraday_adapter_spec.rb
|
146
|
+
- spec/http/request_spec.rb
|
147
|
+
- spec/http/response_handler_spec.rb
|
148
|
+
- spec/resources/base_spec.rb
|
149
|
+
- spec/signature_spec.rb
|
150
|
+
- spec/spec_helper.rb
|
File without changes
|
File without changes
|