sendle-api 0.0.2 → 0.0.11

Sign up to get free protection for your applications and to get access to all the features.
Files changed (36) hide show
  1. checksums.yaml +4 -4
  2. data/Changelog.md +5 -0
  3. data/README.md +99 -5
  4. data/lib/sendle/api.rb +46 -3
  5. data/lib/sendle/api/actions/base.rb +51 -0
  6. data/lib/sendle/api/actions/create.rb +31 -0
  7. data/lib/sendle/api/actions/destroy.rb +23 -0
  8. data/lib/sendle/api/actions/index.rb +16 -14
  9. data/lib/sendle/api/actions/show.rb +23 -0
  10. data/lib/sendle/api/constants.rb +4 -0
  11. data/lib/sendle/api/errors/invalid_plan.rb +16 -0
  12. data/lib/sendle/api/errors/missing_params.rb +16 -0
  13. data/lib/sendle/api/errors/payment_required.rb +9 -0
  14. data/lib/sendle/api/errors/precondition_failed.rb +9 -0
  15. data/lib/sendle/api/errors/unprocessable_entity.rb +19 -0
  16. data/lib/sendle/api/factories/errors.rb +26 -0
  17. data/lib/sendle/api/order.rb +41 -0
  18. data/lib/sendle/api/ping.rb +8 -3
  19. data/lib/sendle/api/quote.rb +28 -0
  20. data/lib/sendle/api/resource.rb +64 -0
  21. data/lib/sendle/api/responses/json.rb +15 -0
  22. data/lib/sendle/api/sugars/create.rb +13 -0
  23. data/lib/sendle/api/sugars/destroy.rb +13 -0
  24. data/lib/sendle/api/sugars/index.rb +13 -0
  25. data/lib/sendle/api/sugars/show.rb +13 -0
  26. data/lib/sendle/api/utils.rb +24 -0
  27. data/lib/sendle/api/version.rb +1 -1
  28. data/spec/sendle/api/order_spec.rb +249 -0
  29. data/spec/sendle/api/ping_spec.rb +9 -1
  30. data/spec/sendle/api/quote_spec.rb +103 -0
  31. data/spec/sendle/api_spec.rb +22 -0
  32. data/spec/sendle/errors/missing_params_spec.rb +13 -0
  33. data/spec/support/helpers.rb +15 -1
  34. data/spec/support/shared_examples/with_credentials_spec.rb +1 -1
  35. metadata +29 -3
  36. data/lib/sendle/utils/actions.rb +0 -19
@@ -0,0 +1,26 @@
1
+ module Sendle
2
+ module Api
3
+ module Factories
4
+ class Errors
5
+
6
+ def self.new_error(rest_client_error)
7
+ response = JSON.parse(rest_client_error.response)
8
+ error_text = response['error_description']
9
+ messages = response['messages']
10
+
11
+ case rest_client_error
12
+ when RestClient::Unauthorized
13
+ Sendle::Api::Errors::Unauthorized.new(error_text)
14
+ when RestClient::PaymentRequired
15
+ Sendle::Api::Errors::PaymentRequired.new(error_text)
16
+ when RestClient::UnprocessableEntity
17
+ Sendle::Api::Errors::UnprocessableEntity.new(messages)
18
+ when RestClient::PreconditionFailed
19
+ Sendle::Api::Errors::PreconditionFailed.new(error_text)
20
+ end
21
+ end
22
+
23
+ end
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,41 @@
1
+ class Sendle::Api::Order < Sendle::Api::Resource
2
+ include Sendle::Api::Actions::Create
3
+ include Sendle::Api::Actions::Show
4
+ include Sendle::Api::Actions::Destroy
5
+
6
+ def url
7
+ Sendle::Api.base_url + "orders"
8
+ end
9
+
10
+ def validate_create_request!(params)
11
+ # Checking for required params of parcel
12
+ required = %w( pickup_date kilogram_weight cubic_metre_volume )
13
+ validate_presence_of!(required, params)
14
+
15
+ # Checking for sender params
16
+ raise Sendle::Api::Errors::MissingParams.new(['sender']) unless hash_contains?(params, :sender)
17
+
18
+ sender_params = params[:sender]
19
+ raise Sendle::Api::Errors::MissingParams.new(['sender:contact']) unless hash_contains?(sender_params, :contact)
20
+ required = %w( name phone )
21
+ validate_presence_of!(required, sender_params[:contact])
22
+
23
+ raise Sendle::Api::Errors::MissingParams.new(['sender:address']) unless hash_contains?(sender_params, :address)
24
+ required = %w( address_line1 suburb postcode state_name )
25
+ validate_presence_of!(required, sender_params[:address])
26
+
27
+ # Checking for receiver params
28
+ raise Sendle::Api::Errors::MissingParams.new(['receiver']) unless hash_contains?(params, :receiver)
29
+
30
+ receiver_params = params[:receiver]
31
+ raise Sendle::Api::Errors::MissingParams.new(['receiver:contact']) unless hash_contains?(receiver_params, :contact)
32
+ required = %w( name )
33
+ validate_presence_of!(required, receiver_params[:contact])
34
+
35
+ raise Sendle::Api::Errors::MissingParams.new(['receiver:address']) unless hash_contains?(receiver_params, :address)
36
+ required = %w( address_line1 suburb postcode state_name )
37
+ validate_presence_of!(required, receiver_params[:address])
38
+
39
+ end
40
+
41
+ end
@@ -1,11 +1,16 @@
1
- class Sendle::Api::Ping
2
- extend Sendle::Api::Actions::Index
1
+ class Sendle::Api::Ping < Sendle::Api::Resource
2
+ include Sendle::Api::Actions::Index
3
3
 
