after_ship 0.0.2 → 0.0.4

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,45 @@
1
+ class AfterShip
2
+ # Wrapper object for AfterShip courier:
3
+ # https://www.aftership.com/docs/api/4/couriers/get-couriers
4
+ class Courier
5
+ include Attributes
6
+
7
+ # Unique code of courier.
8
+ #
9
+ # @return [String]
10
+ attr_accessor :slug
11
+
12
+ # Name of courier.
13
+ #
14
+ # @return [String]
15
+ attr_accessor :name
16
+
17
+ # Contact phone number of courier.
18
+ #
19
+ # @return [String]
20
+ attr_accessor :phone
21
+
22
+ # Other name of courier.
23
+ #
24
+ # @return [String]
25
+ attr_accessor :other_name
26
+
27
+ # Website link of courier.
28
+ #
29
+ # @return [String]
30
+ attr_accessor :web_url
31
+
32
+ # The extra fields need for tracking, such as `tracking_account_number`,
33
+ # `tracking_postal_code`, `tracking_ship_date`.
34
+ #
35
+ # @return [Array]
36
+ attr_accessor :required_fields
37
+
38
+ # Better interface for a courier.
39
+ #
40
+ # @param data [Hash] tracking hash
41
+ def initialize(data)
42
+ load_attributes(data)
43
+ end
44
+ end
45
+ end
@@ -1,6 +1,6 @@
1
1
  class AfterShip
2
2
  # Wrapper object for AfterShip tracking:
3
- # https://www.aftership.com/docs/api/3.0/tracking/get-trackings-slug-tracking_number
3
+ # https://www.aftership.com/docs/api/4/trackings/get-trackings-slug-tracking_number
4
4
  class Tracking
5
5
  include Attributes
6
6
 
@@ -14,27 +14,59 @@ class AfterShip
14
14
  # @return [DateTime]
15
15
  attr_reader :updated_at
16
16
 
17
+ # A unique identifier generated by AfterShip for the tracking.
18
+ #
19
+ # @return [String]
20
+ attr_accessor :id
21
+
17
22
  # Tracking number, e.g. +1ZA2207X6794165804+.
18
23
  #
19
24
  # @return [String]
20
25
  attr_accessor :tracking_number
21
26
 
27
+ # The postal code of receiver's address. Required by some couriers, such
28
+ # as +deutsch-post+.
29
+ #
30
+ # @return [String]
31
+ attr_accessor :tracking_postal_code
32
+
33
+ # Shipping date in +YYYYMMDD+ format. Required by some couriers, such as
34
+ # +deutsch-post+.
35
+ #
36
+ # @return [String]
37
+ attr_reader :tracking_ship_date
38
+
39
+ # Account number of the shipper for a specific courier. Required by some
40
+ # couriers, such as +dynamic-logistics+.
41
+ #
42
+ # @return [String]
43
+ attr_accessor :tracking_account_number
44
+
22
45
  # Unique code of courier.
23
46
  #
24
47
  # @return [String]
25
48
  attr_reader :slug
26
49
 
27
- # Courier name
50
+ # Courier name.
51
+ #
52
+ # Custom method!
28
53
  #
29
54
  # @return [String]
30
55
  attr_accessor :courier
31
56
 
32
57
  # Whether or not AfterShip will continue tracking the shipments. Value is
33
- # +false+ when status is +Delivered+ or +Expired+.
58
+ # +false+ when tag (status) is +Delivered+, +Expired+, or further updates
59
+ # for 30 days since last update.
34
60
  #
35
- # @return [Boolean]
61
+ # @return [Bool]
36
62
  attr_accessor :active
37
63
 
64
+ # Google cloud message registration IDs to receive the push notifications.
65
+ # Accept either array or Comma comma separated as input.
66
+ #
67
+ # @return [Array, String]
68
+ attr_accessor :android
69
+
38
70
  # Custom fields of the tracking.
39
71
  #
40
72
  # @return [Hash]
