sendle-api 0.0.2 → 0.0.11

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.
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