4
4
  class << self
5
5
  alias_method :execute, :index
6
6
  end
7
7
 
8
- def self.url
8
+ def url
9
9
  Sendle::Api.base_url + "ping"
10
10
  end
11
+
12
+ def process_index_response(response)
13
+ Sendle::Api::Responses::Pong.new
14
+ end
15
+
11
16
  end
@@ -0,0 +1,28 @@
1
+ class Sendle::Api::Quote < Sendle::Api::Resource
2
+ include Sendle::Api::Actions::Index
3
+
4
+ class << self
5
+ alias_method :execute, :index
6
+ end
7
+
8
+ def url
9
+ Sendle::Api.base_url + "quote"
10
+ end
11
+
12
+ def include_credentials?
13
+ false
14
+ end
15
+
16
+ def validate_index_request!(params)
17
+ # Checking for required params
18
+ required = %w( pickup_suburb pickup_postcode delivery_suburb delivery_postcode kilogram_weight)
19
+ validate_presence_of!(required, params)
20
+
21
+ # Checking for valid plan_name, if passed in
22
+ if params[:plan_name]
23
+ plan_name = params[:plan_name]
24
+ raise Sendle::Api::Errors::InvalidPlan.new(plan_name) unless PLANS.include?(plan_name)
25
+ end
26
+ end
27
+
28
+ end
@@ -0,0 +1,64 @@
1
+ class Sendle::Api::Resource
2
+ include Sendle::Api::Actions::Base
3
+
4
+ def url
5
+ raise "An API Resource must implement the url method."
6
+ end
7
+
8
+ def self.url
9
+ self.new.url
10
+ end
11
+
12
+ def include_credentials?
13
+ true
14
+ end
15
+
16
+ #Index action hook methods
17
+ def validate_index_request!(params)
18
+ end
19
+
20
+ def process_index_response(response)
21
+ return_json(response)
22
+ end
23
+
24
+ #Create action hook methods
25
+ def validate_create_request!(params)
26
+ end
27
+
28
+ def process_create_response(response)
29
+ return_json(response)
30
+ end
31
+
32
+ #Show action hook methods
33
+ def process_show_response(response)
34
+ return_json(response)
35
+ end
36
+
37
+ #Destroy action hook methods
38
+ def process_destroy_response(response)
39
+ return_json(response)
40
+ end
41
+
42
+ def method_missing(m, *args, &blk)
43
+ if Sendle::Api::Utils.respond_to?(m)
44
+ Sendle::Api::Utils.send(m, *args)
45
+ else
46
+ super(m, *args, blk)
47
+ end
48
+ end
49
+
50
+ protected
51
+
52
+ def return_json(response)
53
+ Sendle::Api::Responses::Json.new(response)
54
+ end
55
+
56
+ def validate_presence_of!(required_params, hash)
57
+ symbolize_strings(required_params).each do |required_param|
58
+ if (!hash.key?(required_param) || nullish?(hash[required_param]))
59
+ raise Sendle::Api::Errors::MissingParams.new(required_params)
60
+ end
61
+ end
62
+ end
63
+
64
+ end
@@ -0,0 +1,15 @@
1
+ module Sendle
2
+ module Api
3
+ module Responses
4
+ class Json
5
+ attr_reader :raw, :json
6
+
7
+ def initialize(json_string)
8
+ @raw = json_string
9
+ @json = JSON.parse(json_string)
10
+ end
11
+
12
+ end
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,13 @@
1
+ module Sendle
2
+ module Api
3
+ module Sugars
4
+ module Create
5
+
6
+ def create(params = {})
7
+ self.new.create(params)
8
+ end
9
+
10
+ end
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,13 @@
1
+ module Sendle
2
+ module Api
3
+ module Sugars
4
+ module Destroy
5
+
6
+ def destroy(id)
7
+ self.new.destroy(id)
8
+ end
9
+
10
+ end
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,13 @@
1
+ module Sendle
2
+ module Api
3
+ module Sugars
4
+ module Index
5
+
6
+ def index(params = {})
7
+ self.new.index(params)
8
+ end
9
+
10
+ end
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,13 @@
1
+ module Sendle
2
+ module Api
3
+ module Sugars
4
+ module Show
5
+
6
+ def show(id)
7
+ self.new.show(id)
8
+ end
9
+
10
+ end
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,24 @@
1
+ module Sendle
2
+ module Api
3
+ class Utils
4
+
5
+ class << self
6
+
7
+ def symbolize_strings(array_string)
8
+ array_string.map { |x| x.to_sym }
9
+ end
10
+
11
+ def nullish?(v)
12
+ v.nil? || v.to_s.empty?
13
+ end
14
+
15
+ def hash_contains?(hash, key)
16
+ hash.key?(key) && !hash[key].nil?
17
+ end
18
+
19
+ end
20
+
21
+ end
22
+ end
23
+
24
+ end
@@ -1,5 +1,5 @@
1
1
  module Sendle
