shipcloud 0.6.0 → 0.7.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: be261ed61c16ba184adf29c75d3c40721eefc397
4
- data.tar.gz: 54e6e380adc84a996c581726a8e3c0a47e60a6bf
3
+ metadata.gz: e1af501886ebceb1740604bdc3216bac732bfd3a
4
+ data.tar.gz: b0eb7b46245cab6d030a7dc4ec268ad2198cc117
5
5
  SHA512:
6
- metadata.gz: 64d988f7fdf9d858e240f132282da454c0bd814b30accc290d045ca17bcf73fce67c370293d1db75b53facff9d9918ace79fcaa4fd99e592fdad0398cfad3340
7
- data.tar.gz: 19ca529bafdf0764d357e0652fe55019a7a84b0d1a5ce8d5c3d5514b571635af6eac92291b2381d084596dc14fbede14a3caf3119997a8518f9603b45645eb83
6
+ metadata.gz: f84e3710264fe699fde827fa9393bb54fa1d054385f8c966da2238898ec9ccfe9b424399e35630c98c89d9e7375fef97d1745d7178087a3030c3267d6e1051f7
7
+ data.tar.gz: 5efa177ecb0085b8dee951c02032b4b874f26c3a85df5ba07920d399c0bf048b2ab2434b75ec3429802a65469195ad03c7f533d4bf39d9c8b1445d45b64367f4
@@ -1,9 +1,10 @@
1
1
  AllCops:
2
- RunRailsCops: true
3
2
  Exclude:
4
3
  - "vendor/**/*"
5
4
  - "db/schema.rb"
6
5
  UseCache: false
6
+ Rails:
7
+ Enabled: true
7
8
  Rails/FindBy:
8
9
  Enabled: false
9
10
  Metrics/LineLength:
@@ -30,6 +31,21 @@ Style/FileName:
30
31
  StyleGuide: https://github.com/bbatsov/ruby-style-guide#snake-case-files
31
32
  Enabled: false
32
33
  Exclude: []
34
+ Style/FirstArrayElementLineBreak:
35
+ Description: >-
36
+ Checks for a line break before the first element in a
37
+ multi-line array.
38
+ Enabled: true
39
+ Style/FirstHashElementLineBreak:
40
+ Description: >-
41
+ Checks for a line break before the first element in a
42
+ multi-line hash.
43
+ Enabled: true
44
+ Style/FirstMethodArgumentLineBreak:
45
+ Description: >-
46
+ Checks for a line break before the first argument in a
47
+ multi-line method call.
48
+ Enabled: true
33
49
  Style/GuardClause:
34
50
  Description: Check for conditionals that can be replaced with guard clauses
35
51
  StyleGuide: https://github.com/bbatsov/ruby-style-guide#no-nested-conditionals
@@ -118,13 +134,24 @@ Style/StringLiteralsInInterpolation:
118
134
  SupportedStyles:
119
135
  - single_quotes
120
136
  - double_quotes
121
- Style/TrailingComma:
122
- Description: Checks for trailing comma in parameter lists and literals.
123
- StyleGuide: https://github.com/bbatsov/ruby-style-guide#no-trailing-array-commas
137
+ Style/TrailingCommaInArguments:
138
+ Description: 'Checks for trailing comma in argument lists.'
139
+ StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#no-trailing-array-commas'
140
+ Enabled: false
141
+ EnforcedStyleForMultiline: no_comma
142
+ SupportedStyles:
143
+ - comma
144
+ - consistent_comma
145
+ - no_comma
146
+ Style/TrailingCommaInLiteral:
147
+ Description: 'Checks for trailing comma in array and hash literals.'
148
+ StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#no-trailing-array-commas'
124
149
  Enabled: false
125
150
  EnforcedStyleForMultiline: no_comma
126
151
  SupportedStyles:
127
152
  - comma
153
+ - consistent_comma
154
+ - no_comma
128
155
  Metrics/AbcSize:
129
156
  Description: A calculated magnitude based on number of assignments, branches, and
130
157
  conditions.
@@ -5,7 +5,6 @@ rvm:
5
5
  - 2.1.7
6
6
  - 2.2.4
7
7
  - 2.3.0
8
- - jruby-9.0.0.0
9
8
  - rbx-2
10
9
  notifications:
11
10
  flowdock:
