fake_braintree 0.0.3 → 0.0.4

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/Changelog.md ADDED
@@ -0,0 +1,9 @@
1
+ # 0.0.4
2
+ * Allow for very basic card verification
3
+
4
+ # 0.0.3
5
+ * Ensure FakeBraintree.log_file_path directory exists
6
+ * The FakeBraintree.log_file_path attribute can now be read (it could only be set before)
7
+ * Clear log when FakeBraintree.clear! is called
8
+ * Correctly handle nonexistent subscriptions when using
9
+ Braintree::Subscription.find
data/README.md CHANGED
@@ -3,4 +3,26 @@
3
3
  Currently in alpha. Needs complete test coverage, then more functionality can
4
4
  be added.
5
5
 
6
- Call FakeBraintree.activate! to make it go.
6
+ ## Quick start
7
+ Call `FakeBraintree.activate!` to make it go. `FakeBraintree.clear!` will clear
8
+ all data, which you probably want to do before each test.
9
+
10
+ Example, in spec\_helper.rb:
11
+
12
+ FakeBraintree.activate!
13
+
14
+ RSpec.configure do |c|
15
+ c.before do
16
+ FakeBraintree.clear!
17
+ end
18
+ end
19
+
20
+ ## Verifying credit cards
21
+
22
+ To verify every credit card you try to use, call
23
+ `FakeBraintree.verify\_all\_cards!`. This will stay "on" until you set
24
+ `FakeBraintree.verify_all_cards = false`. Calling FakeBraintree.clear! _will
25
+ not_ change it. It does very basic verification: it only matches the credit card
26
+ number against these:
27
+ http://www.braintreepayments.com/docs/ruby/reference/sandbox and rejects them if
28
+ they aren't one of the listed numbers.
@@ -3,6 +3,7 @@ require 'braintree'
3
3
  require 'sham_rack'
4
4
 
5
5
  require 'fake_braintree/sinatra_app'
6
+ require 'fake_braintree/valid_credit_cards'
6
7
  require 'fake_braintree/version'
7
8
 
8
9
  module FakeBraintree
@@ -13,7 +14,8 @@ module FakeBraintree
13
14
  @transaction = {}
14
15
 
15
16
  @decline_all_cards = false
16
- attr_accessor :customers, :subscriptions, :failures, :transaction, :decline_all_cards
17
+ @verify_all_cards = false
18
+ attr_accessor :customers, :subscriptions, :failures, :transaction, :decline_all_cards, :verify_all_cards
17
19
  end
18
20
 
19
21
  def self.activate!
@@ -48,7 +50,7 @@ module FakeBraintree
48
50
  end
49
51
 
50
52
  def self.failure_response(card_number)
51
- failure = self.failures[card_number]
53
+ failure = self.failures[card_number] || {}
52
54
  failure["errors"] ||= { "errors" => [] }
53
55
 
