stripe-ruby-mock 2.1.1 → 2.2.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (44) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +1 -0
  3. data/.travis.yml +7 -2
  4. data/README.md +22 -4
  5. data/lib/stripe_mock.rb +2 -0
  6. data/lib/stripe_mock/api/errors.rb +23 -11
  7. data/lib/stripe_mock/api/webhooks.rb +4 -4
  8. data/lib/stripe_mock/data.rb +19 -4
  9. data/lib/stripe_mock/data/list.rb +2 -5
  10. data/lib/stripe_mock/instance.rb +7 -3
  11. data/lib/stripe_mock/request_handlers/accounts.rb +35 -0
  12. data/lib/stripe_mock/request_handlers/charges.rb +28 -0
  13. data/lib/stripe_mock/request_handlers/coupons.rb +3 -2
  14. data/lib/stripe_mock/request_handlers/customers.rb +25 -2
  15. data/lib/stripe_mock/request_handlers/helpers/card_helpers.rb +3 -3
  16. data/lib/stripe_mock/request_handlers/helpers/coupon_helpers.rb +13 -0
  17. data/lib/stripe_mock/request_handlers/invoices.rb +1 -0
  18. data/lib/stripe_mock/request_handlers/subscriptions.rb +30 -2
  19. data/lib/stripe_mock/request_handlers/transfers.rb +5 -0
  20. data/lib/stripe_mock/request_handlers/validators/param_validators.rb +1 -1
  21. data/lib/stripe_mock/test_strategies/base.rb +35 -0
  22. data/lib/stripe_mock/test_strategies/live.rb +13 -0
  23. data/lib/stripe_mock/version.rb +1 -1
  24. data/lib/stripe_mock/webhook_fixtures/{customer.card.created.json → customer.source.created.json} +2 -2
  25. data/lib/stripe_mock/webhook_fixtures/{customer.card.deleted.json → customer.source.deleted.json} +2 -2
  26. data/lib/stripe_mock/webhook_fixtures/{customer.card.updated.json → customer.source.updated.json} +2 -2
  27. data/lib/stripe_mock/webhook_fixtures/transfer.created.json +1 -0
  28. data/lib/stripe_mock/webhook_fixtures/transfer.failed.json +1 -0
  29. data/lib/stripe_mock/webhook_fixtures/transfer.paid.json +1 -0
  30. data/lib/stripe_mock/webhook_fixtures/transfer.updated.json +1 -0
  31. data/spec/integration_examples/charge_token_examples.rb +16 -14
  32. data/spec/integration_examples/prepare_error_examples.rb +20 -0
  33. data/spec/shared_stripe_examples/account_examples.rb +17 -0
  34. data/spec/shared_stripe_examples/card_examples.rb +2 -1
  35. data/spec/shared_stripe_examples/charge_examples.rb +64 -0
  36. data/spec/shared_stripe_examples/coupon_examples.rb +68 -84
  37. data/spec/shared_stripe_examples/customer_examples.rb +57 -2
  38. data/spec/shared_stripe_examples/plan_examples.rb +1 -1
  39. data/spec/shared_stripe_examples/subscription_examples.rb +65 -0
  40. data/spec/shared_stripe_examples/transfer_examples.rb +14 -0
  41. data/spec/spec_helper.rb +18 -3
  42. data/spec/support/stripe_examples.rb +2 -0
  43. data/stripe-ruby-mock.gemspec +1 -1
  44. metadata +31 -41
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 0a938c591e648a2e11b45f6ef5fe9501960b8ef9
4
+ data.tar.gz: 128f7dd797e0dc2e3e308228187326eb9fbd953a
5
+ SHA512:
6
+ metadata.gz: 55bdfab487061c0be56698383d87b2b7641d3dedf1925cc18e0de75837f1179438442aaf4234fc590fe5f325414ba7dc5ec3fc427f8e6c88061d735ec81d8534
7
+ data.tar.gz: 76f52b22076b7bea8f6c8b2206e2bf3933911ea63f42f7bb88021e6b76b5bf802805101cbe61dbcb29369559437020eec06c6721c5e27933db69f11352b4efd3
data/.gitignore CHANGED
@@ -4,3 +4,4 @@ pkg/
4
4
  stripe-mock-server.pid
