shipcloud 0.6.0 → 0.7.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 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