54
56
  { "message" => failure["message"],
@@ -78,6 +80,10 @@ module FakeBraintree
78
80
  self.decline_all_cards
79
81
  end
80
82
 
83
+ def self.verify_all_cards!
84
+ self.verify_all_cards = true
85
+ end
86
+
81
87
  def self.credit_card_from_token(token)
82
88
  self.customers.values.detect do |customer|
83
89
  next unless customer.key?("credit_cards")
@@ -22,6 +22,18 @@ module FakeBraintree
22
22
  def md5(content)
23
23
  Digest::MD5.hexdigest(content)
24
24
  end
25
+
26
+ def verify_credit_card?(customer_hash)
27
+ return true if FakeBraintree.verify_all_cards
28
+
29
+ customer_hash["credit_card"].key?("options") &&
30
+ customer_hash["credit_card"]["options"].is_a?(Hash) &&
31
+ customer_hash["credit_card"]["options"]["verify_card"] == true
32
+ end
33
+
34
+ def has_invalid_credit_card?(customer_hash)
35
+ ! FakeBraintree::VALID_CREDIT_CARDS.include?(customer_hash["credit_card"]["number"])
36
+ end
25
37
  end
26
38
 
27
39
  # Braintree::Customer.create
@@ -30,23 +42,27 @@ module FakeBraintree
30
42
  if FakeBraintree.failure?(customer["credit_card"]["number"])
31
43
  gzipped_response(422, FakeBraintree.failure_response(customer["credit_card"]["number"]).to_xml(:root => 'api_error_response'))
32
44
  else
33
- customer["id"] ||= md5("#{params[:merchant_id]}#{Time.now.to_f}")
34
- customer["merchant-id"] = params[:merchant_id]
35
- if customer["credit_card"] && customer["credit_card"].is_a?(Hash)
36
- customer["credit_card"].delete("__content__")
37
- if !customer["credit_card"].empty?
38
- customer["credit_card"]["last_4"] = customer["credit_card"].delete("number")[-4..-1]
39
- customer["credit_card"]["token"] = md5("#{customer['merchant_id']}#{customer['id']}#{Time.now.to_f}")
40
- expiration_date = customer["credit_card"].delete("expiration_date")
41
- customer["credit_card"]["expiration_month"] = expiration_date.split('/')[0]
42
- customer["credit_card"]["expiration_year"] = expiration_date.split('/')[1]
43
-
44
- credit_card = customer.delete("credit_card")
45
- customer["credit_cards"] = [credit_card]
45
+ if verify_credit_card?(customer) && has_invalid_credit_card?(customer)
46
+ gzipped_response(422, FakeBraintree.failure_response(customer["credit_card"]["number"]).to_xml(:root => 'api_error_response'))
47
+ else
48
+ customer["id"] ||= md5("#{params[:merchant_id]}#{Time.now.to_f}")
49
+ customer["merchant-id"] = params[:merchant_id]
50
+ if customer["credit_card"] && customer["credit_card"].is_a?(Hash)
51
+ customer["credit_card"].delete("__content__")
52
+ if !customer["credit_card"].empty?
53
+ customer["credit_card"]["last_4"] = customer["credit_card"].delete("number")[-4..-1]
54
+ customer["credit_card"]["token"] = md5("#{customer['merchant_id']}#{customer['id']}#{Time.now.to_f}")
55
+ expiration_date = customer["credit_card"].delete("expiration_date")
56
+ customer["credit_card"]["expiration_month"] = expiration_date.split('/')[0]
57
+ customer["credit_card"]["expiration_year"] = expiration_date.split('/')[1]
58
+
59
+ credit_card = customer.delete("credit_card")
60
+ customer["credit_cards"] = [credit_card]
61
+ end
46
62
  end
63
+ FakeBraintree.customers[customer["id"]] = customer
64
+ gzipped_response(201, customer.to_xml(:root => 'customer'))
47
65
  end
48
- FakeBraintree.customers[customer["id"]] = customer
49
- gzipped_response(201, customer.to_xml(:root => 'customer'))
50
66
  end
51
67
  end
52
68
 
@@ -0,0 +1,9 @@
1
+ module FakeBraintree
2
+ VALID_CREDIT_CARDS = %w(4111111111111111 4005519200000004
3
+ 4009348888881881 4012000033330026
4
+ 4012000077777777 4012888888881881
5
+ 4217651111111119 4500600000000061
6
+ 5555555555554444 378282246310005
7
+ 371449635398431 6011111111111117
8
+ 3530111333300000)
9
+ end
@@ -1,3 +1,3 @@
1
1
  module FakeBraintree
2
- VERSION = "0.0.3"
2
+ VERSION = "0.0.4"
3
3
  end
@@ -65,7 +65,7 @@ module FakeBraintree
65
65
  let(:expiration_date) { "04/2016" }
66
66
  let(:payment_method_token) { braintree_credit_card_token(cc_number, expiration_date) }
67
67
  let(:subscription_result) { Braintree::Subscription.create(:payment_method_token => payment_method_token,
68
- :plan_id => plan_id) }
68
+ :plan_id => 'my-plan-id') }
69
69
 