@@ -45,6 +77,19 @@ class AfterShip
45
77
  # @return [String]
46
78
  attr_accessor :customer_name
47
79
 
80
+ # Total delivery time in days.
81
+ #
82
+ # * Difference of 1st checkpoint time and delivered time for delivered
83
+ # shipments.
84
+ # * Difference of 1st checkpoint time and current time for non-delivered
85
+ # shipments.
86
+ #
87
+ # Value as +0+ for pending shipments or delivered shipment with only one
88
+ # checkpoint.
89
+ #
90
+ # @return [Fixnum]
91
+ attr_accessor :delivery_time
92
+
48
93
  # Destination country of the tracking. ISO Alpha-3 (three letters). If you
49
94
  # use postal service to send international shipments, AfterShip will
50
95
  # automatically get tracking results from destination postal service based
@@ -69,6 +114,12 @@ class AfterShip
69
114
  # @return [DateTime]
70
115
  attr_reader :expected_delivery
71
116
 
117
+ # Apple iOS device IDs to receive the push notificaitons.
118
+ # Accept either array or Comma comma separated as input.
119
+ #
120
+ # @return [Array, String]
121
+ attr_accessor :ios
122
+
72
123
  # Text field for order ID.
73
124
  #
74
125
  # @return [String]
@@ -84,8 +135,9 @@ class AfterShip
84
135
  # @return [String]
85
136
  attr_accessor :origin_country_iso3
86
137
 
87
- # You can use the value, to direct access the tracking result at this url:
88
- # https://yourusername.aftership.com/unique_token
138
+ # The token to generate the direct tracking link:
139
+ # https://yourusername.aftership.com/unique_token or
140
+ # https://www.aftership.com/unique_token.
89
141
  #
90
142
  # @return [String]
91
143
  attr_accessor :unique_token
@@ -100,6 +152,16 @@ class AfterShip
100
152
  # @return [String]
101
153
  attr_accessor :shipment_type
102
154
 
155
+ # Shipment weight provied by carrier (if any).
156
+ #
157
+ # @return [Fixnum]
158
+ attr_accessor :shipment_weight
159
+
160
+ # Weight unit provied by carrier, either in +kg+ or +lb+ (if any).
161
+ #
162
+ # @return [String]
163
+ attr_accessor :shipment_weight_unit
164
+
103
165
  # Signed by information for delivered shipment (if any).
104
166
  #
105
167
  # @return [String]
@@ -129,6 +191,8 @@ class AfterShip
129
191
 
130
192
  # Same as tag, except human-friendly:
131
193
  #
194
+ # Custom method!
195
+ #
132
196
  # * +Pending+ => +Pending+
133
197
  # * +InfoReceived+ => +Info Received+
134
198
  # * +InTransit+ => +In Transit+
@@ -178,6 +242,14 @@ class AfterShip
178
242
  @updated_at = DateTime.parse(value)
179
243
  end
180
244
 
245
+ # Shipping date in +YYYYMMDD+ format. Required by some couriers, such as
246
+ # +deutsch-post+.
247
+ #
248
+ # @return [DateTime]
249
+ def tracking_ship_date=(value)
250
+ @tracking_ship_date = DateUtils.parse(value)
251
+ end
252
+
181
253
  # Unique code of courier.
182
254
  #
183
255
  # @return [String]
data/lib/after_ship.rb CHANGED
@@ -1,118 +1,48 @@
1
+ # Gems.
1
2
  require 'typhoeus'
2
3
  require 'multi_json'
3
4
 
4
- require 'attributes'
5
- require 'date_utils'
6
- require 'after_ship/version'
5
+ # Core classes.
6
+ require 'after_ship/core/version'
7
+ require 'after_ship/core/attributes'
8
+ require 'after_ship/core/date_utils'
9
+ require 'after_ship/core/request'
10
+ require 'after_ship/core/error'
11
+ require 'after_ship/core/error_handler'
12
+
13
+ # AfterShip classes.
7
14
  require 'after_ship/tracking'