5
5
  Gemfile.lock
6
6
  stripe-mock-server.log
7
+ .idea
data/.travis.yml CHANGED
@@ -2,11 +2,16 @@ language: ruby
2
2
  rvm:
3
3
  - 1.9.3
4
4
  - 2.0.0
5
- - 2.1.0
5
+ - 2.1.6
6
6
  before_script:
7
7
  - "sudo touch /var/log/stripe-mock-server.log"
8
8
  - "sudo chown travis /var/log/stripe-mock-server.log"
9
- script: "bundle exec rspec; bundle exec rspec -t live"
9
+ script: "bundle exec rspec && bundle exec rspec -t live"
10
+
11
+ env:
12
+ global:
13
+ - IS_TRAVIS=true STRIPE_TEST_SECRET_KEY_A=sk_test_sXdhUWu3NhrB7r1tkK0zZfMW STRIPE_TEST_SECRET_KEY_B=sk_test_v2K2hV9VJ8AoRKTeDRkQ3rG3 STRIPE_TEST_SECRET_KEY_C=sk_test_QNgKQJhW4fWYT63be2AUSVjJ
14
+
10
15
  notifications:
11
16
  webhooks:
12
17
  urls:
data/README.md CHANGED
@@ -4,11 +4,15 @@
4
4
  * Issues: https://github.com/rebelidealist/stripe-ruby-mock/issues
5
5
  * **CHAT**: https://gitter.im/rebelidealist/stripe-ruby-mock
6
6
 
7
+ # REQUEST: Looking for More Core Contributors
8
+
9
+ This gem has unexpectedly grown in popularity and I've gotten pretty busy, so I'm currently looking for more core contributors to help me out. If you're interested, there is only one requirement: submit a significant enough pull request and have it merged into master (many of you have already done this). Afterwards, ping me in [chat](https://gitter.im/rebelidealist/stripe-ruby-mock) and I will add you as a collaborator.
10
+
7
11
  ## Install
8
12
 
9
13
  In your gemfile:
10
14
 
11
- gem 'stripe-ruby-mock', '~> 2.1.1', :require => 'stripe_mock'
15
+ gem 'stripe-ruby-mock', '~> 2.2.0', :require => 'stripe_mock'
12
16
 
13
17
  ## Features
14
18
 
@@ -55,6 +59,7 @@ describe MyApp do
55
59
  it "creates a stripe customer" do
56
60
 
57
61
  # This doesn't touch stripe's servers nor the internet!
