affirm-ruby-v1 1.1.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.
@@ -0,0 +1,432 @@
1
+ require "helper"
2
+ require_relative "charge_object_interface"
3
+
4
+ RSpec.describe Affirm::Charge do
5
+ let(:failed_response) { double(:response, success?: false, body: Hash.new) }
6
+
7
+ context "authorize" do
8
+ context "with failed response" do
9
+ subject { described_class }
10
+
11
+ before do
12
+ expect(Affirm::Client).to receive(:request)
13
+ .with(:post, "transactions", transaction_id: "ABC", order_id: "ORDER-1")
14
+ .and_return(failed_response)
15
+ end
16
+
17
+ it "returns failure object" do
18
+ expect(
19
+ subject.authorize("ABC", "ORDER-1")
20
+ ).to be_an_instance_of(Affirm::FailureResult)
21
+ end
22
+ end
23
+
24
+ context "with successful response" do
25
+ subject { described_class.authorize("ABC", "ORDER-1") }
26
+
27
+ let(:body) do
28
+ JSON.load(
29
+ File.read(File.expand_path("../fixtures/auth.json", __FILE__))
30
+ )
31
+ end
32
+
33
+ let(:successful_response) do
34
+ double(:response, success?: true, body: body)
35
+ end
36
+
37
+ before do
38
+ expect(Affirm::Client).to receive(:request)
39
+ .with(:post, "transactions", transaction_id: "ABC", order_id: "ORDER-1")
40
+ .and_return(successful_response)
41
+ end
42
+
43
+ it_behaves_like "a transaction object interface"
44
+ end
45
+
46
+ context "with reference_id" do
47
+ subject { described_class.authorize("ABC", "ORDER-1", reference_id: "REF-9") }
48
+
49
+ let(:successful_response) do
50
+ double(:response, success?: true, body: { "id" => "TX-1", "status" => "authorized" })
51
+ end
52
+
53
+ before do
54
+ expect(Affirm::Client).to receive(:request)
55
+ .with(:post, "transactions", transaction_id: "ABC", order_id: "ORDER-1", reference_id: "REF-9")
56
+ .and_return(successful_response)
57
+ end
58
+
59
+ it "returns success" do
60
+ expect(subject).to be_success
61
+ end
62
+ end
63
+
64
+ context "without order_id" do
65
+ it "raises ArgumentError when nil" do
66
+ expect {
67
+ described_class.authorize("ABC", nil)
68
+ }.to raise_error(ArgumentError, /order_id is required/)
69
+ end
70
+
71
+ it "raises ArgumentError when empty string" do
72
+ expect {
73
+ described_class.authorize("ABC", "")
74
+ }.to raise_error(ArgumentError, /order_id is required/)
75
+ end
76
+ end
77
+
78
+ context "with successful response but non-Hash body" do
79
+ subject { described_class.authorize("ABC", "ORDER-1") }
80
+
81
+ let(:non_hash_response) do
82
+ double(:response, success?: true, body: "<html>Bad Gateway</html>")
83
+ end
84
+
85
+ before do
86
+ expect(Affirm::Client).to receive(:request)
87
+ .with(:post, "transactions", transaction_id: "ABC", order_id: "ORDER-1")
88
+ .and_return(non_hash_response)
89
+ end
90
+
91
+ it "returns failure object" do
92
+ expect(subject).to be_an_instance_of(Affirm::FailureResult)
93
+ end
94
+ end
95
+
96
+ context "with successful response and no type field" do
97
+ subject { described_class.authorize("ABC", "ORDER-1") }
98
+
99
+ let(:body) do
100
+ JSON.load(
101
+ File.read(File.expand_path("../fixtures/auth.json", __FILE__))
102
+ )
103
+ end
104
+
105
+ let(:successful_response) do
106
+ double(:response, success?: true, body: body)
107
+ end
108
+
109
+ before do
110
+ expect(Affirm::Client).to receive(:request)
111
+ .with(:post, "transactions", transaction_id: "ABC", order_id: "ORDER-1")
112
+ .and_return(successful_response)
113
+ end
114
+
115
+ it "wraps an Auth response in a SuccessResult" do
116
+ expect(subject).to be_an_instance_of(Affirm::SuccessResult)
117
+ expect(subject.__send__(:object)).to be_an_instance_of(Affirm::Responses::Auth)
118
+ end
119
+ end
120
+ end
121
+
122
+ context "find" do
123
+ context "with failed response" do
124
+ subject { described_class }
125
+
126
+ before do
127
+ expect(Affirm::Client).to receive(:request)
128
+ .with(:get, "transactions/1")
129
+ .and_return(failed_response)
130
+ end
131
+
132
+ it "returns failure object" do
133
+ expect(
134
+ subject.find(1)
135
+ ).to be_an_instance_of(Affirm::FailureResult)
136
+ end
137
+ end
138
+
139
+ context "with successful response" do
140
+ subject { described_class.find("ABC") }
141
+
142
+ let(:body) do
143
+ JSON.load(
144
+ File.read(File.expand_path("../fixtures/auth.json", __FILE__))
145
+ )
146
+ end
147
+
148
+ let(:successful_response) do
149
+ double(:response, success?: true, body: body)
150
+ end
151
+
152
+ before do
153
+ expect(Affirm::Client).to receive(:request)
154
+ .with(:get, "transactions/ABC")
155
+ .and_return(successful_response)
156
+ end
157
+
158
+ it_behaves_like "a transaction object interface"
159
+ end
160
+ end
161
+
162
+ context "capture" do
163
+ context "with failed response" do
164
+ subject { described_class }
165
+
166
+ before do
167
+ expect(Affirm::Client).to receive(:request)
168
+ .with(:post, "transactions/1/capture")
169
+ .and_return(failed_response)
170
+ end
171
+
172
+ it "returns failure object" do
173
+ expect(
174
+ subject.capture(1)
175
+ ).to be_an_instance_of(Affirm::FailureResult)
176
+ end
177
+ end
178
+
179
+ context "with successful response" do
180
+ subject { described_class.capture(1) }
181
+
182
+ let(:body) do
183
+ {
184
+ "id" => "ABC-111",
185
+ "order_id" => "XYZ-999",
186
+ "currency" => "USD",
187
+ "amount" => 100,
188
+ "fee" => 10,
189
+ "created" => Time.local(2015, 1, 1),
190
+ "type" => "capture",
191
+ "reference_id" => "REF-1"
192
+ }
193
+ end
194
+
195
+ let(:successful_response) do
196
+ double(:response, success?: true, body: body)
197
+ end
198
+
199
+ before do
200
+ expect(Affirm::Client).to receive(:request)
201
+ .with(:post, "transactions/1/capture")
202
+ .and_return(successful_response)
203
+ end
204
+
205
+ %w(
206
+ id
207
+ reference_id
208
+ order_id
209
+ currency
210
+ amount
211
+ fee
212
+ type
213
+ ).each do |method|
214
+ it method do
215
+ expect(subject.public_send(method)).to eq(body[method])
216
+ end
217
+ end
218
+
219
+ it "created" do
220
+ expect(to_seconds(subject.created)).to eq(to_seconds(body["created"]))
221
+ end
222
+ end
223
+
224
+ context "with capture options" do
225
+ subject { described_class.capture(1, amount: 100, order_id: "O1") }
226
+
227
+ let(:successful_response) do
228
+ double(:response, success?: true, body: { "type" => "capture", "id" => "CAP-1" })
229
+ end
230
+
231
+ before do
232
+ expect(Affirm::Client).to receive(:request)
233
+ .with(:post, "transactions/1/capture", amount: 100, order_id: "O1")
234
+ .and_return(successful_response)
235
+ end
236
+
237
+ it "returns success" do
238
+ expect(subject).to be_success
239
+ end
240
+ end
241
+ end
242
+
243
+ context "void" do
244
+ context "with failed response" do
245
+ subject { described_class }
246
+
247
+ before do
248
+ expect(Affirm::Client).to receive(:request)
249
+ .with(:post, "transactions/1/void")
250
+ .and_return(failed_response)
251
+ end
252
+
253
+ it "returns failure object" do
254
+ expect(
255
+ subject.void(1)
256
+ ).to be_an_instance_of(Affirm::FailureResult)
257
+ end
258
+ end
259
+
260
+ context "with successful response" do
261
+ subject { described_class.void(1) }
262
+
263
+ let(:body) do
264
+ {
265
+ "id" => "ABC-111",
266
+ "reference_id" => "XYZ-999",
267
+ "created" => Time.local(2015, 1, 1),
268
+ "type" => "void"
269
+ }
270
+ end
271
+
272
+ let(:successful_response) do
273
+ double(:response, success?: true, body: body)
274
+ end
275
+
276
+ before do
277
+ expect(Affirm::Client).to receive(:request)
278
+ .with(:post, "transactions/1/void")
279
+ .and_return(successful_response)
280
+ end
281
+
282
+ %w(
283
+ id
284
+ reference_id
285
+ type
286
+ ).each do |method|
287
+ it method do
288
+ expect(subject.public_send(method)).to eq(body[method])
289
+ end
290
+ end
291
+
292
+ it "created" do
293
+ expect(to_seconds(subject.created)).to eq(to_seconds(body["created"]))
294
+ end
295
+ end
296
+ end
297
+
298
+ context "refund" do
299
+ context "with failed response" do
300
+ subject { described_class }
301
+
302
+ before do
303
+ expect(Affirm::Client).to receive(:request)
304
+ .with(:post, "transactions/1/refund", amount: 50)
305
+ .and_return(failed_response)
306
+ end
307
+
308
+ it "returns failure object" do
309
+ expect(
310
+ subject.refund(1, amount: 50)
311
+ ).to be_an_instance_of(Affirm::FailureResult)
312
+ end
313
+ end
314
+
315
+ context "with successful response" do
316
+ subject { described_class.refund(1, amount: 50) }
317
+
318
+ let(:body) do
319
+ {
320
+ "id" => "ABC-111",
321
+ "reference_id" => "XYZ-999",
322
+ "amount" => 50,
323
+ "fee_refunded" => 0,
324
+ "created" => Time.local(2015, 1, 1),
325
+ "type" => "refund"
326
+ }
327
+ end
328
+
329
+ let(:successful_response) do
330
+ double(:response, success?: true, body: body)
331
+ end
332
+
333
+ before do
334
+ expect(Affirm::Client).to receive(:request)
335
+ .with(:post, "transactions/1/refund", amount: 50)
336
+ .and_return(successful_response)
337
+ end
338
+
339
+ %w(
340
+ id
341
+ reference_id
342
+ amount
343
+ fee_refunded
344
+ type
345
+ ).each do |method|
346
+ it method do
347
+ expect(subject.public_send(method)).to eq(body[method])
348
+ end
349
+ end
350
+
351
+ it "created" do
352
+ expect(to_seconds(subject.created)).to eq(to_seconds(body["created"]))
353
+ end
354
+ end
355
+ end
356
+
357
+ context "update" do
358
+ context "with failed response" do
359
+ subject { described_class }
360
+
361
+ before do
362
+ expect(Affirm::Client).to receive(:request)
363
+ .with(:post, "transactions/1/update",
364
+ order_id: "XYZ-007",
365
+ shipping_carrier: "FedEx",
366
+ shipping_confirmation: "1ZX007")
367
+ .and_return(failed_response)
368
+ end
369
+
370
+ it "returns failure object" do
371
+ expect(
372
+ subject.update(1,
373
+ order_id: "XYZ-007",
374
+ shipping_carrier: "FedEx",
375
+ shipping_confirmation: "1ZX007"
376
+ )
377
+ ).to be_an_instance_of(Affirm::FailureResult)
378
+ end
379
+ end
380
+
381
+ context "with successful response" do
382
+ subject do
383
+ described_class.update(1,
384
+ order_id: "XYZ-007",
385
+ shipping_carrier: "FedEx",
386
+ shipping_confirmation: "1ZX007"
387
+ )
388
+ end
389
+
390
+ let(:body) do
391
+ {
392
+ "id" => "ABC-007",
393
+ "order_id" => "XYZ-007",
394
+ "shipping_carrier" => "FedEx",
395
+ "shipping_confirmation" => "1ZX007",
396
+ "created" => Time.local(2015, 1, 1),
397
+ "type" => "update"
398
+ }
399
+ end
400
+
401
+ let(:successful_response) do
402
+ double(:response, success?: true, body: body)
403
+ end
404
+
405
+ before do
406
+ expect(Affirm::Client).to receive(:request)
407
+ .with(:post, "transactions/1/update",
408
+ order_id: "XYZ-007",
409
+ shipping_carrier: "FedEx",
410
+ shipping_confirmation: "1ZX007"
411
+ )
412
+ .and_return(successful_response)
413
+ end
414
+
415
+ %w(
416
+ id
417
+ order_id
418
+ shipping_carrier
419
+ shipping_confirmation
420
+ type
421
+ ).each do |method|
422
+ it method do
423
+ expect(subject.public_send(method)).to eq(body[method])
424
+ end
425
+ end
426
+
427
+ it "created" do
428
+ expect(to_seconds(subject.created)).to eq(to_seconds(body["created"]))
429
+ end
430
+ end
431
+ end
432
+ end
@@ -0,0 +1,135 @@
1
+ require "helper"
2
+
3
+ RSpec.describe Affirm::Client do
4
+ context "new instance" do
5
+ it "creates Faraday connection" do
6
+ expect(subject.connection).to be_an_instance_of(Faraday::Connection)
7
+ end
8
+ end
9
+
10
+ context ".request" do
11
+ it "dispatches :get to a new instance" do
12
+ instance = instance_double(described_class, get: :ok)
13
+ expect(described_class).to receive(:new).and_return(instance)
14
+ expect(instance).to receive(:get).with("transactions/1", { foo: "bar" }).and_return(:ok)
15
+
16
+ expect(
17
+ described_class.request(:get, "transactions/1", { foo: "bar" })
18
+ ).to eq(:ok)
19
+ end
20
+
21
+ it "dispatches :post to a new instance" do
22
+ instance = instance_double(described_class, post: :ok)
23
+ expect(described_class).to receive(:new).and_return(instance)
24
+ expect(instance).to receive(:post).with("transactions", { transaction_id: "ABC" }).and_return(:ok)
25
+
26
+ expect(
27
+ described_class.request(:post, "transactions", { transaction_id: "ABC" })
28
+ ).to eq(:ok)
29
+ end
30
+
31
+ it "defaults data to an empty hash" do
32
+ instance = instance_double(described_class, get: :ok)
33
+ expect(described_class).to receive(:new).and_return(instance)
34
+ expect(instance).to receive(:get).with("transactions/1", {}).and_return(:ok)
35
+
36
+ described_class.request(:get, "transactions/1")
37
+ end
38
+ end
39
+
40
+ context "with api keys set" do
41
+ before do
42
+ Affirm.configure do |config|
43
+ config.public_api_key = "abc"
44
+ config.private_api_key = "xyz"
45
+ end
46
+ end
47
+
48
+ it "sets json handlers" do
49
+ expect(
50
+ subject.connection.builder.handlers.map(&:klass)
51
+ ).to include(Faraday::Request::Json, Faraday::Response::Json)
52
+ end
53
+
54
+ it "sets basic auth header" do
55
+ stubs = Faraday::Adapter::Test::Stubs.new do |stub|
56
+ stub.get("/api/v1/auth-check") do |env|
57
+ expect(env.request_headers["Authorization"]).to eq("Basic YWJjOnh5eg==")
58
+ [200, {}, ""]
59
+ end
60
+ end
61
+
62
+ subject.connection.builder.handlers.pop
63
+ subject.connection.adapter(:test, stubs)
64
+
65
+ expect(subject.get("auth-check")).to be_success
66
+ stubs.verify_stubbed_calls
67
+ end
68
+ end
69
+
70
+ context "post request" do
71
+ before(:all) do
72
+ @stubs = Faraday::Adapter::Test::Stubs.new do |stub|
73
+ stub.post("/api/v1/foo") { [200, {}, ""] }
74
+ stub.post("/api/v1/bar", '{"key":"value"}') { [200, {}, ""] }
75
+ end
76
+ end
77
+
78
+ after(:all) { @stubs.verify_stubbed_calls }
79
+
80
+ before do
81
+ subject.connection.builder.handlers.pop
82
+ subject.connection.adapter(:test, @stubs)
83
+ end
84
+
85
+ it "makes request to full url" do
86
+ response = subject.post("foo", {})
87
+ expect(response.env.url.to_s).to eq("https://api.affirm.com/api/v1/foo")
88
+ end
89
+
90
+ it "makes request to specified path with no leading slash specified" do
91
+ expect(subject.post("foo")).to be_success
92
+ end
93
+
94
+ it "makes request to specified path with leading slash specified" do
95
+ expect(subject.post("/foo")).to be_success
96
+ end
97
+
98
+ it "makes request with json data" do
99
+ expect(subject.post("/bar", { key: "value" })).to be_success
100
+ end
101
+ end
102
+
103
+ context "get request" do
104
+ before(:all) do
105
+ @stubs = Faraday::Adapter::Test::Stubs.new do |stub|
106
+ stub.get("/api/v1/foo") { [200, {}, ""] }
107
+ stub.get("/api/v1/bar?key=value") { [200, {}, ""] }
108
+ end
109
+ end
110
+
111
+ after(:all) { @stubs.verify_stubbed_calls }
112
+
113
+ before do
114
+ subject.connection.builder.handlers.pop
115
+ subject.connection.adapter(:test, @stubs)
116
+ end
117
+
118
+ it "makes request to full url" do
119
+ response = subject.get("foo", {})
120
+ expect(response.env.url.to_s).to eq("https://api.affirm.com/api/v1/foo")
121
+ end
122
+
123
+ it "makes request to specified path with no leading slash specified" do
124
+ expect(subject.get("foo")).to be_success
125
+ end
126
+
127
+ it "makes request to specified path with leading slash specified" do
128
+ expect(subject.get("/foo")).to be_success
129
+ end
130
+
131
+ it "makes request with params" do
132
+ expect(subject.get("/bar", { key: "value" })).to be_success
133
+ end
134
+ end
135
+ end
@@ -0,0 +1,96 @@
1
+ require "helper"
2
+
3
+ RSpec.describe Affirm::Configuration do
4
+ after { restore_config }
5
+
6
+ context "when public_api_key is specified" do
7
+ before do
8
+ Affirm.configure do |config|
9
+ config.public_api_key = "abc"
10
+ end
11
+ end
12
+
13
+ it "returns public api key" do
14
+ expect(Affirm.configuration.public_api_key).to eq("abc")
15
+ end
16
+ end
17
+
18
+ context "when private_api_key is specified" do
19
+ before do
20
+ Affirm.configure do |config|
21
+ config.private_api_key = "xyz"
22
+ end
23
+ end
24
+
25
+ it "returns private api key" do
26
+ expect(Affirm.configuration.private_api_key).to eq("xyz")
27
+ end
28
+ end
29
+
30
+ context "when environment is not specified" do
31
+ before do
32
+ Affirm.configure {}
33
+ end
34
+
35
+ it "defaults to production" do
36
+ expect(Affirm.configuration.environment).to eq(:production)
37
+ end
38
+ end
39
+
40
+ context "when environment is set to production" do
41
+ before do
42
+ Affirm.configure do |config|
43
+ config.environment = :production
44
+ end
45
+ end
46
+
47
+ it "sets environment to production" do
48
+ expect(Affirm.configuration.environment).to eq(:production)
49
+ end
50
+
51
+ it "sets endpoint to production" do
52
+ expect(Affirm.configuration.endpoint).to eq("https://api.affirm.com")
53
+ end
54
+ end
55
+
56
+ context "when environment is set to sandbox" do
57
+ context "via string" do
58
+ before do
59
+ Affirm.configure do |config|
60
+ config.environment = 'sandbox'
61
+ end
62
+ end
63
+
64
+ it "sets environment to sandbox" do
65
+ expect(Affirm.configuration.environment).to eq(:sandbox)
66
+ end
67
+
68
+ it "sets endpoint to sandbox" do
69
+ expect(Affirm.configuration.endpoint).to eq("https://sandbox.affirm.com")
70
+ end
71
+ end
72
+
73
+ context "via symbol" do
74
+ before do
75
+ Affirm.configure do |config|
76
+ config.environment = :sandbox
77
+ end
78
+ end
79
+
80
+ it "sets environment to sandbox" do
81
+ expect(Affirm.configuration.environment).to eq(:sandbox)
82
+ end
83
+
84
+ it "sets endpoint to sandbox" do
85
+ expect(Affirm.configuration.endpoint).to eq("https://sandbox.affirm.com")
86
+ end
87
+ end
88
+ end
89
+
90
+ private
91
+
92
+ def restore_config
93
+ Affirm.configuration = nil
94
+ Affirm.configure {}
95
+ end
96
+ end