70
70
  it "can find a created subscription" do
71
71
  Braintree::Subscription.find(subscription_result.subscription.id).should be
@@ -75,4 +75,52 @@ module FakeBraintree
75
75
  expect { Braintree::Subscription.find('abc123') }.to raise_error(Braintree::NotFoundError, /abc123/)
76
76
  end
77
77
  end
78
+
79
+ describe SinatraApp, "Braintree::Customer.create" do
80
+ let(:cc_number) { %w(4111 1111 1111 1111).join }
81
+ let(:expiration_date) { "04/2016" }
82
+ after { FakeBraintree.verify_all_cards = false }
83
+
84
+ it "successfully creates a customer" do
85
+ result = Braintree::Customer.create(
86
+ :credit_card => {
87
+ :number => cc_number,
88
+ :expiration_date => expiration_date
89
+ })
90
+
91
+ result.should be_success
92
+ end
93
+
94
+ it "verifies the card number when passed :verify_card => true" do
95
+ Braintree::Customer.create(
96
+ :credit_card => {
97
+ :number => cc_number,
98
+ :expiration_date => expiration_date,
99
+ :options => { :verify_card => true }
100
+ }).should be_success
101
+
102
+ Braintree::Customer.create(
103
+ :credit_card => {
104
+ :number => '123456',
105
+ :expiration_date => expiration_date,
106
+ :options => { :verify_card => true }
107
+ }).should_not be_success
108
+ end
109
+
110
+ it "verifies the card number when FakeBraintree.verify_all_cards == true" do
111
+ FakeBraintree.verify_all_cards!
112
+
113
+ Braintree::Customer.create(
114
+ :credit_card => {
115
+ :number => cc_number,
116
+ :expiration_date => expiration_date
117
+ }).should be_success
118
+
119
+ Braintree::Customer.create(
120
+ :credit_card => {
121
+ :number => '123456',
122
+ :expiration_date => expiration_date
123
+ }).should_not be_success
124
+ end
125
+ end
78
126
  end
@@ -84,3 +84,20 @@ describe FakeBraintree, ".clear_log!" do
84
84
  FakeBraintree.clear!
85
85
  end
86
86
  end
87
+
88
+ describe FakeBraintree, "VALID_CREDIT_CARDS" do
89
+ let(:valid_credit_cards) do
90
+ %w(4111111111111111 4005519200000004
91
+ 4009348888881881 4012000033330026
92
+ 4012000077777777 4012888888881881
93
+ 4217651111111119 4500600000000061
94
+ 5555555555554444 378282246310005
95
+ 371449635398431 6011111111111117
96
+ 3530111333300000
97
+ )
98
+ end
99
+
100
+ it "includes only credit cards that are valid in production" do
101
+ FakeBraintree::VALID_CREDIT_CARDS.sort.should == valid_credit_cards.sort
102
+ end
103
+ end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: fake_braintree
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.3
4
+ version: 0.0.4
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -13,7 +13,7 @@ date: 2011-10-24 00:00:00.000000000Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: sham_rack
16
- requirement: &70234757701580 !ruby/object:Gem::Requirement
16
+ requirement: &70166836515360 !ruby/object:Gem::Requirement
17
17
  none: false
18
18
  requirements:
19
19
  - - ! '>='
@@ -21,10 +21,10 @@ dependencies:
21
21
  version: '0'
22
22
  type: :runtime
23
23
  prerelease: false
24
- version_requirements: *70234757701580
24
+ version_requirements: *70166836515360
25
25
  - !ruby/object:Gem::Dependency
26
26
  name: activesupport