2
2
  module Api
3
- VERSION = "0.0.2"
3
+ VERSION = "0.0.11"
4
4
  end
5
5
  end
@@ -0,0 +1,249 @@
1
+ require "spec_helper"
2
+
3
+ describe Sendle::Api::Order do
4
+
5
+ let(:api_key) { 'fake_key' }
6
+ let(:sendle_id) { 'fake_id' }
7
+
8
+ before do
9
+ Sendle::Api.api_key = api_key
10
+ Sendle::Api.sendle_id = sendle_id
11
+ end
12
+
13
+ describe "#create" do
14
+ let(:params) {
15
+ {
16
+ pickup_date: "2016-05-05",
17
+ description: "Kryptonite",
18
+ kilogram_weight: 1,
19
+ cubic_metre_volume: 0.01,
20
+ customer_reference: "SupBdayPressie",
21
+ sender: {
22
+ contact: {
23
+ name: "Lex Luthor",
24
+ phone: "0412 345 678"
25
+ },
26
+ address: {
27
+ address_line1: "123 Gotham Ln",
28
+ suburb: "Sydney",
29
+ state_name: "NSW",
30
+ postcode: "2000",
31
+ country: "Australia"
32
+ },
33
+ instructions: "Knock loudly"
34
+ },
35
+ receiver: {
36
+ contact: {
37
+ name: "Clark Kent",
38
+ email: "clarkissuper@dailyplanet.xyz"
39
+ },
40
+ address: {
41
+ address_line1: "80 Wentworth Park Road",
42
+ suburb: "Glebe",
43
+ state_name: "NSW",
44
+ postcode: "2037",
45
+ country: "Australia"
46
+ },
47
+ instructions: "Give directly to Clark"
48
+ }
49
+ }
50
+ }
51
+
52
+ it_behaves_like "a resource action with credentials"
53
+
54
+ describe "parcel param validation" do
55
+ it "validates presence of required params" do
56
+ params[:pickup_date] = nil
57
+ params[:kilogram_weight] = nil
58
+ params[:cubic_metre_volume] = nil
59
+
60
+ expect {
61
+ Sendle::Api::Order.create(params)
62
+ }.to raise_error(Sendle::Api::Errors::MissingParams, "The following params are required: pickup_date, kilogram_weight, cubic_metre_volume. Please check your request and try again.")
63
+ end
64
+ end
65
+
66
+ describe "sender details" do
67
+ it "validates presence of sender object" do
68
+ params[:sender] = nil
69
+
70
+ expect {
71
+ Sendle::Api::Order.create(params)
72
+ }.to raise_error(Sendle::Api::Errors::MissingParams, "The following params are required: sender. Please check your request and try again.")
73
+ end
74
+
75
+ it "validates presence of contact" do
76
+ params[:sender][:contact] = nil
77
+
78
+ expect {
79
+ Sendle::Api::Order.create(params)
80
+ }.to raise_error(Sendle::Api::Errors::MissingParams, "The following params are required: sender:contact. Please check your request and try again.")
81
+ end
82
+
83
+ it "validates name and phone of contact" do
84
+ expect {
85
+ [:phone, :name].each { |attr| params[:sender][:contact][attr] = nil }
86
+ Sendle::Api::Order.create(params)
87
+ }.to raise_error(Sendle::Api::Errors::MissingParams, "The following params are required: name, phone. Please check your request and try again.")
88
+ end
89
+
90
+ it "validates presence of address" do
91
+ params[:sender][:address] = nil
92
+
93
+ expect {
94
+ Sendle::Api::Order.create(params)
95
+ }.to raise_error(Sendle::Api::Errors::MissingParams, "The following params are required: sender:address. Please check your request and try again.")
96
+ end
97
+
98
+ it "validates address_line1, suburb, postcode, state_name of the address" do
99
+ expect {
100
+ [:address_line1, :suburb, :postcode, :state_name].each { |attr| params[:sender][:address][attr] = nil }
101
+ Sendle::Api::Order.create(params)
102
+ }.to raise_error(Sendle::Api::Errors::MissingParams, "The following params are required: address_line1, suburb, postcode, state_name. Please check your request and try again.")
103
+ end
104
+ end
105
+
106
+ describe "receiver details" do
107
+ it "validates presence of receiver object" do
108
+ params[:receiver] = nil
109
+
110
+ expect {
111
+ Sendle::Api::Order.create(params)
112
+ }.to raise_error(Sendle::Api::Errors::MissingParams, "The following params are required: receiver. Please check your request and try again.")
113
+ end
114
+
115
+ it "validates presence of contact" do
116
+ params[:receiver][:contact] = nil
117
+
118
+ expect {
119
+ Sendle::Api::Order.create(params)
120
+ }.to raise_error(Sendle::Api::Errors::MissingParams, "The following params are required: receiver:contact. Please check your request and try again.")
121
+ end
122
+
123
+ it "validates name of receiver" do
124
+ expect {
125
+ params[:receiver][:contact][:name] = nil
126
+ Sendle::Api::Order.create(params)
127
+ }.to raise_error(Sendle::Api::Errors::MissingParams, "The following params are required: name. Please check your request and try again.")
128
+ end
129
+
130
+ it "validates presence of address" do
131
+ params[:receiver][:address] = nil
132
+
133
+ expect {
134
+ Sendle::Api::Order.create(params)
135
+ }.to raise_error(Sendle::Api::Errors::MissingParams, "The following params are required: receiver:address. Please check your request and try again.")
136
+ end
137
+
138
+ it "validates address_line1, suburb, postcode, state_name of the address" do
139
+ expect {
140
+ [:address_line1, :suburb, :postcode, :state_name].each { |attr| params[:receiver][:address][attr] = nil }
141
+ Sendle::Api::Order.create(params)
142
+ }.to raise_error(Sendle::Api::Errors::MissingParams, "The following params are required: address_line1, suburb, postcode, state_name. Please check your request and try again.")
143
+ end
144
+ end
145
+
146
+ it "handles 412" do
147
+ expect(RestClient::Request).to receive(:execute).and_raise(PRECONDITION_FAILED_ERROR)
148
+
149
+ expect {
150
+ Sendle::Api::Order.create(params)
151
+ }.to raise_error(Sendle::Api::Errors::PreconditionFailed, "The account associated with this API key has not accepted the dangerous goods terms. Please visit your Account Settings in https://www.sendle.com/dashboard/ to view and accept these terms.")
152
+ end
153
+
154
+ it "makes the correct request" do
155
+ expected_params = {
156
+ method: :post,
157
+ url: Sendle::Api::Order.url,
158
+ headers: {
159
+ accept: :json,
160
+ content_type: :json
161
+ },
162
+ payload: params
163
+ }
164
+
165
+ expect(RestClient::Request).to receive(:execute).with(hash_including(expected_params)).and_return(ORDER_CREATED_RESPONSE)
166
+
167
+ Sendle::Api::Order.create(params)
168
+ end
169
+
170
+ it "returns the correct response" do
171
+ allow(RestClient::Request).to receive(:execute).and_return(ORDER_CREATED_RESPONSE)
172
+
173
+ response = Sendle::Api::Order.create(params)
174
+
175
+ expect(response).to be_a Sendle::Api::Responses::Json
176
+ expect(response.json).to eq JSON.parse(ORDER_CREATED_RESPONSE)
177
+ end
178
+
179
+ end
180
+
181
+ describe "#show" do
182
+ let(:order_id) { "9dbadcd6-ee57-488e-a175-49e378ad29ff" }
183
+
184
+ it "throws an error if id isn't provided" do
185
+ expect {
186
+ Sendle::Api::Order.show(nil)
187
+ }.to raise_error(Sendle::Api::Errors::MissingParams, "The following params are required: id. Please check your request and try again.")
188
+ end
189
+
190
+ it "makes the correct request" do
191
+ expected_params = {
192
+ method: :get,
193
+ url: Sendle::Api::Order.url + "/#{order_id}",
194
+ headers: {
195
+ accept: :json,
196
+ content_type: :json
197
+ }
198
+ }
199
+
200
+ expect(RestClient::Request).to receive(:execute).with(hash_including(expected_params)).and_return(ORDER_CREATED_RESPONSE)
201
+
202
+ Sendle::Api::Order.show(order_id)
203
+ end
204
+
205
+ it "returns the correct response" do
206
+ allow(RestClient::Request).to receive(:execute).and_return(ORDER_GET_RESPONSE)
207
+
208
+ response = Sendle::Api::Order.show(order_id)
209
+
210
+ expect(response).to be_a Sendle::Api::Responses::Json
211
+ expect(response.json).to eq JSON.parse(ORDER_GET_RESPONSE)
212
+ end
213
+ end
214
+
215
+ describe "#destroy" do
216
+ let(:order_id) { "9dbadcd6-ee57-488e-a175-49e378ad29ff" }
217
+
218
+ it "throws an error if id isn't provided" do
219
+ expect {
220
+ Sendle::Api::Order.destroy(nil)
221
+ }.to raise_error(Sendle::Api::Errors::MissingParams, "The following params are required: id. Please check your request and try again.")
222
+ end
223
+
224
+ it "makes the correct request" do
225
+ expected_params = {
226
+ method: :delete,
227
+ url: Sendle::Api::Order.url + "/#{order_id}",
228
+ headers: {
229
+ accept: :json,
230
+ content_type: :json
231
+ }
232
+ }
233
+
234
+ expect(RestClient::Request).to receive(:execute).with(hash_including(expected_params)).and_return(ORDER_DELETE_RESPONSE)
235
+
236
+ Sendle::Api::Order.destroy(order_id)
237
+ end
238
+
239
+ it "returns the correct response" do
240
+ allow(RestClient::Request).to receive(:execute).and_return(ORDER_DELETE_RESPONSE)
241
+
242
+ response = Sendle::Api::Order.destroy(order_id)
243
+
244
+ expect(response).to be_a Sendle::Api::Responses::Json
245
+ expect(response.json).to eq JSON.parse(ORDER_DELETE_RESPONSE)
246
+ end
247
+ end
248
+
249
+ end