8
15
  require 'after_ship/checkpoint'
16
+ require 'after_ship/courier'
9
17
 
10
- # Init the client:
18
+ # Quick rundown, check individual methods for more info:
11
19
  #
12
20
  # client = AfterShip.new(api_key: 'your-aftership-api-key')
13
- #
14
- # Get a list of trackings
15
- # https://www.aftership.com/docs/api/3.0/tracking/get-trackings
16
- #
17
21
  # client.trackings
18
- #
19
- # # Will return list of Tracking objects:
20
- #
21
- # [
22
- # #<AfterShip::Tracking ...>,
23
- # #<AfterShip::Tracking ...>,
24
- # ...
25
- # ]
26
- #
27
- # Get a tracking
28
- # https://www.aftership.com/docs/api/3.0/tracking/get-trackings-slug-tracking_number
29
- #
30
22
  # client.tracking('tracking-number', 'ups')
31
- #
32
- # # Will return Tracking object or raise AfterShip::ResourceNotFoundError
33
- # # if not exists:
34
- #
35
- # #<AfterShip::Tracking:0x007fe555bd9560
36
- # @active=false,
37
- # @courier="UPS",
38
- # @created_at=#<DateTime: 2014-05-08T15:25:01+00:00 ...>,
39
- # @updated_at=#<DateTime: 2014-07-18T09:00:47+00:00 ...>>
40
- # @custom_fields={},
41
- # @customer_name=nil,
42
- # @destination_country_iso3="USA",
43
- # @emails=[],
44
- # @expected_delivery=nil,
45
- # @order_id="PL-12480166",
46
- # @order_id_path=nil,
47
- # @origin_country_iso3="IND",
48
- # @shipment_package_count=0,
49
- # @shipment_type="EXPEDITED",
50
- # @signed_by="FRONT DOOR",
51
- # @slug="ups",
52
- # @smses=[],
53
- # @source="api",
54
- # @status="Delivered",
55
- # @tag="Delivered",
56
- # @title="1ZA2207X6790326683",
57
- # @tracked_count=47,
58
- # @tracking_number="1ZA2207X6790326683",
59
- # @unique_token="ly9ueXUJC",
60
- # @checkpoints=[
61
- # #<AfterShip::Checkpoint:0x007fe555bb0340
62
- # @checkpoint_time=#<DateTime: 2014-05-12T14:07:00+00:00 ...>,
63
- # @city="NEW YORK",
64
- # @country_iso3=nil,
65
- # @country_name="US",
66
- # @courier="UPS",
67
- # @created_at=#<DateTime: 2014-05-12T18:34:32+00:00 ...>,
68
- # @message="DELIVERED",
69
- # @slug="ups",
70
- # @state="NY",
71
- # @status="Delivered",
72
- # @tag="Delivered",
73
- # @zip="10075">
74
- # #<AfterShip::Checkpoint ...>,
75
- # ...
76
- # ]>
77
- #
78
- # Create a new tracking
79
- # https://www.aftership.com/docs/api/3.0/tracking/post-trackings
80
- #
81
23
  # client.create_tracking('tracking-number', 'ups', order_id: 'external-id')
82
- #
83
- # # Will return Tracking object or raise AfterShip::InvalidArgumentError
84
- # # if it exists:
85
- #
86
- # #<AfterShip::Tracking ...>
87
- #
88
- # Update a tracking
89
- # https://www.aftership.com/docs/api/3.0/tracking/put-trackings-slug-tracking_number
90
- #
91
24
  # client.update_tracking('tracking-number', 'ups', order_id: 'external-id')
25
+ # client.couriers
92
26
  #
93
27
  # To debug:
94
28
  #
95
29
  # AfterShip.debug = true
96
30
  #