@@ -1,3 +1,28 @@
1
+ ## [Unreleased]
2
+ ### Added
3
+
4
+ ### Removed
5
+
6
+ ### Changed
7
+
8
+ ### Fixed
9
+
10
+ ## [0.7.0] - 2016-01-21
11
+ ### Added
12
+ - Add the possibility to specify the api key on every request. (#8)
13
+ - Add some more specific error classes ```Shipcloud::ClientError```,```Shipcloud::ServerError```,
14
+ ```Shipcloud::InvalidRequestError```, ```Shipcloud::TooManyRequests``` and ```Shipcloud::NotFoundError``` (#11).
15
+ - Access to the entire response and error descriptions from the error object (#11).
16
+
17
+ ### Removed
18
+ - Removed the following ruby versions from travis-ci test runs:
19
+ - jruby-9.0.0.0
20
+ - Removed ```Shipcloud::APIError``` in preference to more granular error classes (#11).
21
+
22
+ ### Changed
23
+
24
+ ### Fixed
25
+
1
26
  ## [0.6.0] - 2016-01-21
2
27
  ### Added
3
28
  - This CHANGELOG file (Following "[Keep a CHANGELOG](http://keepachangelog.com/)")
data/README.md CHANGED
@@ -4,6 +4,8 @@
4
4
 
5
5
  A Ruby wrapper for the shipcloud API
6
6
 
7
+ We have dropped the support of jruby-9, because there is an issue with mixing hash and keyword arguments (https://github.com/jruby/jruby/issues/3138). When this issue is fixed, we will support jruby-9 again.
8
+
7
9
  ## Installation
8
10
 
9
11
  Add this line to your application's Gemfile:
@@ -20,27 +22,42 @@ Or install it yourself as:
20
22
 
21
23
  ## Usage
22
24
 
23
- Before using the shipcloud API, you need to set the API access key:
25
+ Before using the shipcloud API, you may want to set the API access key.
24
26
 
25
- ```
27
+ ```ruby
26
28
  Shipcloud.api_key = 'your-api-key-goes-here'
27
29
  ```
28
30
 
29
31
  Since Version 0.4.0, you can also do this via a configuration block, e.g. in an initializer:
30
32
 
31
- ```
33
+ ```ruby
32
34
  Shipcloud.configure do |config|
33
35
  config.api_key = 'your-api-key-goes-here'
34
36
  end
35
37
  ```
36
38
 
39
+ You can also pass the API key with each request:
40
+ ```ruby
41
+ Shipcloud::Shipment.create(
42
+ {
43
+ carrier: 'ups',
44
+ from: from-address-params,
45
+ to: to-address-params,
46
+ package: package-params,
47
+ create_shipping_label: true
48
+ },
49
+ api_key: "your-api-key"
50
+ )
51
+ ```
52
+ If you pass in the ```api_key``` option, the value will be used as API key for the current request, even if you have set the ```Shipcloud.api_key``` before.
53
+
37
54
  You can sign up for a developer account at *[shipcloud.io](http://www.shipcloud.io)*
38
55
 
39
56
  ### Create a new shipment
40
57
 
41
58
  To create a new Shipment on the shipclod platform, you need to provide the name of the carrier, to- and from-address, and the package dimensions.
42
59
  For details, see *[shipcloud API documentation on Shipments](http://developers.shipcloud.io/reference/#shipments)*
43
- ```
60
+ ```ruby
44
61
  Shipcloud::Shipment.create(
45
62
  carrier: 'ups',
46
63
  from: from-address-params,
@@ -52,7 +69,7 @@ Shipcloud::Shipment.create(
52
69
 
53
70
  `Shipment#create` will return shipping label and tracking information, encapsulated in a `Shipcloud::Shipment` object:
54
71
 
55
- ```
72
+ ```ruby
56
73
  shipment = Shipcloud::Shipment.create(...) # parameters ommitted
57
74
  shipment.tracking_url # -> http://track.shipcloud.io/uzdgu22z3ed12
58
75
  ```
@@ -2,6 +2,7 @@ require "net/http"
2
2
  require "net/https"
3
3
  require "json"
4
4
  require "shipcloud/version"
5
+ require "shipcloud/shipcloud_error"
5
6
 
6
7
  module Shipcloud
7
8
  API_VERSION = "v1"
@@ -12,8 +13,6 @@ module Shipcloud
12
13
  "User-Agent" => "shipcloud-ruby v#{Shipcloud::VERSION}, API #{Shipcloud::API_VERSION}, #{RUBY_VERSION}, #{RUBY_PLATFORM}, #{RUBY_PATCHLEVEL}"
13
14
  }
14
15
 
15
- @@api_key = nil
16
-
17
16
  autoload :Base, "shipcloud/base"
18
17
  autoload :Shipment, "shipcloud/shipment"
19
18
  autoload :Carrier, "shipcloud/carrier"
@@ -33,13 +32,8 @@ module Shipcloud
33
32
  autoload :Base, "shipcloud/request/base"
34
33
  autoload :Connection, "shipcloud/request/connection"
35
34
  autoload :Info, "shipcloud/request/info"
36
- autoload :Validator, "shipcloud/request/validator"
37
35
  end
38
36
 
39
- class ShipcloudError < StandardError; end
40
- class AuthenticationError < ShipcloudError; end
41
- class APIError < ShipcloudError; end
42
-
43
37
  class << self
44
38
  attr_accessor :configuration
45
39
  end
@@ -75,7 +69,6 @@ module Shipcloud
75
69
  #
76
70
  # @param [String] api_key The api key
77
71
  def self.api_key=(api_key)
78
- @@api_key = api_key
79
72
  configuration.api_key = api_key
80
73
  end
81
74
 
@@ -84,9 +77,12 @@ module Shipcloud
84
77
  # @param [Symbol] http_method The http method to use, must be one of :get, :post, :put and :delete
85
78
  # @param [String] api_url The API url to use
86
79
  # @param [Hash] data The data to send, e.g. used when creating new objects.
80
+ # @param [String] optional api_key The api key. If no api key is given, Shipcloud.api_key will
81
+ # be used for the request
87
82
  # @return [Array] The parsed JSON response.
88
- def self.request(http_method, api_url, data)
89
- info = Request::Info.new(http_method, api_url, data)
83
+ def self.request(http_method, api_url, data, api_key: nil)
84
+ api_key ||= Shipcloud.api_key
85
+ info = Request::Info.new(http_method, api_url, api_key, data)
90
86
  Request::Base.new(info).perform
91
87
  end
92
88
  end
@@ -3,8 +3,12 @@ module Shipcloud
3
3
  module All
4
4
  module ClassMethods
5
5
  # Loads all Objects of the resource
6
- def all(filter = {})
7
- response = Shipcloud.request(:get, base_url, filter)
6
+ # @param [Hash] optional filter Filter the shipments list using one or more filter
7
+ # creteria
8
+ # @param [String] optional api_key The api key. If no api key is given, Shipcloud.api_key
9
+ # will be used for the request
10
+ def all(filter = {}, api_key: nil)
11
+ response = Shipcloud.request(:get, base_url, filter, api_key: api_key)
8
12
  if index_response_root
9
13
  response = response.fetch(index_response_root, [])
10
14
  end
@@ -5,8 +5,10 @@ module Shipcloud
5
5
  # Creates a new object
6
6
  #
7
7
  # @param [Hash] attributes The attributes of the created object
8
- def create(attributes)
9
- response = Shipcloud.request(:post, base_url, attributes)
8
+ # @param \[String\] optional api_key The api key. If no api key is given, Shipcloud.api_key
9
+ # will be used for the request
10
+ def create(attributes, api_key: nil)
11
+ response = Shipcloud.request(:post, base_url, attributes, api_key: api_key)
10
12
  if create_response_root
11
13
  response = response.fetch(create_response_root, {})
12
14
  end
@@ -5,8 +5,10 @@ module Shipcloud
5
5
  # Deletes the given object
6
6
  #
7
7
  # @param [String] id The id of the object that gets deleted
8
- def delete(id)
9
- response = Shipcloud.request(:delete, "#{base_url}/#{id}", {})
8
+ # @param \[String\] optional api_key The api key. If no api key is given, Shipcloud.api_key
9
+ # will be used for the request
10
+ def delete(id, api_key: nil)
11
+ Shipcloud.request(:delete, "#{base_url}/#{id}", {}, api_key: api_key)
10
12
  true
11
13
  end
12
14
  end
@@ -5,9 +5,11 @@ module Shipcloud
5
5
  # Finds a given object
6
6
  #
7
7
  # @param [String] id The id of the object that should be found
8
+ # @param \[String\] optional api_key The api key. If no api key is given, Shipcloud.api_key
9
+ # will be used for the request
8
10
  # @return [Shipcloud::Base] The found object
9
- def find(id)
10
- response = Shipcloud.request(:get, "#{base_url}/#{id}", {})
11
+ def find(id, api_key: nil)
12
+ response = Shipcloud.request(:get, "#{base_url}/#{id}", {}, api_key: api_key)
11
13
  self.new(response)
12
14
  end
13
15
  end
@@ -6,8 +6,10 @@ module Shipcloud
6
6
  # Updates a object
7
7
  # @param [String] id The id of the object that should be updated
8
8
  # @param [Hash] attributes The attributes that should be updated
9
- def update(id, attributes)
10
- response = Shipcloud.request(:put, "#{base_url}/#{id}", attributes)
9
+ # @param \[String\] optional api_key The api key. If no api key is given, Shipcloud.api_key
10
+ # will be used for the request
11
+ def update(id, attributes, api_key: nil)
12
+ response = Shipcloud.request(:put, "#{base_url}/#{id}", attributes, api_key: api_key)
11
13
  self.new(response)
12
14
  end
13
15
  end
@@ -19,8 +21,10 @@ module Shipcloud
19
21
  # Updates a object
20
22
  #
21
23
  # @param [Hash] attributes The attributes that should be updated
22
- def update(attributes)
23
- response = Shipcloud.request(:put, "#{base_url}/#{id}", attributes)
24
+ # @param \[String\] optional api_key The api key. If no api key is given, Shipcloud.api_key
25
+ # will be used for the request
26
+ def update(attributes, api_key: nil)
27
+ response = Shipcloud.request(:put, "#{base_url}/#{id}", attributes, api_key: api_key)
24
28
  set_attributes(response)
25
29
  end
26
30
  end
@@ -2,32 +2,33 @@ module Shipcloud
2
2
  module Request
3
3
  class Base
4
4
  attr_reader :info
5
- attr_accessor :response
6
5
 
7
6
  def initialize(info)
8
7
  @info = info
9
8
  end
10
9
 
11
10
  def perform
12
- raise AuthenticationError if Shipcloud.api_key.nil?
11
+ raise AuthenticationError unless @info.api_key
13
12
  connection.setup_https
14
- send_request
15
- validator.validated_data_for(response)
13
+ response = connection.request
14
+ validate_response(response)
15
+ JSON.parse(response.body)
16
+ rescue JSON::ParserError
17
+ raise ShipcloudError.new(response)
16
18
  end
17
19
 
18
20
  protected
19
21
 
20
- def send_request
21
- self.response = connection.request
22
+ def validate_response(response)
23
+ error = ShipcloudError.from_response(response)
24
+ if error
25
+ raise error
26
+ end
22
27
  end
23
28
 
24
29
  def connection
25
30
  @connection ||= Connection.new(info)
26
31
  end
27
-
28
- def validator
29
- @validator ||= Validator.new(info)
30
- end
31
32
  end
32
33
  end
33
34
  end
@@ -38,7 +38,7 @@ module Shipcloud
38
38
  else
39
39
  Net::HTTP::Get.new(@info.path_with_params(@info.url, @info.data), API_HEADERS)
40
40
  end
41
- https_request.basic_auth(Shipcloud.api_key, "")
41
+ https_request.basic_auth(@info.api_key, "")
42
42
  https_request.body = @info.data.to_json if [:post, :put].include?(@info.http_method)
43
43
  https_request
44
44
  end
@@ -1,9 +1,10 @@
1
1
  module Shipcloud
2
2
  module Request
3
3
  class Info
4
- attr_accessor :http_method, :api_url, :data
4
+ attr_accessor :http_method, :api_url, :api_key, :data
5
5
 
6
- def initialize(http_method, api_url, data)
6
+ def initialize(http_method, api_url, api_key, data)
7
+ @api_key = api_key
7
8
  @http_method = http_method
8
9
  @api_url = api_url
9
10
  @data = data
@@ -0,0 +1,66 @@
1
+ module Shipcloud
2
+ class ShipcloudError < StandardError
3
+ attr_reader :errors, :response
4
+
5
+ def initialize(response = nil)
6
+ @response = response
7
+ @errors = parse_errors
8
+ error_message = errors.empty? ? response_body : errors
9
+ super(error_message)
10
+ end
11
+
12
+ # Returns the appropriate Shipcloud::ShipcloudError subclass based
13
+ # on status code
14
+ #
15
+ # @param [HTTPResponse] response HTTP response
16
+ # @return [Shipcloud::ShipcloudError]
17
+ def self.from_response(response)
18
+ response_code = response.code.to_i
19
+ if error_class = error_class_for(response_code)
20
+ error_class.new(response)
21
+ end
22
+ end
23
+
24
+ def self.error_class_for(response_code)
25
+ case response_code
26
+ when 400, 422 then InvalidRequestError
27
+ when 401 then AuthenticationError
28
+ when 402 then TooManyRequests
29
+ when 404 then NotFoundError
30
+ when 400..499 then ClientError
31
+ when 500..599 then ServerError
32
+ end
33
+ end
34
+
35
+ private_class_method :error_class_for
36
+
37
+ private
38
+
39
+ def parse_errors
40
+ return [] unless response_body
41
+ data = JSON.parse(response_body)
42
+ if data.is_a?(Hash) && data["errors"]
43
+ data["errors"]
44
+ else
45
+ []
46
+ end
47
+ rescue JSON::ParserError
48
+ []
49
+ end
50
+
51
+ def response_body
52
+ return unless @response
53
+ @response.body
54
+ end
55
+ end
56
+
57
+ # Raised on errors in the 400-499 range
58
+ class ClientError < ShipcloudError; end
59
+ class AuthenticationError < ClientError; end
60
+ class InvalidRequestError < ClientError; end
61
+ class TooManyRequests < ClientError; end
62
+ class NotFoundError < ClientError; end
63
+
64
+ # Raised on errors in the 500-599 range
65
+ class ServerError < ShipcloudError; end
66
+ end
@@ -1,3 +1,3 @@
1
1
  module Shipcloud
2
- VERSION = "0.6.0"
2
+ VERSION = "0.7.0"
3
3
  end
@@ -35,31 +35,35 @@ describe Shipcloud::Address do
35
35
 
36
36
  describe '.create' do
37
37
  it 'makes a new POST request using the correct API endpoint' do
38
- Shipcloud.should_receive(:request).with(:post, 'addresses', valid_attributes).and_return('data' => {})
38
+ expect(Shipcloud).to receive(:request).
39
+ with(:post, "addresses", valid_attributes, api_key: nil).and_return("data" => {})
40
+
39
41
  Shipcloud::Address.create(valid_attributes)
40
42
  end
41
43
  end
42
44
 
43
45
  describe '.find' do
44
46
  it 'makes a new GET request using the correct API endpoint to receive a specific address' do
45
- Shipcloud.should_receive(:request).with(
46
- :get, 'addresses/123', {}).and_return('id' => '123')
47
- Shipcloud::Address.find('123')
47
+ expect(Shipcloud).to receive(:request).with(
48
+ :get, "addresses/123", {}, api_key: nil).and_return("id" => "123")
49
+
50
+ Shipcloud::Address.find("123")
48
51
  end
49
52
  end
50
53
 
51
54
  describe '.update' do
52
55
  it 'makes a new PUT request using the correct API endpoint' do
53
- Shipcloud.should_receive(:request).with(
54
- :put, 'addresses/123', {:street => 'Mittelweg' }).and_return('data' => {})
55
- Shipcloud::Address.update('123', {:street => 'Mittelweg' })
56
+ expect(Shipcloud).to receive(:request).with(
57
+ :put, "addresses/123", { street: "Mittelweg" }, api_key: nil).and_return("data" => {})
58
+
59
+ Shipcloud::Address.update("123", street: "Mittelweg")
56
60
  end
57
61
  end
58
62
 
59
63
  describe '.all' do
60
64
  it 'makes a new Get request using the correct API endpoint' do
61
65
  expect(Shipcloud).to receive(:request).
62
- with(:get, 'addresses', {}).and_return([])
66
+ with(:get, "addresses", {}, api_key: nil).and_return([])
63
67
 
64
68
  Shipcloud::Address.all
65
69
  end
@@ -77,38 +81,38 @@ describe Shipcloud::Address do
77
81
 
78
82
  def stub_addresses_request
79
83
  allow(Shipcloud).to receive(:request).
80
- with(:get, 'addresses', {}).
81
- and_return(
82
- [
83
- {
84
- 'id' => '1c81efb7-9b95-4dd8-92e3-cac1bca3df6f',
85
- 'company' => '',
86
- 'first_name' => 'Max',
87
- 'last_name' => 'Mustermann',
88
- 'care_of' => '',
89
- 'street' => 'Musterstraße',
90
- 'street_no' => '42',
91
- 'zip_code' => '12345',
92
- 'city' => 'Musterstadt',
93
- 'state' => '',
94
- 'country' => 'DE',
95
- 'phone' => ''
96
- },
97
- {
98
- 'id' => '7ea2a290-b456-4ecf-9010-e82b3da298f0',
99
- 'company' => 'Muster-Company',
100
- 'first_name' => 'Max',
101
- 'last_name' => 'Mustermann',
102
- 'care_of' => '',
103
- 'street' => 'Musterstraße',
104
- 'street_no' => '42',
105
- 'zip_code' => '54321',
106
- 'city' => 'Musterstadt',
107
- 'state' => '',
108
- 'country' => 'DE',
109
- 'phone' => ''
110
- }
111
- ]
112
- )
84
+ with(:get, "addresses", {}, api_key: nil).
85
+ and_return(
86
+ [
87
+ {
88
+ "id" => "1c81efb7-9b95-4dd8-92e3-cac1bca3df6f",
89
+ "company" => "",
90
+ "first_name" => "Max",
91
+ "last_name" => "Mustermann",
92
+ "care_of" => "",
93
+ "street" => "Musterstraße",
94
+ "street_no" => "42",
95
+ "zip_code" => "12345",
96
+ "city" => "Musterstadt",
97
+ "state" => "",
98
+ "country" => "DE",
99
+ "phone" => ""
100
+ },
101
+ {
102
+ "id" => "7ea2a290-b456-4ecf-9010-e82b3da298f0",
103
+ "company" => "Muster-Company",
104
+ "first_name" => "Max",
105
+ "last_name" => "Mustermann",
106
+ "care_of" => "",
107
+ "street" => "Musterstraße",
108
+ "street_no" => "42",
109
+ "zip_code" => "54321",
110
+ "city" => "Musterstadt",
111
+ "state" => "",
112
+ "country" => "DE",
113
+ "phone" => ""
114
+ }
115
+ ]
116
+ )
113
117
  end
114
118
  end
@@ -24,7 +24,7 @@ describe Shipcloud::Carrier do
24
24
  describe '.all' do
25
25
  it 'makes a new Get request using the correct API endpoint' do
26
26
  expect(Shipcloud).to receive(:request).
27
- with(:get, 'carriers', {}).and_return([])
27
+ with(:get, "carriers", {}, api_key: nil).and_return([])
28
28
 
29
29
  Shipcloud::Carrier.all
30
30
  end
@@ -69,9 +69,9 @@ describe Shipcloud::Carrier do
69
69
  end
70
70
 
71
71
  def stub_carriers_request
72
- allow(Shipcloud).to receive(:request)
73
- .with(:get, 'carriers', {})
74
- .and_return(
72
+ allow(Shipcloud).to receive(:request).
73
+ with(:get, "carriers", {}, api_key: nil).
74
+ and_return(
75
75
  [
76
76
  {
77
77
  'name' => 'carrier_1',
@@ -3,25 +3,61 @@ require "spec_helper"
3
3
  describe Shipcloud::Request::Base do
4
4
  context "#perform" do
5
5
  it "checks for an api key" do
6
- Shipcloud.stub(:api_key).and_return(nil)
6
+ info = Shipcloud::Request::Info.new(:get, "shipments", nil, {})
7
7
 
8
8
  expect{
9
- Shipcloud::Request::Base.new(nil).perform
9
+ Shipcloud::Request::Base.new(info).perform
10
10
  }.to raise_error Shipcloud::AuthenticationError
11
11
  end
12
12
 
13
- it "performs an https request" do
14
- Shipcloud.stub(:api_key).and_return("some key")
15
- connection = stub
16
- validator = stub
17
- Shipcloud::Request::Connection.stub(:new).and_return(connection)
18
- Shipcloud::Request::Validator.stub(:new).and_return(validator)
13
+ it "performs an https request and returns a response hash" do
14
+ connection = double
15
+ expect(Shipcloud::Request::Connection).to receive(:new).and_return(connection)
16
+ expect(connection).to receive(:setup_https)
17
+ response = double(code: "200", body: { id: 1 }.to_json)
18
+ expect(connection).to receive(:request).and_return(response)
19
+ info = Shipcloud::Request::Info.new(:get, "shipments", "api_key", {})
19
20
 
20
- connection.should_receive(:setup_https)
21
- connection.should_receive(:request)
22
- validator.should_receive(:validated_data_for)
21
+ data = Shipcloud::Request::Base.new(info).perform
23
22
 
24
- Shipcloud::Request::Base.new(nil).perform
23
+ expect(data).to eq("id" => 1)
24
+ end
25
+
26
+ it "performs an https request and raises an Shipcloud::ClientError if the response "\
27
+ "has a 400 status code" do
28
+ connection = double
29
+ expect(Shipcloud::Request::Connection).to receive(:new).and_return(connection)
30
+ expect(connection).to receive(:setup_https)
31
+ response = double(code: "400", body: { id: 1 }.to_json)
32
+ expect(connection).to receive(:request).and_return(response)
33
+ info = Shipcloud::Request::Info.new(:get, "shipments", "api_key", {})
34
+
35
+ expect { Shipcloud::Request::Base.new(info).perform }.to raise_error(Shipcloud::ClientError)
36
+ end
37
+
38
+ it "performs an https request and raises an Shipcloud::ServerError if the response "\
39
+ "has a 500 status code" do
40
+ connection = double
41
+ expect(Shipcloud::Request::Connection).to receive(:new).and_return(connection)
42
+ expect(connection).to receive(:setup_https)
43
+ response = double(code: "500", body: { id: 1 }.to_json)
44
+ expect(connection).to receive(:request).and_return(response)
45
+ info = Shipcloud::Request::Info.new(:get, "shipments", "api_key", {})
46
+
47
+ expect { Shipcloud::Request::Base.new(info).perform }.to raise_error(Shipcloud::ServerError)
48
+ end
49
+
50
+ it "performs an https request and raises an Shipcloud::ShipcloudError if the body of the "\
51
+ "response is not in JSON" do
52
+ connection = double
53
+ expect(Shipcloud::Request::Connection).to receive(:new).and_return(connection)
54
+ expect(connection).to receive(:setup_https)
55
+ response = double(code: "200", body: "no json")
56
+ expect(connection).to receive(:request).and_return(response)
57
+ info = Shipcloud::Request::Info.new(:get, "shipments", "api_key", {})
58
+
59
+ expect { Shipcloud::Request::Base.new(info).perform }.
60
+ to raise_error(Shipcloud::ShipcloudError)
25
61
  end
26
62
  end
27
- end
63
+ end
@@ -0,0 +1,125 @@
1
+ require "spec_helper"
2
+
3
+ describe Shipcloud::ShipcloudError do
4
+ describe ".from_response" do
5
+ context "with a response with status code 400" do
6
+ it "returns a Shipcloud::InvalidRequestError" do
7
+ expect(Shipcloud::ShipcloudError.from_response(build_response(status_code: 400))).to be_a(
8
+ Shipcloud::InvalidRequestError
9
+ )
10
+ end
11
+ end
12
+
13
+ context "with a response with status code 422" do
14
+ it "returns a Shipcloud::InvalidRequestError" do
15
+ expect(Shipcloud::ShipcloudError.from_response(build_response(status_code: 422))).to be_a(
16
+ Shipcloud::InvalidRequestError
17
+ )
18
+ end
19
+ end
20
+
21
+ context "with a response with status code 401" do
22
+ it "returns a Shipcloud::AuthenticationError" do
23
+ expect(Shipcloud::ShipcloudError.from_response(build_response(status_code: 401))).to be_a(
24
+ Shipcloud::AuthenticationError
25
+ )
26
+ end
27
+ end
28
+
29
+ context "with a response with status code 402" do
30
+ it "returns a Shipcloud::TooManyRequests" do
31
+ expect(Shipcloud::ShipcloudError.from_response(build_response(status_code: 402))).to be_a(
32
+ Shipcloud::TooManyRequests
33
+ )
34
+ end
35
+ end
36
+
37
+ context "with a response with status code 404" do
38
+ it "returns a Shipcloud::NotFoundError" do
39
+ expect(Shipcloud::ShipcloudError.from_response(build_response(status_code: 404))).to be_a(
40
+ Shipcloud::NotFoundError
41
+ )
42
+ end
43
+ end
44
+
45
+ context "with a response with a 4xx status code" do
46
+ it "returns a Shipcloud::ClientError" do
47
+ expect(Shipcloud::ShipcloudError.from_response(build_response(status_code: 400))).to be_a(
48
+ Shipcloud::ClientError
49
+ )
50
+ end
51
+ end
52
+
53
+ context "with a response with a 5xx status code" do
54
+ it "returns a Shipcloud::ClientError" do
55
+ expect(Shipcloud::ShipcloudError.from_response(build_response(status_code: 500))).to be_a(
56
+ Shipcloud::ServerError
57
+ )
58
+ end
59
+ end
60
+
61
+ context "with a 200 response" do
62
+ it "returns nil" do
63
+ expect(Shipcloud::ShipcloudError.from_response(build_response(status_code: 200))).to be_nil
64
+ end
65
+ end
66
+ end
67
+
68
+ describe "#message" do
69
+ context "with an errors node in the response body" do
70
+ it "returns the errors formated as one string" do
71
+ errors = ["error 1", "error 2"]
72
+ response = build_response(body: { errors: errors }.to_json)
73
+ error = Shipcloud::ShipcloudError.new(response)
74
+
75
+ expect(error.message).to eq '["error 1", "error 2"]'
76
+ end
77
+ end
78
+ context "without an errors node in the response body" do
79
+ it "returns the body of the response" do
80
+ error = Shipcloud::ShipcloudError.new(build_response(body: "test"))
81
+
82
+ expect(error.message).to eq "test"
83
+ end
84
+ end
85
+ end
86
+
87
+ describe "#errors" do
88
+ it "returns the errors node of the response" do
89
+ errors = ["error 1", "error 2"]
90
+ response = build_response(body: { errors: errors }.to_json)
91
+ error = Shipcloud::ShipcloudError.new(response)
92
+
93
+ expect(error.errors).to eq errors
94
+ end
95
+ context "with a response that has no errors node" do
96
+ it "returns an empty list" do
97
+ response = build_response(body: {}.to_json)
98
+ error = Shipcloud::ShipcloudError.new(response)
99
+
100
+ expect(error.errors).to eq []
101
+ end
102
+ end
103
+ context "with a response that has no JSON formated body" do
104
+ it "returns an empty list" do
105
+ response = build_response(body: "error")
106
+ error = Shipcloud::ShipcloudError.new(response)
107
+
108
+ expect(error.errors).to eq []
109
+ end
110
+ end
111
+ end
112
+
113
+ describe "#response" do
114
+ it "returns the response" do
115
+ response = build_response
116
+ error = Shipcloud::ShipcloudError.new(response)
117
+
118
+ expect(error.response).to eq response
119
+ end
120
+ end
121
+
122
+ def build_response(status_code: 400, body: nil)
123
+ double(code: status_code.to_s, body: body)
124
+ end
125
+ end
@@ -52,7 +52,7 @@ describe Shipcloud::ShipmentQuote do
52
52
  describe ".create" do
53
53
  it "makes a new POST request using the correct API endpoint" do
54
54
  expect(Shipcloud).to receive(:request).
55
- with(:post, "shipment_quotes", valid_attributes).
55
+ with(:post, "shipment_quotes", valid_attributes, api_key: nil).
56
56
  and_return("data" => {})
57
57
 
58
58
  Shipcloud::ShipmentQuote.create(valid_attributes)
@@ -47,28 +47,32 @@ describe Shipcloud::Shipment do
47
47
 
48
48
  describe ".create" do
49
49
  it "makes a new POST request using the correct API endpoint" do
50
- Shipcloud.should_receive(:request).with(:post, "shipments", valid_attributes).and_return("data" => {})
50
+ expect(Shipcloud).to receive(:request).
51
+ with(:post, "shipments", valid_attributes, api_key: nil).and_return("data" => {})
51
52
  Shipcloud::Shipment.create(valid_attributes)
52
53
  end
53
54
  end
54
55
 
55
56
  describe ".find" do
56
57
  it "makes a new GET request using the correct API endpoint to receive a specific subscription" do
57
- Shipcloud.should_receive(:request).with(:get, "shipments/123", {}).and_return("id" => "123")
58
+ expect(Shipcloud).to receive(:request).with(:get, "shipments/123", {}, api_key: nil).
59
+ and_return("id" => "123")
58
60
  Shipcloud::Shipment.find("123")
59
61
  end
60
62
  end
61
63
 
62
64
  describe ".update" do
63
65
  it "makes a new PUT request using the correct API endpoint" do
64
- Shipcloud.should_receive(:request).with(:put, "shipments/123", {:carrier => 'ups' }).and_return("data" => {})
65
- Shipcloud::Shipment.update("123", {:carrier => 'ups' })
66
+ expect(Shipcloud).to receive(:request).
67
+ with(:put, "shipments/123", { carrier: "ups" }, api_key: nil).and_return("data" => {})
68
+ Shipcloud::Shipment.update("123", carrier: "ups")
66
69
  end
67
70
  end
68
71
 
69
72
  describe ".delete" do
70
73
  it "makes a new DELETE request using the correct API endpoint" do
71
- Shipcloud.should_receive(:request).with(:delete, "shipments/123", {}).and_return(true)
74
+ expect(Shipcloud).to receive(:request).with(:delete, "shipments/123", {}, api_key: nil).
75
+ and_return(true)
72
76
  Shipcloud::Shipment.delete("123")
73
77
  end
74
78
  end
@@ -76,7 +80,7 @@ describe Shipcloud::Shipment do
76
80
  describe ".all" do
77
81
  it "makes a new Get request using the correct API endpoint" do
78
82
  expect(Shipcloud).to receive(:request).
79
- with(:get, "shipments", {}).
83
+ with(:get, "shipments", {}, api_key: nil).
80
84
  and_return("shipments" => [])
81
85
 
82
86
  Shipcloud::Shipment.all
@@ -104,7 +108,7 @@ describe Shipcloud::Shipment do
104
108
  }
105
109
 
106
110
  expect(Shipcloud).to receive(:request).
107
- with(:get, "shipments", filter).
111
+ with(:get, "shipments", filter, api_key: nil).
108
112
  and_return("shipments" => shipments_array)
109
113
 
110
114
  Shipcloud::Shipment.all(filter)
@@ -113,7 +117,7 @@ describe Shipcloud::Shipment do
113
117
 
114
118
  def stub_shipments_requests
115
119
  allow(Shipcloud).to receive(:request).
116
- with(:get, "shipments", {}).
120
+ with(:get, "shipments", {}, api_key: nil).
117
121
  and_return("shipments" => shipments_array)
118
122
  end
119
123
 
@@ -16,8 +16,8 @@ describe Shipcloud::Webhook do
16
16
 
17
17
  describe ".create" do
18
18
  it "makes a new POST request using the correct API endpoint" do
19
- Shipcloud.should_receive(:request).
20
- with(:post, "webhooks", valid_attributes).
19
+ expect(Shipcloud).to receive(:request).
20
+ with(:post, "webhooks", valid_attributes, api_key: nil).
21
21
  and_return("data" => {})
22
22
  Shipcloud::Webhook.create(valid_attributes)
23
23
  end
@@ -25,7 +25,9 @@ describe Shipcloud::Webhook do
25
25
 
26
26
  describe ".find" do
27
27
  it "makes a new GET request using the correct API endpoint to receive a specific webhook" do
28
- Shipcloud.should_receive(:request).with(:get, "webhooks/123", {}).and_return("id" => "123")
28
+ expect(Shipcloud).to receive(:request).
29
+ with(:get, "webhooks/123", {}, api_key: nil).
30
+ and_return("id" => "123")
29
31
  Shipcloud::Webhook.find("123")
30
32
  end
31
33
  end
@@ -33,7 +35,7 @@ describe Shipcloud::Webhook do
33
35
  describe ".all" do
34
36
  it "makes a new Get request using the correct API endpoint" do
35
37
  expect(Shipcloud).to receive(:request).
36
- with(:get, "webhooks", {}).
38
+ with(:get, "webhooks", {}, api_key: nil).
37
39
  and_return("webhooks" => [])
38
40
 
39
41
  Shipcloud::Webhook.all
@@ -52,7 +54,7 @@ describe Shipcloud::Webhook do
52
54
 
53
55
  def stub_webhooks_request
54
56
  allow(Shipcloud).to receive(:request).
55
- with(:get, "webhooks", {}).
57
+ with(:get, "webhooks", {}, api_key: nil).
56
58
  and_return("webhooks" => webhooks_array)
57
59
  end
58
60
 
@@ -29,6 +29,20 @@ describe Shipcloud do
29
29
  WebMock.should have_requested(:get, "https://#{Shipcloud::api_key}:@#{Shipcloud.configuration.api_base}/#{Shipcloud::API_VERSION}/transactions")
30
30
  end
31
31
  end
32
+
33
+ context "with an api key passed in as an argument" do
34
+ it "uses the given api key instead of the global one" do
35
+ WebMock.stub_request(:any, /#{Shipcloud.configuration.api_base}/).to_return(body: "{}")
36
+ Shipcloud.api_key = "global-api-key"
37
+
38
+ Shipcloud.request(:get, "transactions", {}, api_key: "123")
39
+
40
+ expect(WebMock).to have_requested(
41
+ :get,
42
+ "https://123:@#{Shipcloud.configuration.api_base}/#{Shipcloud::API_VERSION}/transactions"
43
+ )
44
+ end
45
+ end
32
46
  end
33
47
 
34
48
  describe '.configure' do
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: shipcloud
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.6.0
4
+ version: 0.7.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - sthollmann
@@ -151,7 +151,7 @@ files:
151
151
  - lib/shipcloud/request/base.rb
152
152
  - lib/shipcloud/request/connection.rb
153
153
  - lib/shipcloud/request/info.rb
154
- - lib/shipcloud/request/validator.rb
154
+ - lib/shipcloud/shipcloud_error.rb
155
155
  - lib/shipcloud/shipment.rb
156
156
  - lib/shipcloud/shipment_quote.rb
157
157
  - lib/shipcloud/version.rb
@@ -161,7 +161,7 @@ files:
161
161
  - spec/shipcloud/carrier_spec.rb
162
162
  - spec/shipcloud/request/base_spec.rb
163
163
  - spec/shipcloud/request/connection_spec.rb
164
- - spec/shipcloud/request/validator_spec.rb
164
+ - spec/shipcloud/shipcloud_error_spec.rb
165
165
  - spec/shipcloud/shipment_quote_spec.rb
166
166
  - spec/shipcloud/shipment_spec.rb
167
167
  - spec/shipcloud/webhooks_spec.rb
@@ -196,7 +196,7 @@ test_files:
196
196
  - spec/shipcloud/carrier_spec.rb
197
197
  - spec/shipcloud/request/base_spec.rb
198
198
  - spec/shipcloud/request/connection_spec.rb
199
- - spec/shipcloud/request/validator_spec.rb
199
+ - spec/shipcloud/shipcloud_error_spec.rb
200
200
  - spec/shipcloud/shipment_quote_spec.rb
201
201
  - spec/shipcloud/shipment_spec.rb
202
202
  - spec/shipcloud/webhooks_spec.rb
@@ -1,33 +0,0 @@
1
- module Shipcloud
2
- module Request
3
- class Validator
4
- attr_reader :info
5
- attr_accessor :response
6
-
7
- def initialize(info)
8
- @info = info
9
- end
10
-
11
- def validated_data_for(incoming_response)
12
- self.response = incoming_response
13
- verify_response_code
14
- if response.body
15
- info.data = JSON.parse(response.body)
16
- validate_response_data
17
- end
18
- info.data
19
- end
20
-
21
- protected
22
-
23
- def verify_response_code
24
- raise AuthenticationError if response.code.to_i == 401
25
- raise APIError if response.code.to_i >= 500
26
- end
27
-
28
- def validate_response_data
29
- raise APIError.new(info.data["errors"]) if info.data.is_a?(Hash) && info.data["errors"]
30
- end
31
- end
32
- end
33
- end
@@ -1,24 +0,0 @@
1
- require "spec_helper"
2
-
3
- describe Shipcloud::Request::Validator do
4
- describe "#validated_data_for" do
5
- it "validates the data" do
6
- info = Shipcloud::Request::Info.new(:get, "random", OpenStruct.new(id: 1))
7
- validator = Shipcloud::Request::Validator.new info
8
- response = OpenStruct.new(body: '{"response":"ok"}', code: 200)
9
-
10
- validator.validated_data_for(response).should eq "response" => "ok"
11
- end
12
-
13
- it 'raises an APIError if the response contains errors' do
14
- info = Shipcloud::Request::Info.new(:get, 'random', {})
15
- validator = Shipcloud::Request::Validator.new info
16
- response = OpenStruct.new(body: '{"errors":["some error"]}', code: 200)
17
-
18
- expect { validator.validated_data_for(response) }.to raise_error(
19
- Shipcloud::APIError,
20
- ['some error'].to_s
21
- )
22
- end
23
- end
24
- end