27
- requirement: &70234757700380 !ruby/object:Gem::Requirement
27
+ requirement: &70166836511340 !ruby/object:Gem::Requirement
28
28
  none: false
29
29
  requirements:
30
30
  - - ! '>='
@@ -32,10 +32,10 @@ dependencies:
32
32
  version: '0'
33
33
  type: :runtime
34
34
  prerelease: false
35
- version_requirements: *70234757700380
35
+ version_requirements: *70166836511340
36
36
  - !ruby/object:Gem::Dependency
37
37
  name: i18n
38
- requirement: &70234757699160 !ruby/object:Gem::Requirement
38
+ requirement: &70166836500660 !ruby/object:Gem::Requirement
39
39
  none: false
40
40
  requirements:
41
41
  - - ! '>='
@@ -43,10 +43,10 @@ dependencies:
43
43
  version: '0'
44
44
  type: :runtime
45
45
  prerelease: false
46
- version_requirements: *70234757699160
46
+ version_requirements: *70166836500660
47
47
  - !ruby/object:Gem::Dependency
48
48
  name: sinatra
49
- requirement: &70234757698720 !ruby/object:Gem::Requirement
49
+ requirement: &70166836498100 !ruby/object:Gem::Requirement
50
50
  none: false
51
51
  requirements:
52
52
  - - ! '>='
@@ -54,10 +54,10 @@ dependencies:
54
54
  version: '0'
55
55
  type: :runtime
56
56
  prerelease: false
57
- version_requirements: *70234757698720
57
+ version_requirements: *70166836498100
58
58
  - !ruby/object:Gem::Dependency
59
59
  name: braintree
60
- requirement: &70234757698120 !ruby/object:Gem::Requirement
60
+ requirement: &70166836491540 !ruby/object:Gem::Requirement
61
61
  none: false
62
62
  requirements:
63
63
  - - ~>
@@ -65,10 +65,10 @@ dependencies:
65
65
  version: '2.5'
66
66
  type: :runtime
67
67
  prerelease: false
68
- version_requirements: *70234757698120
68
+ version_requirements: *70166836491540
69
69
  - !ruby/object:Gem::Dependency
70
70
  name: rspec
71
- requirement: &70234757697400 !ruby/object:Gem::Requirement
71
+ requirement: &70166836489720 !ruby/object:Gem::Requirement
72
72
  none: false
73
73
  requirements:
74
74
  - - ~>
@@ -76,10 +76,10 @@ dependencies:
76
76
  version: 2.6.0
77
77
  type: :development
78
78
  prerelease: false
79
- version_requirements: *70234757697400
79
+ version_requirements: *70166836489720
80
80
  - !ruby/object:Gem::Dependency
81
81
  name: mocha
82
- requirement: &70234757696880 !ruby/object:Gem::Requirement
82
+ requirement: &70166836488220 !ruby/object:Gem::Requirement
83
83
  none: false
84
84
  requirements:
85
85
  - - ~>
@@ -87,7 +87,7 @@ dependencies:
87
87
  version: 0.9.12
88
88
  type: :development
89
89
  prerelease: false
90
- version_requirements: *70234757696880
90
+ version_requirements: *70166836488220
91
91
  description: A fake Braintree that you can run integration tests against
92
92
  email:
93
93
  - gabe@thoughtbot.com
@@ -97,12 +97,14 @@ extensions: []
97
97
  extra_rdoc_files: []
98
98
  files:
99
99
  - .gitignore
100
+ - Changelog.md
100
101
  - Gemfile
101
102
  - README.md
102
103
  - Rakefile
103
104
  - fake_braintree.gemspec
104
105
  - lib/fake_braintree.rb
105
106
  - lib/fake_braintree/sinatra_app.rb
107
+ - lib/fake_braintree/valid_credit_cards.rb
106
108
  - lib/fake_braintree/version.rb
107
109
  - spec/fake_braintree/sinatra_app_spec.rb
108
110
  - spec/fake_braintree_spec.rb