fake_braintree 0.0.5 → 0.0.6
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.
- data/.travis.yml +5 -0
- data/Changelog.md +7 -0
- data/README.md +103 -6
- data/Rakefile +2 -2
- data/fake_braintree.gemspec +6 -1
- data/lib/fake_braintree.rb +49 -10
- data/lib/fake_braintree/customer.rb +81 -25
- data/lib/fake_braintree/helpers.rb +4 -0
- data/lib/fake_braintree/redirect.rb +37 -0
- data/lib/fake_braintree/sinatra_app.rb +48 -15
- data/lib/fake_braintree/subscription.rb +62 -11
- data/lib/fake_braintree/version.rb +1 -1
- data/spec/fake_braintree/credit_card_spec.rb +8 -15
- data/spec/fake_braintree/customer_spec.rb +56 -48
- data/spec/fake_braintree/subscription_spec.rb +67 -41
- data/spec/fake_braintree/transaction_spec.rb +44 -0
- data/spec/fake_braintree/transparent_redirect_spec.rb +76 -0
- data/spec/fake_braintree_spec.rb +79 -26
- data/spec/spec_helper.rb +26 -11
- data/spec/support/braintree_helpers.rb +8 -4
- data/spec/support/customer_helpers.rb +12 -0
- data/spec/support/subscription_helpers.rb +6 -0
- metadata +89 -18
@@ -11,14 +11,9 @@ module FakeBraintree
|
|
11
11
|
|
12
12
|
# Braintree::Customer.create
|
13
13
|
post "/merchants/:merchant_id/customers" do
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
else
|
18
|
-
customer_hash = customer.customer_hash
|
19
|
-
FakeBraintree.customers[customer_hash["id"]] = customer_hash
|
20
|
-
gzipped_response(201, customer_hash.to_xml(:root => 'customer'))
|
21
|
-
end
|
14
|
+
customer_hash = Hash.from_xml(request.body).delete("customer")
|
15
|
+
options = {:merchant_id => params[:merchant_id]}
|
16
|
+
Customer.new(customer_hash, options).create
|
22
17
|
end
|
23
18
|
|
24
19
|
# Braintree::Customer.find
|
@@ -31,12 +26,25 @@ module FakeBraintree
|
|
31
26
|
end
|
32
27
|
end
|
33
28
|
|
29
|
+
# Braintree::Customer.update
|
30
|
+
put "/merchants/:merchant_id/customers/:id" do
|
31
|
+
customer_hash = Hash.from_xml(request.body).delete("customer")
|
32
|
+
options = {:id => params[:id], :merchant_id => params[:merchant_id]}
|
33
|
+
Customer.new(customer_hash, options).update
|
34
|
+
end
|
35
|
+
|
36
|
+
# Braintree::Customer.delete
|
37
|
+
delete "/merchants/:merchant_id/customers/:id" do
|
38
|
+
customer_hash = {}
|
39
|
+
options = {:id => params[:id], :merchant_id => params[:merchant_id]}
|
40
|
+
Customer.new(customer_hash, options).delete
|
41
|
+
end
|
42
|
+
|
34
43
|
# Braintree::Subscription.create
|
35
44
|
post "/merchants/:merchant_id/subscriptions" do
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
gzipped_response(201, response_hash.to_xml(:root => 'subscription'))
|
45
|
+
subscription_hash = Hash.from_xml(request.body).delete("subscription")
|
46
|
+
options = {:merchant_id => params[:merchant_id]}
|
47
|
+
Subscription.new(subscription_hash, options).create
|
40
48
|
end
|
41
49
|
|
42
50
|
# Braintree::Subscription.find
|
@@ -49,6 +57,13 @@ module FakeBraintree
|
|
49
57
|
end
|
50
58
|
end
|
51
59
|
|
60
|
+
# Braintree::Subscription.update
|
61
|
+
put "/merchants/:merchant_id/subscriptions/:id" do
|
62
|
+
subscription_hash = Hash.from_xml(request.body).delete("subscription")
|
63
|
+
options = {:id => params[:id], :merchant_id => params[:merchant_id]}
|
64
|
+
Subscription.new(subscription_hash, options).update
|
65
|
+
end
|
66
|
+
|
52
67
|
# Braintree::CreditCard.find
|
53
68
|
get "/merchants/:merchant_id/payment_methods/:credit_card_token" do
|
54
69
|
credit_card = FakeBraintree.credit_card_from_token(params[:credit_card_token])
|
@@ -64,18 +79,36 @@ module FakeBraintree
|
|
64
79
|
transaction = Hash.from_xml(request.body)["transaction"]
|
65
80
|
transaction_id = md5("#{params[:merchant_id]}#{Time.now.to_f}")
|
66
81
|
transaction_response = {"id" => transaction_id, "amount" => transaction["amount"]}
|
67
|
-
FakeBraintree.
|
82
|
+
FakeBraintree.transactions[transaction_id] = transaction_response
|
68
83
|
gzipped_response(200, transaction_response.to_xml(:root => "transaction"))
|
69
84
|
end
|
70
85
|
end
|
71
86
|
|
72
87
|
# Braintree::Transaction.find
|
73
88
|
get "/merchants/:merchant_id/transactions/:transaction_id" do
|
74
|
-
|
75
|
-
|
89
|
+
transaction = FakeBraintree.transactions[params[:transaction_id]]
|
90
|
+
if transaction
|
91
|
+
gzipped_response(200, transaction.to_xml(:root => "transaction"))
|
76
92
|
else
|
77
93
|
gzipped_response(404, {})
|
78
94
|
end
|
79
95
|
end
|
96
|
+
|
97
|
+
# Braintree::TransparentRedirect.url
|
98
|
+
post "/merchants/:merchant_id/transparent_redirect_requests" do
|
99
|
+
if params[:tr_data]
|
100
|
+
redirect = Redirect.new(params, params[:merchant_id])
|
101
|
+
FakeBraintree.redirects[redirect.id] = redirect
|
102
|
+
redirect to(redirect.url), 303
|
103
|
+
else
|
104
|
+
[422, { "Content-Type" => "text/html" }, ["Invalid submission"]]
|
105
|
+
end
|
106
|
+
end
|
107
|
+
|
108
|
+
# Braintree::TransparentRedirect.confirm
|
109
|
+
post "/merchants/:merchant_id/transparent_redirect_requests/:id/confirm" do
|
110
|
+
redirect = FakeBraintree.redirects[params[:id]]
|
111
|
+
redirect.confirm
|
112
|
+
end
|
80
113
|
end
|
81
114
|
end
|
@@ -2,20 +2,71 @@ module FakeBraintree
|
|
2
2
|
class Subscription
|
3
3
|
include Helpers
|
4
4
|
|
5
|
-
def initialize(
|
6
|
-
@subscription_hash =
|
5
|
+
def initialize(subscription_hash, options)
|
6
|
+
@subscription_hash = subscription_hash.merge("merchant_id" => options[:merchant_id],
|
7
|
+
"id" => options[:id])
|
7
8
|
end
|
8
9
|
|
9
|
-
def
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
10
|
+
def create
|
11
|
+
hash = subscription_hash
|
12
|
+
FakeBraintree.subscriptions[hash["id"]] = hash
|
13
|
+
gzipped_response(201, hash.to_xml(:root => 'subscription'))
|
14
|
+
end
|
15
|
+
|
16
|
+
def update
|
17
|
+
if existing_subscription_hash
|
18
|
+
hash = update_existing_subscription!
|
19
|
+
gzipped_response(200, hash.to_xml(:root => 'subscription'))
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
def subscription_hash
|
24
|
+
subscription_hash = @subscription_hash.dup
|
25
|
+
subscription_hash["id"] ||= subscription_id
|
26
|
+
subscription_hash["transactions"] = []
|
27
|
+
subscription_hash["add_ons"] = added_add_ons
|
28
|
+
subscription_hash["discounts"] = added_discounts
|
29
|
+
subscription_hash["plan_id"] = @subscription_hash["plan_id"]
|
30
|
+
subscription_hash["next_billing_date"] = braintree_formatted_date(1.month.from_now)
|
31
|
+
subscription_hash["payment_method_token"] = @subscription_hash["payment_method_token"]
|
32
|
+
subscription_hash["status"] = Braintree::Subscription::Status::Active
|
33
|
+
|
34
|
+
subscription_hash
|
35
|
+
end
|
36
|
+
|
37
|
+
private
|
38
|
+
|
39
|
+
def existing_subscription_hash
|
40
|
+
@subscription_hash['id'] && FakeBraintree.subscriptions[@subscription_hash["id"]]
|
41
|
+
end
|
42
|
+
|
43
|
+
def update_existing_subscription!
|
44
|
+
new_hash = existing_subscription_hash.merge(subscription_hash)
|
45
|
+
FakeBraintree.subscriptions[@subscription_hash['id']] = new_hash
|
46
|
+
end
|
47
|
+
|
48
|
+
def braintree_formatted_date(date)
|
49
|
+
date.strftime('%Y-%m-%d')
|
50
|
+
end
|
51
|
+
|
52
|
+
def subscription_id
|
53
|
+
md5("#{@subscription_hash["payment_method_token"]}#{Time.now.to_f}")[0,6]
|
54
|
+
end
|
55
|
+
|
56
|
+
def added_add_ons
|
57
|
+
if @subscription_hash["add_ons"] && @subscription_hash["add_ons"]["add"]
|
58
|
+
@subscription_hash["add_ons"]["add"].map { |add_on| { "id" => add_on["inherited_from_id"] } }
|
59
|
+
else
|
60
|
+
[]
|
61
|
+
end
|
62
|
+
end
|
17
63
|
|
18
|
-
|
64
|
+
def added_discounts
|
65
|
+
if @subscription_hash["discounts"] && @subscription_hash["discounts"]["add"]
|
66
|
+
@subscription_hash["discounts"]["add"].map { |discount| { "id" => discount["inherited_from_id"] } }
|
67
|
+
else
|
68
|
+
[]
|
69
|
+
end
|
19
70
|
end
|
20
71
|
end
|
21
72
|
end
|
@@ -2,31 +2,24 @@ require 'spec_helper'
|
|
2
2
|
|
3
3
|
describe FakeBraintree::SinatraApp do
|
4
4
|
context "Braintree::CreditCard.find" do
|
5
|
-
let(:cc_number) { %w(4111 1111 1111 9876).join }
|
6
|
-
let(:expiration_date) { "04/2016" }
|
7
|
-
let(:token) { braintree_credit_card_token(cc_number, expiration_date) }
|
8
|
-
|
9
5
|
it "gets the correct credit card" do
|
10
6
|
credit_card = Braintree::CreditCard.find(token)
|
11
7
|
|
12
|
-
credit_card.last_4.should ==
|
13
|
-
credit_card.
|
14
|
-
credit_card.
|
8
|
+
credit_card.last_4.should == TEST_CC_NUMBER[-4,4]
|
9
|
+
credit_card.expiration_month.should == month
|
10
|
+
credit_card.expiration_year.should == year
|
15
11
|
end
|
12
|
+
|
13
|
+
let(:month) { '04' }
|
14
|
+
let(:year) { '2016' }
|
15
|
+
let(:token) { braintree_credit_card_token(TEST_CC_NUMBER, [month, year].join('/')) }
|
16
16
|
end
|
17
17
|
|
18
18
|
context "Braintree::CreditCard.sale" do
|
19
|
-
let(:cc_number) { %w(4111 1111 1111 9876).join }
|
20
|
-
let(:expiration_date) { "04/2016" }
|
21
|
-
let(:token) { braintree_credit_card_token(cc_number, expiration_date) }
|
22
|
-
let(:amount) { 10.00 }
|
23
|
-
|
24
19
|
it "successfully creates a sale" do
|
25
|
-
result = Braintree::CreditCard.sale(
|
20
|
+
result = Braintree::CreditCard.sale(cc_token, :amount => 10.00)
|
26
21
|
result.should be_success
|
27
|
-
|
28
22
|
Braintree::Transaction.find(result.transaction.id).should be
|
29
|
-
lambda { Braintree::Transaction.find("foo") }.should raise_error(Braintree::NotFoundError)
|
30
23
|
end
|
31
24
|
end
|
32
25
|
end
|
@@ -1,24 +1,28 @@
|
|
1
1
|
require 'spec_helper'
|
2
2
|
|
3
3
|
describe "Braintree::Customer.create" do
|
4
|
-
let(:cc_number) { %w(4111 1111 1111 1111).join }
|
5
|
-
let(:expiration_date) { "04/2016" }
|
6
4
|
after { FakeBraintree.verify_all_cards = false }
|
7
5
|
|
8
|
-
|
9
|
-
Braintree::Customer.create(:credit_card =>
|
6
|
+
it "successfully creates a customer" do
|
7
|
+
result = Braintree::Customer.create(:credit_card => { :number => TEST_CC_NUMBER,
|
8
|
+
:expiration_date => '04/2016'})
|
9
|
+
result.should be_success
|
10
10
|
end
|
11
11
|
|
12
|
-
it "
|
13
|
-
result =
|
14
|
-
|
12
|
+
it "can handle an empty credit card hash" do
|
13
|
+
result = Braintree::Customer.create(:credit_card => {})
|
14
|
+
result.should be_success
|
15
|
+
end
|
16
|
+
|
17
|
+
it "creates a customer using an expiration month and year" do
|
18
|
+
result = Braintree::Customer.create(:credit_card => { :number => TEST_CC_NUMBER,
|
19
|
+
:expiration_month => '04',
|
20
|
+
:expiration_year => '2016'})
|
15
21
|
result.should be_success
|
16
22
|
end
|
17
23
|
|
18
24
|
it "records the billing address" do
|
19
|
-
result =
|
20
|
-
:number => cc_number,
|
21
|
-
:expiration_date => expiration_date,
|
25
|
+
result = create_customer(
|
22
26
|
:billing_address => {
|
23
27
|
:street_address => "1 E Main St",
|
24
28
|
:extended_address => "Suite 3",
|
@@ -34,54 +38,34 @@ describe "Braintree::Customer.create" do
|
|
34
38
|
billing_address.street_address.should == "1 E Main St"
|
35
39
|
billing_address.postal_code.should == "60622"
|
36
40
|
end
|
41
|
+
end
|
37
42
|
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
:number => cc_number,
|
42
|
-
:expiration_date => expiration_date,
|
43
|
-
:options => { :verify_card => true }
|
44
|
-
).should be_success
|
45
|
-
end
|
46
|
-
|
47
|
-
it "rejects invalid cards" do
|
48
|
-
create_customer_with_credit_card(
|
49
|
-
:number => '123456',
|
50
|
-
:expiration_date => expiration_date,
|
51
|
-
:options => { :verify_card => true }
|
52
|
-
).should_not be_success
|
53
|
-
end
|
43
|
+
describe "Braintree::Customer.create", "when passed :verify_card => true" do
|
44
|
+
it "accepts valid cards" do
|
45
|
+
create_customer(:options => { :verify_card => true }).should be_success
|
54
46
|
end
|
55
47
|
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
it "accepts valid cards" do
|
60
|
-
create_customer_with_credit_card(
|
61
|
-
:number => cc_number,
|
62
|
-
:expiration_date => expiration_date
|
63
|
-
).should be_success
|
64
|
-
end
|
65
|
-
|
66
|
-
it "rejects invalid cards" do
|
67
|
-
create_customer_with_credit_card(
|
68
|
-
:number => '123456',
|
69
|
-
:expiration_date => expiration_date
|
70
|
-
).should_not be_success
|
71
|
-
end
|
48
|
+
it "rejects invalid cards" do
|
49
|
+
create_customer_with_invalid_card(:options => { :verify_card => true }).should_not be_success
|
72
50
|
end
|
73
51
|
end
|
74
52
|
|
75
|
-
describe "Braintree::Customer.
|
76
|
-
|
77
|
-
|
53
|
+
describe "Braintree::Customer.create", "when FakeBraintree.verify_all_cards == true" do
|
54
|
+
before { FakeBraintree.verify_all_cards! }
|
55
|
+
|
56
|
+
it "accepts valid cards" do
|
57
|
+
create_customer.should be_success
|
58
|
+
end
|
78
59
|
|
79
|
-
|
80
|
-
|
60
|
+
it "rejects invalid cards" do
|
61
|
+
create_customer_with_invalid_card.should_not be_success
|
81
62
|
end
|
63
|
+
end
|
82
64
|
|
65
|
+
describe "Braintree::Customer.find" do
|
83
66
|
it "successfully finds a customer" do
|
84
|
-
result = Braintree::Customer.create(:first_name => "Bob",
|
67
|
+
result = Braintree::Customer.create(:first_name => "Bob",
|
68
|
+
:last_name => "Smith")
|
85
69
|
|
86
70
|
Braintree::Customer.find(result.customer.id).first_name.should == "Bob"
|
87
71
|
end
|
@@ -90,3 +74,27 @@ describe "Braintree::Customer.find" do
|
|
90
74
|
lambda { Braintree::Customer.find("foo") }.should raise_error(Braintree::NotFoundError)
|
91
75
|
end
|
92
76
|
end
|
77
|
+
|
78
|
+
describe "Braintree::Customer.update" do
|
79
|
+
it "successfully updates a customer" do
|
80
|
+
customer_id = create_customer.customer.id
|
81
|
+
result = Braintree::Customer.update(customer_id, :first_name => "Jerry")
|
82
|
+
|
83
|
+
result.should be_success
|
84
|
+
Braintree::Customer.find(customer_id).first_name.should == "Jerry"
|
85
|
+
end
|
86
|
+
|
87
|
+
it "raises an error for a nonexistent customer" do
|
88
|
+
lambda { Braintree::Customer.update("foo", {:first_name => "Bob"}) }.should raise_error(Braintree::NotFoundError)
|
89
|
+
end
|
90
|
+
end
|
91
|
+
|
92
|
+
describe "Braintree::Customer.delete" do
|
93
|
+
it "successfully deletes a customer" do
|
94
|
+
customer_id = create_customer.customer.id
|
95
|
+
result = Braintree::Customer.delete(customer_id)
|
96
|
+
|
97
|
+
result.should be_success
|
98
|
+
expect { Braintree::Customer.find(customer_id) }.to raise_error(Braintree::NotFoundError)
|
99
|
+
end
|
100
|
+
end
|
@@ -1,56 +1,82 @@
|
|
1
1
|
require 'spec_helper'
|
2
2
|
|
3
|
-
describe
|
4
|
-
|
5
|
-
|
6
|
-
let(:cc_number) { %w(4111 1111 1111 9876).join }
|
7
|
-
let(:expiration_date) { "04/2016" }
|
8
|
-
let(:payment_method_token) { braintree_credit_card_token(cc_number, expiration_date) }
|
9
|
-
let(:payment_method_token_2) { braintree_credit_card_token(cc_number.sub('1', '5'), expiration_date) }
|
10
|
-
|
11
|
-
it "successfully creates a subscription" do
|
12
|
-
result = Braintree::Subscription.create(:payment_method_token => payment_method_token,
|
13
|
-
:plan_id => plan_id)
|
14
|
-
result.should be_success
|
15
|
-
end
|
3
|
+
describe "Braintree::Subscription.create" do
|
4
|
+
let(:plan_id) { 'plan-id-from-braintree-control-panel' }
|
5
|
+
let(:expiration_date) { "04/2016" }
|
16
6
|
|
17
|
-
|
18
|
-
|
19
|
-
|
7
|
+
it "successfully creates a subscription" do
|
8
|
+
Braintree::Subscription.create(:payment_method_token => cc_token,
|
9
|
+
:plan_id => 'my_plan_id').should be_success
|
10
|
+
end
|
20
11
|
|
21
|
-
|
22
|
-
|
12
|
+
it "assigns a Braintree-esque ID to the subscription" do
|
13
|
+
create_subscription.subscription.id.should =~ /^[a-z0-9]{6}$/
|
14
|
+
end
|
23
15
|
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
16
|
+
it "assigns unique IDs to each subscription" do
|
17
|
+
cc_token_1 = cc_token
|
18
|
+
cc_token_2 = braintree_credit_card_token(TEST_CC_NUMBER.sub('1', '5'), expiration_date)
|
19
|
+
first_result = Braintree::Subscription.create(:payment_method_token => cc_token_1,
|
20
|
+
:plan_id => plan_id)
|
21
|
+
second_result = Braintree::Subscription.create(:payment_method_token => cc_token_2,
|
22
|
+
:plan_id => plan_id)
|
29
23
|
|
30
|
-
|
31
|
-
|
24
|
+
first_result.subscription.id.should_not == second_result.subscription.id
|
25
|
+
end
|
32
26
|
|
33
|
-
|
34
|
-
|
35
|
-
|
27
|
+
it "stores created subscriptions in FakeBraintree.subscriptions" do
|
28
|
+
FakeBraintree.subscriptions[create_subscription.subscription.id].should_not be_nil
|
29
|
+
end
|
36
30
|
|
37
|
-
|
31
|
+
it "sets the next billing date to a string of 1.month.from_now in UTC" do
|
32
|
+
Timecop.freeze do
|
33
|
+
create_subscription.subscription.next_billing_date.should == 1.month.from_now.utc.strftime('%Y-%m-%d')
|
38
34
|
end
|
39
35
|
end
|
36
|
+
end
|
37
|
+
|
38
|
+
describe "Braintree::Subscription.find" do
|
39
|
+
it "can find a created subscription" do
|
40
|
+
payment_method_token = cc_token
|
41
|
+
plan_id = "abc123"
|
42
|
+
subscription_id =
|
43
|
+
create_subscription(:payment_method_token => payment_method_token, :plan_id => plan_id).subscription.id
|
44
|
+
subscription = Braintree::Subscription.find(subscription_id)
|
45
|
+
subscription.should_not be_nil
|
46
|
+
subscription.payment_method_token.should == payment_method_token
|
47
|
+
subscription.plan_id.should == plan_id
|
48
|
+
end
|
40
49
|
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
let(:subscription_result) { Braintree::Subscription.create(:payment_method_token => payment_method_token,
|
46
|
-
:plan_id => 'my-plan-id') }
|
50
|
+
it "raises a Braintree:NotFoundError when it cannot find a subscription" do
|
51
|
+
create_subscription
|
52
|
+
expect { Braintree::Subscription.find('abc123') }.to raise_error(Braintree::NotFoundError, /abc123/)
|
53
|
+
end
|
47
54
|
|
48
|
-
|
49
|
-
|
50
|
-
|
55
|
+
it "returns add-ons added with the subscription" do
|
56
|
+
add_on_id = "def456"
|
57
|
+
subscription_id = create_subscription(:add_ons => { :add => [{ :inherited_from_id => add_on_id }] }).subscription.id
|
58
|
+
subscription = Braintree::Subscription.find(subscription_id)
|
59
|
+
add_ons = subscription.add_ons
|
60
|
+
add_ons.size.should == 1
|
61
|
+
add_ons.first.id.should == add_on_id
|
62
|
+
end
|
51
63
|
|
52
|
-
|
53
|
-
|
54
|
-
|
64
|
+
it "returns discounts added with the subscription" do
|
65
|
+
discount_id = "def456"
|
66
|
+
subscription_id = create_subscription(:discounts => { :add => [{ :inherited_from_id => discount_id, :amount => BigDecimal.new("15.00") }]}).subscription.id
|
67
|
+
subscription = Braintree::Subscription.find(subscription_id)
|
68
|
+
discounts = subscription.discounts
|
69
|
+
discounts.size.should == 1
|
70
|
+
discounts.first.id.should == discount_id
|
55
71
|
end
|
56
72
|
end
|
73
|
+
|
74
|
+
describe "Braintree::Subscription.update" do
|
75
|
+
it "can update a subscription" do
|
76
|
+
Braintree::Subscription.update(subscription_id, :plan_id => 'a_new_plan')
|
77
|
+
Braintree::Subscription.find(subscription_id).plan_id.should == 'a_new_plan'
|
78
|
+
end
|
79
|
+
|
80
|
+
let(:subscription_id) { subscription.subscription.id }
|
81
|
+
let(:subscription) { create_subscription }
|
82
|
+
end
|