97
- # client.tracking('9405903699300211343566', 'usps') # In transit
98
- # client.tracking('1ZA2207X6794165804', 'ups') # Delivered, wild
99
- # client.tracking('1ZA2207X6791425225', 'ups') # Delivered, ok
100
- # client.tracking('1ZA2207X6790326683', 'ups') # Delivered, ok
31
+ # Some test trackings:
32
+ #
33
+ # client.tracking('1ZA2207X0444990982', 'ups')
101
34
  class AfterShip
102
- class Error < StandardError; end
103
- class InvalidJSONDataError < Error; end # 400
104
- class InvalidCredentialsError < Error; end # 401
105
- class RequestFailedError < Error; end # 402
106
- class ResourceNotFoundError < Error; end # 404
107
- class InvalidArgumentError < Error; end # 409
108
- class TooManyRequestsError < Error; end # 429
109
- class ServerError < Error; end # 500, 502, 503, 504
110
- class UnknownError < Error; end
35
+ # The API root URL.
36
+ DEFAULT_API_ADDRESS = 'https://api.aftership.com/v4'
111
37
 
112
- DEFAULT_API_ADDRESS = 'https://api.aftership.com/v3'
113
- TRACKINGS_ENDPOINT = "#{ DEFAULT_API_ADDRESS }/trackings"
38
+ # The trackings endpoint URL.
39
+ TRACKINGS_ENDPOINT = "#{ DEFAULT_API_ADDRESS }/trackings"
114
40
 