62
+ # Specify :source in place of :card (with same value) to return customer with source data
58
63
  customer = Stripe::Customer.create({
59
64
  email: 'johnny@appleseed.com',
60
65
  card: stripe_helper.generate_card_token
@@ -106,16 +111,29 @@ Every once in a while you want to make sure your tests are actually valid. Strip
106
111
  Here is an example of setting up your RSpec (2.x) test suite to run live with a command line switch:
107
112
 
108
113
  ```ruby
114
+ # RSpec 2.x
109
115
  RSpec.configure do |c|
110
116
  if c.filter_manager.inclusions.keys.include?(:live)
111
- puts "Running **live** tests against Stripe..."
112
117
  StripeMock.toggle_live(true)
118
+ puts "Running **live** tests against Stripe..."
113
119
  end
114
120
  end
115
121
  ```
116
122
 
117
123
  With this you can run live tests by running `rspec -t live`
118
124
 
125
+ Here is an example of setting up your RSpec (3.x) test suite to run live with the same command line switch:
126
+
127
+ ```ruby
128
+ # RSpec 3.x
129
+ RSpec.configure do |c|
130
+ if c.filter_manager.inclusions.rules.include?(:live)
131
+ StripeMock.toggle_live(true)
132
+ puts "Running **live** tests against Stripe..."
133
+ end
134
+ end
135
+ ```
136
+
119
137
  ## Mocking Card Errors
120
138
 
121
139
  Tired of manually inputting fake credit card numbers to test against errors? Tire no more!
@@ -324,8 +342,8 @@ assign card data to a generated card token:
324
342
  it "generates a stripe card token" do
325
343
  card_token = StripeMock.generate_card_token(last4: "9191", exp_year: 1984)
326
344
 
327
- cus = Stripe::Customer.create(card: card_token)
328
- card = cus.cards.data.first
345
+ cus = Stripe::Customer.create(source: card_token)
346
+ card = cus.sources.data.first
329
347
  expect(card.last4).to eq("9191")
330
348
  expect(card.exp_year).to eq(1984)
331
349
  end
data/lib/stripe_mock.rb CHANGED
@@ -36,11 +36,13 @@ require 'stripe_mock/api/webhooks'
36
36
 
37
37
  require 'stripe_mock/request_handlers/helpers/card_helpers.rb'
38
38
  require 'stripe_mock/request_handlers/helpers/charge_helpers.rb'
39
+ require 'stripe_mock/request_handlers/helpers/coupon_helpers.rb'
39
40
  require 'stripe_mock/request_handlers/helpers/subscription_helpers.rb'
40
41
  require 'stripe_mock/request_handlers/helpers/token_helpers.rb'
41
42
 
42
43
  require 'stripe_mock/request_handlers/validators/param_validators.rb'
43
44
 
45
+ require 'stripe_mock/request_handlers/accounts.rb'
44
46
  require 'stripe_mock/request_handlers/charges.rb'
45
47
  require 'stripe_mock/request_handlers/cards.rb'
46
48
  require 'stripe_mock/request_handlers/sources.rb'
@@ -24,18 +24,30 @@ module StripeMock
24
24
 
25
25
  def self.argument_map
26
26
  @__map ||= {
27
- incorrect_number: ["The card number is incorrect", 'number', 'incorrect_number', 402],
28
- invalid_number: ["The card number is not a valid credit card number", 'number', 'invalid_number', 402],
29
- invalid_expiry_month: ["The card's expiration month is invalid", 'exp_month', 'invalid_expiry_month', 402],
30
- invalid_expiry_year: ["The card's expiration year is invalid", 'exp_year', 'invalid_expiry_year', 402],
31
- invalid_cvc: ["The card's security code is invalid", 'cvc', 'invalid_cvc', 402],
32
- expired_card: ["The card has expired", 'exp_month', 'expired_card', 402],
33
- incorrect_cvc: ["The card's security code is incorrect", 'cvc', 'incorrect_cvc', 402],
34
- card_declined: ["The card was declined", nil, 'card_declined', 402],
35
- missing: ["There is no card on a customer that is being charged.", nil, 'missing', 402],
36
- processing_error: ["An error occurred while processing the card", nil, 'processing_error', 402],
27
+ incorrect_number: add_json_body(["The card number is incorrect", 'number', 'incorrect_number', 402]),
28
+ invalid_number: add_json_body(["The card number is not a valid credit card number", 'number', 'invalid_number', 402]),
29
+ invalid_expiry_month: add_json_body(["The card's expiration month is invalid", 'exp_month', 'invalid_expiry_month', 402]),
30
+ invalid_expiry_year: add_json_body(["The card's expiration year is invalid", 'exp_year', 'invalid_expiry_year', 402]),
31
+ invalid_cvc: add_json_body(["The card's security code is invalid", 'cvc', 'invalid_cvc', 402]),
32
+ expired_card: add_json_body(["The card has expired", 'exp_month', 'expired_card', 402]),
33
+ incorrect_cvc: add_json_body(["The card's security code is incorrect", 'cvc', 'incorrect_cvc', 402]),
34
+ card_declined: add_json_body(["The card was declined", nil, 'card_declined', 402]),
35
+ missing: add_json_body(["There is no card on a customer that is being charged.", nil, 'missing', 402]),
36
+ processing_error: add_json_body(["An error occurred while processing the card", nil, 'processing_error', 402]),
37
+ card_error: add_json_body(['This card number looks invalid.', 'number', 'invalid_number', 402])
37
38
  }
38
39
  end
39
- end
40
40
 
41
+ def self.add_json_body(error_values)
42
+ error_keys = [:message, :param, :code]
43
+
44
+ json_hash = Hash[error_keys.zip error_values]
45
+ json_hash[:type] = 'card_error'
46
+
47
+ error_values.push(error: json_hash) # http_body
48
+ error_values.push(error: json_hash) # json_body
49
+
50
+ error_values
51
+ end
52
+ end
41
53
  end
@@ -4,7 +4,7 @@ module StripeMock
4
4
 
5
5
  fixture_file = File.join(@webhook_fixture_path, "#{type}.json")
6
6
 
7
- if File.exists?(fixture_file) == false
7
+ unless File.exists?(fixture_file)
8
8
  unless Webhooks.event_list.include?(type)
9
9
  raise UnsupportedRequestError.new "Unsupported webhook event `#{type}` (Searched in #{@webhook_fixture_path})"
10
10
  end
@@ -44,9 +44,9 @@ module StripeMock
44
44
  'charge.dispute.created',
45
45
  'charge.dispute.updated',
46
46
  'charge.dispute.closed',
47
- 'customer.card.created',
48
- 'customer.card.deleted',
49
- 'customer.card.updated',
47
+ 'customer.source.created',
48
+ 'customer.source.deleted',
49
+ 'customer.source.updated',
50
50
  'customer.created',
51
51
  'customer.updated',
52
52
  'customer.deleted',
@@ -1,6 +1,24 @@
1
1
  module StripeMock
2
2
  module Data
3
3
 
4
+ def self.mock_account(params = {})
5
+ id = params[:id] || 'acct_103ED82ePvKYlo2C'
6
+ {
7
+ id: id,
8
+ email: "bob@example.com",
9
+ statement_descriptor: nil,
10
+ display_name: "Stripe.com",
11
+ timezone: "US/Pacific",
12
+ details_submitted: false,
13
+ charges_enabled: false,
14
+ transfers_enabled: false,
15
+ currencies_supported: [
16
+ "usd"
17
+ ],
18
+
19
+ }.merge(params)
20
+ end
21
+
4
22
  def self.mock_customer(sources, params)
5
23
  cus_id = params[:id] || "test_cus_default"
6
24
  sources.each {|source| source[:customer] = cus_id}
@@ -41,10 +59,7 @@ module StripeMock
41
59
  amount: 0,
42
60
  currency: "usd",
43
61
  refunded: false,
44
- fee: 0,
45
62
  status: 'succeeded',
46
- fee_details: [
47
- ],
48
63
  source: {
49
64
  object: "card",
50
65
  last4: "4242",
@@ -148,7 +163,6 @@ module StripeMock
148
163
 
149
164
  def self.mock_coupon(params={})
150
165
  {
151
- :duration => 'repeating',
152
166
  :duration_in_months => 3,
153
167
  :percent_off => 25,
154
168
  :amount_off => nil,
@@ -186,6 +200,7 @@ module StripeMock
186
200
  :customer => "c_test_customer",
187
201
  :quantity => 1,
188
202
  :tax_percent => nil,
203
+ :discount => nil,
189
204
  :metadata => {}
190
205
  }, params)
191
206
  end
@@ -40,11 +40,8 @@ module StripeMock
40
40
 
41
41
  def offset
42
42
  if starting_after
43
- if index = data.index { |datum| datum.id == starting_after }
44
- index + 1
45
- else
46
- raise "No such object id: #{starting_after}"
47
- end
43
+ index = data.index { |datum| datum[:id] == starting_after }
44
+ (index || raise("No such object id: #{starting_after}")) + 1
48
45
  else
49
46
  0
50
47
  end
@@ -18,6 +18,7 @@ module StripeMock
18
18
  @@handlers.find {|h| method_url =~ h[:route] }
19
19
  end
20
20
 
21
+ include StripeMock::RequestHandlers::Accounts
21
22
  include StripeMock::RequestHandlers::Charges
22
23
  include StripeMock::RequestHandlers::Cards
23
24
  include StripeMock::RequestHandlers::Sources
@@ -33,12 +34,13 @@ module StripeMock
33
34
  include StripeMock::RequestHandlers::Tokens
34
35
 
35
36
 
36
- attr_reader :bank_tokens, :charges, :coupons, :customers, :events,
37
+ attr_reader :accounts, :bank_tokens, :charges, :coupons, :customers, :events,
37
38
  :invoices, :invoice_items, :plans, :recipients, :transfers, :subscriptions
38
39
 
39
40
  attr_accessor :error_queue, :debug
40
41
 
41
42
  def initialize
43
+ @accounts = {}
42
44
  @bank_tokens = {}
43
45
  @card_tokens = {}
44
46
  @customers = {}
@@ -64,6 +66,8 @@ module StripeMock
64
66
  def mock_request(method, url, api_key, params={}, headers={}, api_base_url=nil)
65
67
  return {} if method == :xtest
66
68
 
69
+ api_key ||= Stripe.api_key
70
+
67
71
  # Ensure params hash has symbols as keys
68
72
  params = Stripe::Util.symbolize_names(params)
69
73
 
@@ -85,8 +89,8 @@ module StripeMock
85
89
  [res, api_key]
86
90
  end
87
91
  else
88
- puts "WARNING: Unrecognized method + url: [#{method} #{url}]"
89
- puts " params: #{params}"
92
+ puts "[StripeMock] Warning : Unrecognized endpoint + method : [#{method} #{url}]"
93
+ puts "[StripeMock] params: #{params}" unless params.empty?
90
94
  [{}, api_key]
91
95
  end
92
96
  end
@@ -0,0 +1,35 @@
1
+ module StripeMock
2
+ module RequestHandlers
3
+ module Accounts
4
+
5
+ def Accounts.included(klass)
6
+ klass.add_handler 'post /v1/accounts', :new_account
7
+ klass.add_handler 'get /v1/account', :get_account
8
+ klass.add_handler 'get /v1/accounts/(.*)', :get_account
9
+ klass.add_handler 'post /v1/accounts/(.*)', :update_account
10
+ klass.add_handler 'get /v1/accounts', :list_accounts
11
+ end
12
+
13
+ def new_account(route, method_url, params, headers)
14
+ params[:id] ||= new_id('acct')
15
+ route =~ method_url
16
+ accounts[ params[:id] ] ||= Data.mock_account(params)
17
+ end
18
+
19
+ def get_account(route, method_url, params, headers)
20
+ route =~ method_url
21
+ Data.mock_account
22
+ end
23
+
24
+ def update_account(route, method_url, params, headers)
25
+ route =~ method_url
26
+ assert_existence :account, $1, accounts[$1]
27
+ accounts[$1].merge!(params)
28
+ end
29
+
30
+ def list_accounts(route, method_url, params, headers)
31
+ Data.mock_list_object(accounts.values, params)
32
+ end
33
+ end
34
+ end
35
+ end
@@ -9,6 +9,7 @@ module StripeMock
9
9
  klass.add_handler 'post /v1/charges/(.*)/capture', :capture_charge
10
10
  klass.add_handler 'post /v1/charges/(.*)/refund', :refund_charge
11
11
  klass.add_handler 'post /v1/charges/(.*)/refunds', :create_refund
12
+ klass.add_handler 'post /v1/charges/(.*)', :update_charge
12
13
  end
13
14
 
14
15
  def new_charge(route, method_url, params, headers)
@@ -32,6 +33,20 @@ module StripeMock
32
33
  charges[id] = Data.mock_charge(params.merge :id => id, :balance_transaction => new_balance_transaction('txn'))
33
34
  end
34
35
 
36
+ def update_charge(route, method_url, params, headers)
37
+ route =~ method_url
38
+ id = $1
39
+
40
+ charge = assert_existence :charge, id, charges[id]
41
+ allowed = allowed_params(params)
42
+ disallowed = params.keys - allowed
43
+ if disallowed.count > 0
44
+ raise Stripe::InvalidRequestError.new("Received unknown parameters: #{disallowed.join(', ')}" , '', 400)
45
+ end
46
+
47
+ charges[id] = charge.merge(params)
48
+ end
49
+
35
50
  def get_charges(route, method_url, params, headers)
36
51
  params[:offset] ||= 0
37
52
  params[:limit] ||= 10
@@ -115,6 +130,19 @@ module StripeMock
115
130
  def require_param(param)
116
131
  raise Stripe::InvalidRequestError.new("Missing required param: #{param}", param.to_s, 400)
117
132
  end
133
+
134
+ def allowed_params(params)
135
+ allowed = [:description, :metadata, :receipt_email, :fraud_details, :shipping]
136
+
137
+ # This is a workaround for the way the Stripe API sends params even when they aren't modified.
138
+ # Stipe will include those params even when they aren't modified.
139
+ allowed << :fee_details if params.has_key?(:fee_details) && params[:fee_details].nil?
140
+ allowed << :source if params.has_key?(:source) && params[:source].empty?
141
+ if params.has_key?(:refunds) && (params[:refunds].empty? ||
142
+ params[:refunds].has_key?(:data) && params[:refunds][:data].nil?)
143
+ allowed << :refunds
144
+ end
145
+ end
118
146
  end
119
147
  end
120
148
  end
@@ -11,17 +11,18 @@ module StripeMock
11
11
 
12
12
  def new_coupon(route, method_url, params, headers)
13
13
  params[:id] ||= new_id('coupon')
14
+ raise Stripe::InvalidRequestError.new('Missing required param: duration', 'coupon', 400) unless params[:duration]
14
15
  coupons[ params[:id] ] = Data.mock_coupon(params)
15
16
  end
16
17
 
17
18
  def get_coupon(route, method_url, params, headers)
18
19
  route =~ method_url
19
- assert_existence :coupon, $1, coupons[$1]
20
+ assert_existence :id, $1, coupons[$1]
20
21
  end
21
22
 
22
23
  def delete_coupon(route, method_url, params, headers)
23
24
  route =~ method_url
24
- assert_existence :coupon, $1, coupons.delete($1)
25
+ assert_existence :id, $1, coupons.delete($1)
25
26
  end
26
27
 
27
28
  def list_coupons(route, method_url, params, headers)
@@ -15,7 +15,16 @@ module StripeMock
15
15
  sources = []
16
16
 
17
17
  if params[:source]
18
- sources << get_card_by_token(params.delete(:source))
18
+ new_card =
19
+ if params[:source].is_a?(Hash)
20
+ unless params[:source][:object] && params[:source][:number] && params[:source][:exp_month] && params[:source][:exp_year]
21
+ raise Stripe::InvalidRequestError.new('You must supply a valid card', nil, 400)
22
+ end
23
+ card_from_params(params[:source])
24
+ else
25
+ get_card_by_token(params.delete(:source))
26
+ end
27
+ sources << new_card
19
28
  params[:default_source] = sources.first[:id]
20
29
  end
21
30
 
@@ -25,7 +34,7 @@ module StripeMock
25
34
  plan_id = params[:plan].to_s
26
35
  plan = assert_existence :plan, plan_id, plans[plan_id]
27
36
 
28
- if params[:default_source].nil? && plan[:trial_period_days].nil? && plan[:amount] != 0
37
+ if params[:default_source].nil? && params[:trial_end].nil? && plan[:trial_period_days].nil? && plan[:amount] != 0
29
38
  raise Stripe::InvalidRequestError.new('You must supply a valid card', nil, 400)
30
39
  end
31
40
 
@@ -36,6 +45,13 @@ module StripeMock
36
45
  raise Stripe::InvalidRequestError.new('Received unknown parameter: trial_end', nil, 400)
37
46
  end
38
47
 
48
+ if params[:coupon]
49
+ coupon = coupons[ params[:coupon] ]
50
+ assert_existence :coupon, params[:coupon], coupon
51
+
52
+ add_coupon_to_customer(customers[params[:id]], coupon)
53
+ end
54
+
39
55
  customers[ params[:id] ]
40
56
  end
41
57
 
@@ -50,6 +66,13 @@ module StripeMock
50
66
  cus[:default_source] = new_card[:id]
51
67
  end
52
68
 
69
+ if params[:coupon]
70
+ coupon = coupons[ params[:coupon] ]
71
+ assert_existence :coupon, params[:coupon], coupon
72
+
73
+ add_coupon_to_customer(cus, coupon)
74
+ end
75
+
53
76
  cus
54
77
  end
55
78