fake_braintree 0.0.2
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +5 -0
- data/Gemfile +4 -0
- data/README.md +6 -0
- data/Rakefile +8 -0
- data/fake_braintree.gemspec +27 -0
- data/lib/fake_braintree.rb +163 -0
- data/lib/fake_braintree/sinatra_app.rb +147 -0
- data/lib/fake_braintree/version.rb +3 -0
- data/spec/fake_braintree/sinatra_app_spec.rb +32 -0
- data/spec/fake_braintree_spec.rb +65 -0
- data/spec/spec_helper.rb +16 -0
- data/spec/support/braintree_helpers.rb +15 -0
- metadata +139 -0
data/Gemfile
ADDED
data/README.md
ADDED
data/Rakefile
ADDED
@@ -0,0 +1,27 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
$:.push File.expand_path("../lib", __FILE__)
|
3
|
+
require "fake_braintree/version"
|
4
|
+
|
5
|
+
Gem::Specification.new do |s|
|
6
|
+
s.name = "fake_braintree"
|
7
|
+
s.version = FakeBraintree::VERSION
|
8
|
+
s.authors = ["thoughtbot, inc."]
|
9
|
+
s.email = ["gabe@thoughtbot.com", "ben@thoughtbot.com"]
|
10
|
+
s.homepage = ""
|
11
|
+
s.summary = %q{A fake Braintree that you can run integration tests against}
|
12
|
+
s.description = %q{A fake Braintree that you can run integration tests against}
|
13
|
+
|
14
|
+
s.files = `git ls-files`.split("\n")
|
15
|
+
s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
|
16
|
+
s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
|
17
|
+
s.require_paths = ["lib"]
|
18
|
+
|
19
|
+
s.add_dependency 'sham_rack'
|
20
|
+
s.add_dependency 'activesupport'
|
21
|
+
s.add_dependency 'i18n'
|
22
|
+
s.add_dependency 'sinatra'
|
23
|
+
s.add_dependency 'braintree', '~> 2.5'
|
24
|
+
|
25
|
+
s.add_development_dependency 'rspec', '~> 2.6.0'
|
26
|
+
s.add_development_dependency 'mocha', '~> 0.9.12'
|
27
|
+
end
|
@@ -0,0 +1,163 @@
|
|
1
|
+
require 'braintree'
|
2
|
+
require 'sham_rack'
|
3
|
+
|
4
|
+
require 'fake_braintree/sinatra_app'
|
5
|
+
require 'fake_braintree/version'
|
6
|
+
|
7
|
+
Braintree::Configuration.logger = Logger.new("tmp/log")
|
8
|
+
|
9
|
+
module FakeBraintree
|
10
|
+
class << self
|
11
|
+
@customers = {}
|
12
|
+
@subscriptions = {}
|
13
|
+
@failures = {}
|
14
|
+
@transaction = {}
|
15
|
+
|
16
|
+
@decline_all_cards = false
|
17
|
+
attr_accessor :customers, :subscriptions, :failures, :transaction, :decline_all_cards
|
18
|
+
end
|
19
|
+
|
20
|
+
def self.activate!
|
21
|
+
Braintree::Configuration.environment = :production
|
22
|
+
Braintree::Configuration.merchant_id = "xxx"
|
23
|
+
Braintree::Configuration.public_key = "xxx"
|
24
|
+
Braintree::Configuration.private_key = "xxx"
|
25
|
+
clear!
|
26
|
+
ShamRack.mount(FakeBraintree::SinatraApp, "www.braintreegateway.com", 443)
|
27
|
+
end
|
28
|
+
|
29
|
+
def self.clear!
|
30
|
+
self.customers = {}
|
31
|
+
self.subscriptions = {}
|
32
|
+
self.failures = {}
|
33
|
+
self.transaction = {}
|
34
|
+
self.decline_all_cards = false
|
35
|
+
end
|
36
|
+
|
37
|
+
def self.failure?(card_number)
|
38
|
+
self.failures.include?(card_number)
|
39
|
+
end
|
40
|
+
|
41
|
+
def self.failure_response(card_number)
|
42
|
+
failure = self.failures[card_number]
|
43
|
+
failure["errors"] ||= { "errors" => [] }
|
44
|
+
|
45
|
+
{ "message" => failure["message"],
|
46
|
+
"verification" => { "status" => failure["status"],
|
47
|
+
"processor_response_text" => failure["message"],
|
48
|
+
"processor_response_code" => failure["code"],
|
49
|
+
"gateway_rejection_reason" => "cvv",
|
50
|
+
"cvv_response_code" => failure["code"] },
|
51
|
+
"errors" => failure["errors"],
|
52
|
+
"params" => {}}
|
53
|
+
end
|
54
|
+
|
55
|
+
def self.create_failure
|
56
|
+
{ "message" => "Do Not Honor",
|
57
|
+
"verification" => { "status" => "processor_declined",
|
58
|
+
"processor_response_text" => "Do Not Honor",
|
59
|
+
"processor_response_code" => '2000' },
|
60
|
+
"errors" => { 'errors' => [] },
|
61
|
+
"params" => {} }
|
62
|
+
end
|
63
|
+
|
64
|
+
def self.decline_all_cards!
|
65
|
+
self.decline_all_cards = true
|
66
|
+
end
|
67
|
+
|
68
|
+
def self.decline_all_cards?
|
69
|
+
self.decline_all_cards
|
70
|
+
end
|
71
|
+
|
72
|
+
def self.credit_card_from_token(token)
|
73
|
+
self.customers.values.detect do |customer|
|
74
|
+
next unless customer.key?("credit_cards")
|
75
|
+
|
76
|
+
card = customer["credit_cards"].detect {|card| card["token"] == token }
|
77
|
+
return card if card
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
81
|
+
def self.generated_transaction
|
82
|
+
{"status_history"=>[{"timestamp"=>Time.now,
|
83
|
+
"amount"=>FakeBraintree.transaction[:amount],
|
84
|
+
"transaction_source"=>"CP",
|
85
|
+
"user"=>"copycopter",
|
86
|
+
"status"=>"authorized"},
|
87
|
+
{"timestamp"=>Time.now,
|
88
|
+
"amount"=>FakeBraintree.transaction[:amount],
|
89
|
+
"transaction_source"=>"CP",
|
90
|
+
"user"=>"copycopter",
|
91
|
+
"status"=>FakeBraintree.transaction[:status]}],
|
92
|
+
"created_at"=>(FakeBraintree.transaction[:created_at] || Time.now),
|
93
|
+
"currency_iso_code"=>"USD",
|
94
|
+
"settlement_batch_id"=>nil,
|
95
|
+
"processor_authorization_code"=>"ZKB4VJ",
|
96
|
+
"avs_postal_code_response_code"=>"I",
|
97
|
+
"order_id"=>nil,
|
98
|
+
"updated_at"=>Time.now,
|
99
|
+
"refunded_transaction_id"=>nil,
|
100
|
+
"amount"=>FakeBraintree.transaction[:amount],
|
101
|
+
"credit_card"=>{"last_4"=>"1111",
|
102
|
+
"card_type"=>"Visa",
|
103
|
+
"token"=>"8yq7",
|
104
|
+
"customer_location"=>"US",
|
105
|
+
"expiration_year"=>"2013",
|
106
|
+
"expiration_month"=>"02",
|
107
|
+
"bin"=>"411111",
|
108
|
+
"cardholder_name"=>"Chad Lee Pytel"
|
109
|
+
},
|
110
|
+
"refund_id"=>nil,
|
111
|
+
"add_ons"=>[],
|
112
|
+
"shipping"=>{"region"=>nil,
|
113
|
+
"company"=>nil,
|
114
|
+
"country_name"=>nil,
|
115
|
+
"extended_address"=>nil,
|
116
|
+
"postal_code"=>nil,
|
117
|
+
"id"=>nil,
|
118
|
+
"street_address"=>nil,
|
119
|
+
"country_code_numeric"=>nil,
|
120
|
+
"last_name"=>nil,
|
121
|
+
"locality"=>nil,
|
122
|
+
"country_code_alpha2"=>nil,
|
123
|
+
"country_code_alpha3"=>nil,
|
124
|
+
"first_name"=>nil},
|
125
|
+
"id"=>"49sbx6",
|
126
|
+
"merchant_account_id"=>"Thoughtbot",
|
127
|
+
"type"=>"sale",
|
128
|
+
"cvv_response_code"=>"I",
|
129
|
+
"subscription_id"=>FakeBraintree.transaction[:subscription_id],
|
130
|
+
"custom_fields"=>"\n",
|
131
|
+
"discounts"=>[],
|
132
|
+
"billing"=>{"region"=>nil,
|
133
|
+
"company"=>nil,
|
134
|
+
"country_name"=>nil,
|
135
|
+
"extended_address"=>nil,
|
136
|
+
"postal_code"=>nil,
|
137
|
+
"id"=>nil,
|
138
|
+
"street_address"=>nil,
|
139
|
+
"country_code_numeric"=>nil,
|
140
|
+
"last_name"=>nil,
|
141
|
+
"locality"=>nil,
|
142
|
+
"country_code_alpha2"=>nil,
|
143
|
+
"country_code_alpha3"=>nil,
|
144
|
+
"first_name"=>nil},
|
145
|
+
"processor_response_code"=>"1000",
|
146
|
+
"refund_ids"=>[],
|
147
|
+
"customer"=>{"company"=>nil,
|
148
|
+
"id"=>"108427",
|
149
|
+
"last_name"=>nil,
|
150
|
+
"fax"=>nil,
|
151
|
+
"phone"=>nil,
|
152
|
+
"website"=>nil,
|
153
|
+
"first_name"=>nil,
|
154
|
+
"email"=>"cpytel@thoughtbot.com" },
|
155
|
+
"avs_error_response_code"=>nil,
|
156
|
+
"processor_response_text"=>"Approved",
|
157
|
+
"avs_street_address_response_code"=>"I",
|
158
|
+
"status"=>FakeBraintree.transaction[:status],
|
159
|
+
"gateway_rejection_reason"=>nil}
|
160
|
+
end
|
161
|
+
end
|
162
|
+
|
163
|
+
FakeBraintree.activate!
|
@@ -0,0 +1,147 @@
|
|
1
|
+
require 'digest/md5'
|
2
|
+
require 'sinatra'
|
3
|
+
require 'active_support'
|
4
|
+
require 'active_support/core_ext'
|
5
|
+
|
6
|
+
module FakeBraintree
|
7
|
+
class SinatraApp < Sinatra::Base
|
8
|
+
set :show_exceptions, false
|
9
|
+
set :dump_errors, true
|
10
|
+
set :raise_errors, true
|
11
|
+
disable :logging
|
12
|
+
|
13
|
+
helpers do
|
14
|
+
def gzip(content)
|
15
|
+
ActiveSupport::Gzip.compress(content)
|
16
|
+
end
|
17
|
+
|
18
|
+
def gzipped_response(status_code, uncompressed_content)
|
19
|
+
[status_code, { "Content-Encoding" => "gzip" }, gzip(uncompressed_content)]
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
post "/merchants/:merchant_id/customers" do
|
24
|
+
customer = Hash.from_xml(request.body).delete("customer")
|
25
|
+
if FakeBraintree.failure?(customer["credit_card"]["number"])
|
26
|
+
gzipped_response(422, FakeBraintree.failure_response(customer["credit_card"]["number"]).to_xml(:root => 'api_error_response'))
|
27
|
+
else
|
28
|
+
customer["id"] ||= Digest::MD5.hexdigest("#{params[:merchant_id]}#{Time.now.to_f}")
|
29
|
+
customer["merchant-id"] = params[:merchant_id]
|
30
|
+
if customer["credit_card"] && customer["credit_card"].is_a?(Hash)
|
31
|
+
customer["credit_card"].delete("__content__")
|
32
|
+
if !customer["credit_card"].empty?
|
33
|
+
customer["credit_card"]["last_4"] = customer["credit_card"].delete("number")[-4..-1]
|
34
|
+
customer["credit_card"]["token"] = Digest::MD5.hexdigest("#{customer['merchant_id']}#{customer['id']}#{Time.now.to_f}")
|
35
|
+
expiration_date = customer["credit_card"].delete("expiration_date")
|
36
|
+
customer["credit_card"]["expiration_month"] = expiration_date.split('/')[0]
|
37
|
+
customer["credit_card"]["expiration_year"] = expiration_date.split('/')[1]
|
38
|
+
|
39
|
+
credit_card = customer.delete("credit_card")
|
40
|
+
customer["credit_cards"] = [credit_card]
|
41
|
+
end
|
42
|
+
end
|
43
|
+
FakeBraintree.customers[customer["id"]] = customer
|
44
|
+
gzipped_response(201, customer.to_xml(:root => 'customer'))
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
get "/merchants/:merchant_id/customers/:id" do
|
49
|
+
customer = FakeBraintree.customers[params[:id]]
|
50
|
+
gzipped_response(200, customer.to_xml(:root => 'customer'))
|
51
|
+
end
|
52
|
+
|
53
|
+
put "/merchants/:merchant_id/customers/:id" do
|
54
|
+
customer = Hash.from_xml(request.body).delete("customer")
|
55
|
+
if !FakeBraintree.failure?(customer["credit_card"]["number"])
|
56
|
+
customer["id"] = params[:id]
|
57
|
+
customer["merchant-id"] = params[:merchant_id]
|
58
|
+
if customer["credit_card"] && customer["credit_card"].is_a?(Hash)
|
59
|
+
customer["credit_card"].delete("__content__")
|
60
|
+
if !customer["credit_card"].empty?
|
61
|
+
customer["credit_card"]["last_4"] = customer["credit_card"].delete("number")[-4..-1]
|
62
|
+
customer["credit_card"]["token"] = Digest::MD5.hexdigest("#{customer['merchant_id']}#{customer['id']}#{Time.now.to_f}")
|
63
|
+
credit_card = customer.delete("credit_card")
|
64
|
+
customer["credit_cards"] = [credit_card]
|
65
|
+
end
|
66
|
+
end
|
67
|
+
FakeBraintree.customers[params["id"]] = customer
|
68
|
+
gzipped_response(200, customer.to_xml(:root => 'customer'))
|
69
|
+
else
|
70
|
+
gzipped_response(422, FakeBraintree.failure_response(customer["credit_card"]["number"]).to_xml(:root => 'api_error_response'))
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
delete "/merchants/:merchant_id/customers/:id" do
|
75
|
+
FakeBraintree.customers[params["id"]] = nil
|
76
|
+
gzipped_response(200, "")
|
77
|
+
end
|
78
|
+
|
79
|
+
post "/merchants/:merchant_id/subscriptions" do
|
80
|
+
"<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<subscription>\n <plan-id type=\"integer\">2</plan-id>\n <payment-method-token>b22x</payment-method-token>\n</subscription>\n"
|
81
|
+
subscription = Hash.from_xml(request.body).delete("subscription")
|
82
|
+
subscription["id"] ||= Digest::MD5.hexdigest("#{subscription["payment_method_token"]}#{Time.now.to_f}")
|
83
|
+
subscription["transactions"] = []
|
84
|
+
subscription["add_ons"] = []
|
85
|
+
subscription["discounts"] = []
|
86
|
+
subscription["next_billing_date"] = 1.month.from_now
|
87
|
+
subscription["status"] = Braintree::Subscription::Status::Active
|
88
|
+
FakeBraintree.subscriptions[subscription["id"]] = subscription
|
89
|
+
gzipped_response(201, subscription.to_xml(:root => 'subscription'))
|
90
|
+
end
|
91
|
+
|
92
|
+
get "/merchants/:merchant_id/subscriptions/:id" do
|
93
|
+
subscription = FakeBraintree.subscriptions[params[:id]]
|
94
|
+
gzipped_response(200, subscription.to_xml(:root => 'subscription'))
|
95
|
+
end
|
96
|
+
|
97
|
+
put "/merchants/:merchant_id/subscriptions/:id" do
|
98
|
+
subscription = Hash.from_xml(request.body).delete("subscription")
|
99
|
+
subscription["transactions"] = []
|
100
|
+
subscription["add_ons"] = []
|
101
|
+
subscription["discounts"] = []
|
102
|
+
FakeBraintree.subscriptions[params["id"]] = subscription
|
103
|
+
gzipped_response(200, subscription.to_xml(:root => 'subscription'))
|
104
|
+
end
|
105
|
+
|
106
|
+
# Braintree::Transaction.search
|
107
|
+
post "/merchants/:merchant_id/transactions/advanced_search_ids" do
|
108
|
+
# "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<search>\n <created-at>\n <min type=\"datetime\">2011-01-10T14:14:26Z</min>\n </created-at>\n</search>\n"
|
109
|
+
gzipped_response(200, "<search-results>\n <page-size type=\"integer\">50</page-size>\n <ids type=\"array\">\n <item>49sbx6</item>\n </ids>\n</search-results>\n")
|
110
|
+
end
|
111
|
+
|
112
|
+
# Braintree::Transaction.search
|
113
|
+
post "/merchants/:merchant_id/transactions/advanced_search" do
|
114
|
+
# "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<search>\n <ids type=\"array\">\n <item>49sbx6</item>\n </ids>\n <created-at>\n <min type=\"datetime\">2011-01-10T14:14:26Z</min>\n </created-at>\n</search>\n"
|
115
|
+
gzipped_response(200, FakeBraintree.generated_transaction.to_xml)
|
116
|
+
end
|
117
|
+
|
118
|
+
get "/merchants/:merchant_id/payment_methods/:credit_card_token" do
|
119
|
+
credit_card = FakeBraintree.credit_card_from_token(params[:credit_card_token])
|
120
|
+
gzipped_response(200, credit_card.to_xml(:root => "credit_card"))
|
121
|
+
end
|
122
|
+
|
123
|
+
# Braintree::Transaction.sale
|
124
|
+
# Braintree::CreditCard.sale
|
125
|
+
post "/merchants/:merchant_id/transactions" do
|
126
|
+
transaction = Hash.from_xml(request.body)["transaction"]
|
127
|
+
transaction_id = Digest::MD5.hexdigest("#{params[:merchant_id]}#{Time.now.to_f}")
|
128
|
+
transaction_response = {"id" => transaction_id, "amount" => transaction["amount"]}
|
129
|
+
|
130
|
+
if FakeBraintree.decline_all_cards?
|
131
|
+
gzipped_response(422, FakeBraintree.create_failure.to_xml(:root => 'api_error_response'))
|
132
|
+
else
|
133
|
+
FakeBraintree.transaction.replace(transaction_response)
|
134
|
+
gzipped_response(200, transaction_response.to_xml(:root => "transaction"))
|
135
|
+
end
|
136
|
+
end
|
137
|
+
|
138
|
+
# Braintree::Transaction.find
|
139
|
+
get "/merchants/:merchant_id/transactions/:transaction_id" do
|
140
|
+
if FakeBraintree.transaction["id"] == params[:transaction_id]
|
141
|
+
gzipped_response(200, FakeBraintree.transaction.to_xml(:root => "transaction"))
|
142
|
+
else
|
143
|
+
gzipped_response(404, {})
|
144
|
+
end
|
145
|
+
end
|
146
|
+
end
|
147
|
+
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
module FakeBraintree
|
4
|
+
describe SinatraApp, "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
|
+
it "gets the correct credit card" do
|
10
|
+
credit_card = Braintree::CreditCard.find(token)
|
11
|
+
|
12
|
+
credit_card.last_4.should == "9876"
|
13
|
+
credit_card.expiration_year.should == "2016"
|
14
|
+
credit_card.expiration_month.should == "04"
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
describe SinatraApp, "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
|
+
it "successfully creates a sale" do
|
25
|
+
result = Braintree::CreditCard.sale(token, amount: amount, options: {submit_for_settlement: true})
|
26
|
+
result.should be_success
|
27
|
+
|
28
|
+
Braintree::Transaction.find(result.transaction.id).should be
|
29
|
+
lambda { Braintree::Transaction.find("foo") }.should raise_error(Braintree::NotFoundError)
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
@@ -0,0 +1,65 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe FakeBraintree, ".credit_card_from_token" do
|
4
|
+
let(:cc_number) { %w(4111 1111 1111 9876).join }
|
5
|
+
let(:cc_number_2) { %w(4111 1111 1111 2222).join }
|
6
|
+
let(:expiration_date) { "04/2016" }
|
7
|
+
let(:expiration_date_2) { "05/2019" }
|
8
|
+
let(:token) { braintree_credit_card_token(cc_number, expiration_date) }
|
9
|
+
let(:token_2) { braintree_credit_card_token(cc_number_2, expiration_date_2) }
|
10
|
+
|
11
|
+
it "looks up the credit card based on a CC token" do
|
12
|
+
credit_card = FakeBraintree.credit_card_from_token(token)
|
13
|
+
credit_card["last_4"].should == "9876"
|
14
|
+
credit_card["expiration_year"].should == "2016"
|
15
|
+
credit_card["expiration_month"].should == "04"
|
16
|
+
|
17
|
+
credit_card = FakeBraintree.credit_card_from_token(token_2)
|
18
|
+
credit_card["last_4"].should == "2222"
|
19
|
+
credit_card["expiration_year"].should == "2019"
|
20
|
+
credit_card["expiration_month"].should == "05"
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
describe FakeBraintree, ".decline_all_cards!" do
|
25
|
+
let(:cc_number) { %w(4111 1111 1111 9876).join }
|
26
|
+
let(:expiration_date) { "04/2016" }
|
27
|
+
let(:token) { braintree_credit_card_token(cc_number, expiration_date) }
|
28
|
+
let(:amount) { 10.00 }
|
29
|
+
|
30
|
+
before do
|
31
|
+
FakeBraintree.decline_all_cards!
|
32
|
+
end
|
33
|
+
|
34
|
+
it "declines all cards" do
|
35
|
+
result = Braintree::CreditCard.sale(token, amount: amount)
|
36
|
+
result.should_not be_success
|
37
|
+
end
|
38
|
+
|
39
|
+
it "stops declining cards after clear! is called" do
|
40
|
+
FakeBraintree.clear!
|
41
|
+
result = Braintree::CreditCard.sale(token, amount: amount)
|
42
|
+
result.should be_success
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
describe "configuration variables" do
|
47
|
+
subject { Braintree::Configuration }
|
48
|
+
|
49
|
+
it "sets the environment to production" do
|
50
|
+
subject.environment.should == :production
|
51
|
+
end
|
52
|
+
|
53
|
+
it "sets some fake API credentials" do
|
54
|
+
subject.merchant_id.should == "xxx"
|
55
|
+
subject.public_key.should == "xxx"
|
56
|
+
subject.private_key.should == "xxx"
|
57
|
+
end
|
58
|
+
|
59
|
+
its(:logger) { should be_a Logger }
|
60
|
+
|
61
|
+
it "does not log to STDOUT" do
|
62
|
+
STDOUT.expects(:write).with("Logger test\n").never
|
63
|
+
subject.logger.info('Logger test')
|
64
|
+
end
|
65
|
+
end
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,16 @@
|
|
1
|
+
# Requires supporting ruby files with custom matchers and macros, etc,
|
2
|
+
# in spec/support/ and its subdirectories.
|
3
|
+
require 'rspec'
|
4
|
+
require 'fake_braintree'
|
5
|
+
Dir[File.join(File.dirname(__FILE__), "support/**/*.rb")].each {|f| require f}
|
6
|
+
|
7
|
+
Dir.mkdir('tmp') unless Dir.exist?('tmp')
|
8
|
+
File.new('tmp/braintree_log', 'w').close
|
9
|
+
|
10
|
+
RSpec.configure do |config|
|
11
|
+
config.mock_with :mocha
|
12
|
+
|
13
|
+
config.include BraintreeHelpers
|
14
|
+
|
15
|
+
config.before { FakeBraintree.clear! }
|
16
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
module BraintreeHelpers
|
2
|
+
def create_braintree_customer(cc_number, expiration_date)
|
3
|
+
Braintree::Customer.create(
|
4
|
+
email: "me@example.com",
|
5
|
+
credit_card: {
|
6
|
+
number: cc_number,
|
7
|
+
expiration_date: expiration_date
|
8
|
+
}
|
9
|
+
).customer
|
10
|
+
end
|
11
|
+
|
12
|
+
def braintree_credit_card_token(cc_number, expiration_date)
|
13
|
+
create_braintree_customer(cc_number, expiration_date).credit_cards[0].token
|
14
|
+
end
|
15
|
+
end
|
metadata
ADDED
@@ -0,0 +1,139 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: fake_braintree
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.2
|
5
|
+
prerelease:
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- thoughtbot, inc.
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
date: 2011-09-08 00:00:00.000000000Z
|
13
|
+
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
15
|
+
name: sham_rack
|
16
|
+
requirement: &2162481680 !ruby/object:Gem::Requirement
|
17
|
+
none: false
|
18
|
+
requirements:
|
19
|
+
- - ! '>='
|
20
|
+
- !ruby/object:Gem::Version
|
21
|
+
version: '0'
|
22
|
+
type: :runtime
|
23
|
+
prerelease: false
|
24
|
+
version_requirements: *2162481680
|
25
|
+
- !ruby/object:Gem::Dependency
|
26
|
+
name: activesupport
|
27
|
+
requirement: &2162481240 !ruby/object:Gem::Requirement
|
28
|
+
none: false
|
29
|
+
requirements:
|
30
|
+
- - ! '>='
|
31
|
+
- !ruby/object:Gem::Version
|
32
|
+
version: '0'
|
33
|
+
type: :runtime
|
34
|
+
prerelease: false
|
35
|
+
version_requirements: *2162481240
|
36
|
+
- !ruby/object:Gem::Dependency
|
37
|
+
name: i18n
|
38
|
+
requirement: &2162480820 !ruby/object:Gem::Requirement
|
39
|
+
none: false
|
40
|
+
requirements:
|
41
|
+
- - ! '>='
|
42
|
+
- !ruby/object:Gem::Version
|
43
|
+
version: '0'
|
44
|
+
type: :runtime
|
45
|
+
prerelease: false
|
46
|
+
version_requirements: *2162480820
|
47
|
+
- !ruby/object:Gem::Dependency
|
48
|
+
name: sinatra
|
49
|
+
requirement: &2162480400 !ruby/object:Gem::Requirement
|
50
|
+
none: false
|
51
|
+
requirements:
|
52
|
+
- - ! '>='
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '0'
|
55
|
+
type: :runtime
|
56
|
+
prerelease: false
|
57
|
+
version_requirements: *2162480400
|
58
|
+
- !ruby/object:Gem::Dependency
|
59
|
+
name: braintree
|
60
|
+
requirement: &2162479900 !ruby/object:Gem::Requirement
|
61
|
+
none: false
|
62
|
+
requirements:
|
63
|
+
- - ~>
|
64
|
+
- !ruby/object:Gem::Version
|
65
|
+
version: '2.5'
|
66
|
+
type: :runtime
|
67
|
+
prerelease: false
|
68
|
+
version_requirements: *2162479900
|
69
|
+
- !ruby/object:Gem::Dependency
|
70
|
+
name: rspec
|
71
|
+
requirement: &2162479400 !ruby/object:Gem::Requirement
|
72
|
+
none: false
|
73
|
+
requirements:
|
74
|
+
- - ~>
|
75
|
+
- !ruby/object:Gem::Version
|
76
|
+
version: 2.6.0
|
77
|
+
type: :development
|
78
|
+
prerelease: false
|
79
|
+
version_requirements: *2162479400
|
80
|
+
- !ruby/object:Gem::Dependency
|
81
|
+
name: mocha
|
82
|
+
requirement: &2162478940 !ruby/object:Gem::Requirement
|
83
|
+
none: false
|
84
|
+
requirements:
|
85
|
+
- - ~>
|
86
|
+
- !ruby/object:Gem::Version
|
87
|
+
version: 0.9.12
|
88
|
+
type: :development
|
89
|
+
prerelease: false
|
90
|
+
version_requirements: *2162478940
|
91
|
+
description: A fake Braintree that you can run integration tests against
|
92
|
+
email:
|
93
|
+
- gabe@thoughtbot.com
|
94
|
+
- ben@thoughtbot.com
|
95
|
+
executables: []
|
96
|
+
extensions: []
|
97
|
+
extra_rdoc_files: []
|
98
|
+
files:
|
99
|
+
- .gitignore
|
100
|
+
- Gemfile
|
101
|
+
- README.md
|
102
|
+
- Rakefile
|
103
|
+
- fake_braintree.gemspec
|
104
|
+
- lib/fake_braintree.rb
|
105
|
+
- lib/fake_braintree/sinatra_app.rb
|
106
|
+
- lib/fake_braintree/version.rb
|
107
|
+
- spec/fake_braintree/sinatra_app_spec.rb
|
108
|
+
- spec/fake_braintree_spec.rb
|
109
|
+
- spec/spec_helper.rb
|
110
|
+
- spec/support/braintree_helpers.rb
|
111
|
+
homepage: ''
|
112
|
+
licenses: []
|
113
|
+
post_install_message:
|
114
|
+
rdoc_options: []
|
115
|
+
require_paths:
|
116
|
+
- lib
|
117
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
118
|
+
none: false
|
119
|
+
requirements:
|
120
|
+
- - ! '>='
|
121
|
+
- !ruby/object:Gem::Version
|
122
|
+
version: '0'
|
123
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
124
|
+
none: false
|
125
|
+
requirements:
|
126
|
+
- - ! '>='
|
127
|
+
- !ruby/object:Gem::Version
|
128
|
+
version: '0'
|
129
|
+
requirements: []
|
130
|
+
rubyforge_project:
|
131
|
+
rubygems_version: 1.8.8
|
132
|
+
signing_key:
|
133
|
+
specification_version: 3
|
134
|
+
summary: A fake Braintree that you can run integration tests against
|
135
|
+
test_files:
|
136
|
+
- spec/fake_braintree/sinatra_app_spec.rb
|
137
|
+
- spec/fake_braintree_spec.rb
|
138
|
+
- spec/spec_helper.rb
|
139
|
+
- spec/support/braintree_helpers.rb
|