115
- JSON_OPTIONS = {
41
+ # The activated couriers endpoint URL.
42
+ COURIERS_ENDPOINT = "#{ DEFAULT_API_ADDRESS }/couriers"
43
+
44
+ # Common JSON loading/dumping options.
45
+ JSON_OPTIONS = {
116
46
  symbolize_keys: true # Symbol keys to string keys
117
47
  }
118
48
 
@@ -136,49 +66,127 @@ class AfterShip
136
66
  attr_accessor :debug
137
67
  end
138
68
 
69
+ # The API key required for the AfterShip service.
70
+ #
71
+ # @return [String]
139
72
  attr_reader :api_key
140
73
 
74
+ # Init the client:
75
+ #
76
+ # client = AfterShip.new(api_key: 'your-aftership-api-key')
77
+ #
141
78
  # @param options [Hash]
142
- # api_key [String]
79
+ # @option options api_key [String]
143
80
  def initialize(options)
144
- require_arguments(
145
- api_key: options[:api_key]
146
- )
147
-
148
- @api_key = options.delete(:api_key)
81
+ @api_key = options.fetch(:api_key)
149
82
  end
150
83
 
151
84
  # Get a list of trackings.
152
- # https://www.aftership.com/docs/api/3.0/tracking/get-trackings
85
+ # https://www.aftership.com/docs/api/4/trackings/get-trackings
86
+ #
87
+ # client.trackings
88
+ #
89
+ # # Will return list of Tracking objects:
90
+ #
91
+ # [
92
+ # #<AfterShip::Tracking ...>,
93
+ # #<AfterShip::Tracking ...>,
94
+ # ...
95
+ # ]
153
96
  #
154
97
  # @return [Hash]
155
98
  def trackings
156
- response = request_response(TRACKINGS_ENDPOINT, {}, :get)
157
- data = response.fetch(:data).fetch(:trackings)
99
+ data = Request.get(url: TRACKINGS_ENDPOINT, api_key: api_key) do |response|
100
+ response.fetch(:data).fetch(:trackings)
101
+ end
158
102
 
159
103
  data.map { |datum| Tracking.new(datum) }
160
104
  end
161
105
 
162
106
  # Get a single tracking. Raises an error if not found.
163
- # https://www.aftership.com/docs/api/3.0/tracking/get-trackings-slug-tracking_number
107
+ # https://www.aftership.com/docs/api/4/trackings/get-trackings-slug-tracking_number
108
+ #
109
+ # client.tracking('tracking-number', 'ups')
110
+ #
111
+ # # Will return Tracking object or raise AfterShip::Error::NotFound:
112
+ #
113
+ # #<AfterShip::Tracking:0x007f838ef44e58
114
+ # @active=false,
115
+ # @android=[],
116
+ # @courier="UPS",
117
+ # @created_at=#<DateTime: 2014-11-19T15:16:17+00:00 ...>,
118
+ # @custom_fields={},
119
+ # @customer_name=nil,
120
+ # @delivery_time=8,
121
+ # @destination_country_iso3="USA",
122
+ # @emails=[],
123
+ # @expected_delivery=nil,
124
+ # @id="546cb4414a1a2097122ae7b1",
125
+ # @ios=[],
126
+ # @order_id="PL-66448782",
127
+ # @order_id_path=nil,
128
+ # @origin_country_iso3="IND",
129
+ # @shipment_package_count=1,
130
+ # @shipment_type="UPS SAVER",
131
+ # @shipment_weight=0.5,
132
+ # @shipment_weight_unit="kg",
133
+ # @signed_by="MET CUSTOM",
134
+ # @slug="ups",
135
+ # @smses=[],
136
+ # @source="api",
137
+ # @status="Delivered",
138
+ # @tag="Delivered",
139
+ # @title="1ZA2207X0490715335",
140
+ # @tracked_count=6,
141
+ # @tracking_account_number=nil,
142
+ # @tracking_number="1ZA2207X0490715335",
143
+ # @tracking_postal_code=nil,
144
+ # @tracking_ship_date=nil,
145
+ # @unique_token="-y6ziF438",
146
+ # @updated_at=#<DateTime: 2014-11-19T22:12:32+00:00 ...>,
147
+ # @checkpoints=[
148
+ # #<AfterShip::Checkpoint:0x007f838ef57d50
149
+ # @checkpoint_time=
150
+ # #<DateTime: 2014-11-11T19:12:00+00:00 ...>,
151
+ # @city="MUMBAI",
152
+ # @country_iso3=nil,
153
+ # @country_name="IN",
154
+ # @courier="UPS",
155
+ # @created_at=
156
+ # #<DateTime: 2014-11-19T15:16:17+00:00 ...>,
157
+ # @message="PICKUP SCAN",
158
+ # @slug="ups",
159
+ # @state=nil,
160
+ # @status="In Transit",
161
+ # @tag="InTransit",
162
+ # @zip=nil>,
163
+ # #<AfterShip::Checkpoint ...>,
164
+ # ...
165
+ # ]
166
+ # >
164
167
  #
165
168
  # @param tracking_number [String]
166
169
  # @param courier [String]
167
170
  #
168
171
  # @return [Hash]
169
172
  def tracking(tracking_number, courier)
170
- require_arguments(tracking_number: tracking_number, courier: courier)
171
-
172
- url = "#{ TRACKINGS_ENDPOINT }/#{ courier }/#{ tracking_number }"
173
-
174
- response = request_response(url, {}, :get)
175
- data = response.fetch(:data).fetch(:tracking)
173
+ url = "#{ TRACKINGS_ENDPOINT }/#{ courier }/#{ tracking_number }"
174
+ data = Request.get(url: url, api_key: api_key) do |response|
175
+ response.fetch(:data).fetch(:tracking)
176
+ end
176
177
 
177
178
  Tracking.new(data)
178
179
  end
179
180
 
180
181
  # Create a new tracking.
181
- # https://www.aftership.com/docs/api/3.0/tracking/post-trackings
182
+ # https://www.aftership.com/docs/api/4/trackings/post-trackings
183
+ #
184
+ # client.create_tracking('tracking-number', 'ups', order_id: 'external-id')
185
+ #
186
+ # # Will return Tracking object or raise
187
+ # # AfterShip::Error::TrackingAlreadyExists:
188
+ #
189
+ # #<AfterShip::Tracking ...>
182
190
  #
183
191
  # @param tracking_number [String]
184
192
  # @param courier [String]
@@ -186,22 +194,30 @@ class AfterShip
186
194
  #
187
195
  # @return [Hash]
188
196
  def create_tracking(tracking_number, courier, options = {})
189
- require_arguments(tracking_number: tracking_number, courier: courier)
190
-
191
- params = {
197
+ body = {
192
198
  tracking: {
193
199
  tracking_number: tracking_number,
194
200
  slug: courier
195
201
  }.merge(options)
196
202
  }
197
203
 
198
- response = request_response(TRACKINGS_ENDPOINT, params, :post)
199
- data = response.fetch(:data).fetch(:tracking)
204
+ data = Request.post(url: TRACKINGS_ENDPOINT, api_key: api_key,
205
+ body: body) do |response|
206
+ response.fetch(:data).fetch(:tracking)
207
+ end
200
208
 
201
209
  Tracking.new(data)
202
210
  end
203
211
 
204
- # https://www.aftership.com/docs/api/3.0/tracking/put-trackings-slug-tracking_number
212
+ # Update a tracking.
213
+ # https://www.aftership.com/docs/api/4/trackings/put-trackings-slug-tracking_number
214
+ #
215
+ # client.update_tracking('tracking-number', 'ups', order_id: 'external-id')
216
+ #
217
+ # # Will return Tracking object or raise
218
+ # # AfterShip::Error::TrackingAlreadyExists:
219
+ #
220
+ # #<AfterShip::Tracking ...>
205
221
  #
206
222
  # @param tracking_number [String]
207
223
  # @param courier [String]
@@ -209,115 +225,43 @@ class AfterShip
209
225
  #
210
226
  # @return [Hash]
211
227
  def update_tracking(tracking_number, courier, options = {})
212
- require_arguments(tracking_number: tracking_number, courier: courier)
213
-
214
- url = "#{ TRACKINGS_ENDPOINT }/#{ courier }/#{ tracking_number }"
215
- params = {
228
+ url = "#{ TRACKINGS_ENDPOINT }/#{ courier }/#{ tracking_number }"
229
+ body = {
216
230
  tracking: options
217
231
  }
218
232
 
219
- response = request_response(url, params, :put)
220
- data = response.fetch(:data).fetch(:tracking)
221
-
222
- Tracking.new(data)
223
- end
224
-
225
- # Raises an ArgumentError if any of the args is empty or nil.
226
- #
227
- # @param hash [Hash] arguments needed in options
228
- def require_arguments(hash)
229
- hash.each do |name, value|
230
- if value.respond_to?(:empty?)
231
- invalid_argument!(name) if value.empty?
232
- else
233
- invalid_argument!(name)
234
- end
233
+ data = Request.put(url: url, api_key: api_key, body: body) do |response|
234
+ response.fetch(:data).fetch(:tracking)
235
235
  end
236
- end
237
236
 
238
- protected
239
-
240
- # @param name [Symbol]
241
- def invalid_argument!(name)
242
- fail ArgumentError, "Argument #{ name } cannot be empty"
237
+ Tracking.new(data)
243
238
  end
244
239
 
245
- # Prepare a `Typhoeus::Request`, send it over the net and deal
246
- # with te response by either returning a Hash or raising an error.
240
+ # Get a list of activated couriers.
241
+ # https://www.aftership.com/docs/api/4/couriers/get-couriers
247
242
  #
248
- # @param url [String]
249
- # @param body_hash [Hash]
250
- # @param method [Symbol]
243
+ # client.couriers
251
244
  #
252
- # @return [Hash]
253
- def request_response(url, body_hash, method = :get)
254
- body_json = MultiJson.dump(body_hash)
255
-
256
- request = Typhoeus::Request.new(
257
- url,
258
- method: method,
259
- verbose: self.class.debug,
260
- body: body_json,
261
- headers: {
262
- 'aftership-api-key' => @api_key,
263
- 'Content-Type' => 'application/json'
264
- }
265
- )
266
-
267
- if self.class.debug
268
- request.on_complete do |response|
269
- puts
270
- puts 'Request body:'
271
- puts request.options[:body]
272
- puts
273
- puts 'Response body:'
274
- puts response.body
275
- puts
276
- end
277
- end
278
-
279
- response = request.run
280
- response_to_json(response)
281
- end
282
-
283
- # Deal with API response, either return a Hash or raise an error.
245
+ # # Will return list of Courier objects:
284
246
  #
285
- # @param response [Typhoeus::Response]
247
+ # [
248
+ # #<AfterShip::Courier:0x007fa2771d4bf8
249
+ # @name="USPS",
250
+ # @other_name="United States Postal Service",
251
+ # @phone="+1 800-275-8777",
252
+ # @required_fields=[],
253
+ # @slug="usps",
254
+ # @web_url="https://www.usps.com">,
255
+ # #<AfterShip::Courier ...>
256
+ # ...
257
+ # ]
286
258
  #
287
259
  # @return [Hash]
288
- #
289
- # rubocop:disable Metrics/CyclomaticComplexity, Metrics/MethodLength
290
- def response_to_json(response)
291
- json_response = parse_response(response)
292
-
293
- case json_response[:meta][:code]
294
- when 200, 201
295
- return json_response
296
- when 400
297
- fail InvalidJSONDataError, json_response[:meta][:error_message]
298
- when 401
299
- fail InvalidCredentialsError, json_response[:meta][:error_message]
300
- when 402
301
- fail RequestFailedError, json_response[:meta][:error_message]
302
- when 404
303
- fail ResourceNotFoundError, json_response[:meta][:error_message]
304
- when 409
305
- fail InvalidArgumentError, json_response[:meta][:error_message]
306
- when 429
307
- fail TooManyRequestsError, json_response[:meta][:error_message]
308
- when 500, 502, 503, 504
309
- fail ServerError, json_response[:meta][:error_message]
310
- else
311
- fail UnknownError, json_response[:meta][:error_message]
260
+ def couriers
261
+ data = Request.get(url: COURIERS_ENDPOINT, api_key: api_key) do |response|
262
+ response.fetch(:data).fetch(:couriers)
312
263
  end
313
- end
314
264
 
315
- # Parse response body into a Hash.
316
- #
317
- # @param response [Typhoeus::Response]
318
- #
319
- # @return [Hash]
320
- def parse_response(response)
321
- MultiJson.load(response.body, JSON_OPTIONS)
265
+ data.map { |datum| Courier.new(datum) }
322
266
  end
323
267
  end
@@ -0,0 +1,40 @@
1
+ require 'spec_helper'
2
+
3
+ RSpec.describe AfterShip do
4
+ let(:client) { AfterShip.new(api_key: 'key') }
5
+
6
+ it 'trackings' do
7
+ trackings = client.trackings
8
+ expect(trackings.size).to eq(2)
9
+ end
10
+
11
+ it 'trackings with debug' do
12
+ AfterShip.debug = true
13
+
14
+ trackings = client.trackings
15
+ expect(trackings.size).to eq(2)
16
+
17
+ AfterShip.debug = nil
18
+ end
19
+
20
+ it 'tracking' do
21
+ tracking = client.tracking('delivered', 'ups')
22
+ expect(tracking.tracking_number).to eq('1ZA2207X0444990982')
23
+ expect(tracking.checkpoints.size).to eq(15)
24
+ end
25
+
26
+ it 'create_tracking' do
27
+ tracking = client.create_tracking('created', 'ups', order_id: 'external-id')
28
+ expect(tracking.tracking_number).to eq('1Z0659120300549388')
29
+ end
30
+
31
+ it 'update_tracking' do
32
+ tracking = client.update_tracking('updated', 'ups', order_id: 'external-id')
33
+ expect(tracking.tracking_number).to eq('1Z0659120300549388')
34
+ end
35
+
36
+ it 'couriers' do
37
+ couriers = client.couriers
38
+ expect(couriers.size).to eq(4)
39
+ end
40
+ end