stripe-ruby-mock 1.10.1.7 → 2.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (71) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +1 -0
  3. data/README.md +70 -3
  4. data/Rakefile +1 -1
  5. data/lib/stripe_mock/api/client.rb +1 -0
  6. data/lib/stripe_mock/api/instance.rb +1 -0
  7. data/lib/stripe_mock/api/live.rb +15 -0
  8. data/lib/stripe_mock/api/server.rb +24 -21
  9. data/lib/stripe_mock/api/test_helpers.rb +24 -0
  10. data/lib/stripe_mock/client.rb +4 -8
  11. data/lib/stripe_mock/data.rb +54 -30
  12. data/lib/stripe_mock/instance.rb +15 -5
  13. data/lib/stripe_mock/request_handlers/cards.rb +29 -18
  14. data/lib/stripe_mock/request_handlers/charges.rb +34 -6
  15. data/lib/stripe_mock/request_handlers/coupons.rb +1 -3
  16. data/lib/stripe_mock/request_handlers/customers.rb +3 -9
  17. data/lib/stripe_mock/request_handlers/events.rb +1 -3
  18. data/lib/stripe_mock/request_handlers/helpers/card_helpers.rb +16 -9
  19. data/lib/stripe_mock/request_handlers/helpers/charge_helpers.rb +16 -0
  20. data/lib/stripe_mock/request_handlers/helpers/subscription_helpers.rb +9 -2
  21. data/lib/stripe_mock/request_handlers/helpers/token_helpers.rb +3 -1
  22. data/lib/stripe_mock/request_handlers/invoice_items.rb +32 -2
  23. data/lib/stripe_mock/request_handlers/invoices.rb +7 -3
  24. data/lib/stripe_mock/request_handlers/plans.rb +2 -5
  25. data/lib/stripe_mock/request_handlers/recipients.rb +26 -4
  26. data/lib/stripe_mock/request_handlers/subscriptions.rb +26 -33
  27. data/lib/stripe_mock/request_handlers/tokens.rb +24 -4
  28. data/lib/stripe_mock/request_handlers/validators/param_validators.rb +18 -0
  29. data/lib/stripe_mock/server.rb +4 -5
  30. data/lib/stripe_mock/test_strategies/base.rb +27 -0
  31. data/lib/stripe_mock/test_strategies/live.rb +22 -0
  32. data/lib/stripe_mock/test_strategies/mock.rb +19 -0
  33. data/lib/stripe_mock/util.rb +5 -0
  34. data/lib/stripe_mock/version.rb +1 -1
  35. data/lib/stripe_mock/webhook_fixtures/charge.failed.json +3 -2
  36. data/lib/stripe_mock/webhook_fixtures/charge.refunded.json +16 -9
  37. data/lib/stripe_mock/webhook_fixtures/charge.succeeded.json +3 -2
  38. data/lib/stripe_mock/webhook_fixtures/customer.card.created.json +1 -0
  39. data/lib/stripe_mock/webhook_fixtures/customer.card.deleted.json +1 -0
  40. data/lib/stripe_mock/webhook_fixtures/customer.card.updated.json +1 -0
  41. data/lib/stripe_mock/webhook_fixtures/customer.created.json +1 -0
  42. data/lib/stripe_mock/webhook_fixtures/customer.deleted.json +2 -1
  43. data/lib/stripe_mock/webhook_fixtures/customer.updated.json +1 -0
  44. data/lib/stripe_mock.rb +9 -1
  45. data/spec/fixtures/create_refund.yml +126 -0
  46. data/spec/instance_spec.rb +4 -2
  47. data/spec/integration_examples/charge_token_examples.rb +49 -0
  48. data/spec/integration_examples/customer_card_examples.rb +42 -0
  49. data/spec/integration_examples/prepare_error_examples.rb +18 -0
  50. data/spec/readme_spec.rb +2 -1
  51. data/spec/server_spec.rb +12 -3
  52. data/spec/shared_stripe_examples/card_examples.rb +108 -3
  53. data/spec/shared_stripe_examples/card_token_examples.rb +26 -0
  54. data/spec/shared_stripe_examples/charge_examples.rb +55 -39
  55. data/spec/shared_stripe_examples/coupon_examples.rb +2 -17
  56. data/spec/shared_stripe_examples/customer_examples.rb +30 -39
  57. data/spec/shared_stripe_examples/error_mock_examples.rb +1 -1
  58. data/spec/shared_stripe_examples/invoice_examples.rb +31 -15
  59. data/spec/shared_stripe_examples/invoice_item_examples.rb +62 -10
  60. data/spec/shared_stripe_examples/plan_examples.rb +29 -18
  61. data/spec/shared_stripe_examples/recipient_examples.rb +55 -5
  62. data/spec/shared_stripe_examples/refund_examples.rb +90 -0
  63. data/spec/shared_stripe_examples/subscription_examples.rb +159 -82
  64. data/spec/shared_stripe_examples/validation_examples.rb +19 -0
  65. data/spec/spec_helper.rb +32 -1
  66. data/spec/stripe_mock_spec.rb +70 -0
  67. data/spec/support/stripe_examples.rb +7 -14
  68. data/spec/util_spec.rb +8 -0
  69. data/stripe-ruby-mock.gemspec +2 -2
  70. metadata +38 -34
  71. data/lib/stripe_mock/api/strict.rb +0 -11
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: e0b68df0cf8a9bb5fcc7743fe4dd1983cf4bd0a3
4
+ data.tar.gz: 4a10d0bbbf8b53ebb4dbf86875b4c2cc35191c15
5
+ SHA512:
6
+ metadata.gz: acce1dfcefe02aab720f6ae0b489bd25fbef197d50bc0b4b57971264ce14fbad3c6b42a4cd379d12bba6ada203f81f037e49e11277a7db5af227b023729268db
7
+ data.tar.gz: e206a8a69476fd96a82e42a53f16855ce9645a97b0dee81b6dd714dee78b25a2646f30e2b516908c1529b2df8bddca8dc786945d24951b0631305ba54343ad39
data/.gitignore CHANGED
@@ -3,3 +3,4 @@ pkg/
3
3
  .DS_Store
4
4
  stripe-mock-server.pid
5
5
  Gemfile.lock
6
+ stripe-mock-server.log
data/README.md CHANGED
@@ -8,13 +8,25 @@
8
8
 
9
9
  In your gemfile:
10
10
 
11
- gem 'stripe-ruby-mock', '~> 1.10.1.7'
11
+ gem 'stripe-ruby-mock', '~> 2.0.0'
12
12
 
13
13
  ## Features
14
14
 
15
15
  * No stripe server access required
16
16
  * Easily test against stripe errors
17
17
  * Mock and customize stripe webhooks
18
+ * Flip a switch to run your tests against Stripe's **live test servers**
19
+
20
+ ### Specifications
21
+
22
+ **STRIPE API TARGET VERSION:** 2014-06-17
23
+
24
+ * Strict params: Plan, Token#create
25
+
26
+ ## TODO BEFORE MERGE
27
+
28
+ * Strictify params: Customer#create
29
+ * Require existing card tokens
18
30
 
19
31
  ## Description
20
32
 
@@ -31,6 +43,7 @@ You can use stripe-ruby-mock with any ruby testing library. Here's a quick dummy
31
43
  require 'stripe_mock'
32
44
 
33
45
  describe MyApp do
46
+ let(:stripe_helper) { StripeMock.create_test_helper }
34
47
  before { StripeMock.start }
35
48
  after { StripeMock.stop }
36
49
 
@@ -39,13 +52,65 @@ describe MyApp do
39
52
  # This doesn't touch stripe's servers nor the internet!
40
53
  customer = Stripe::Customer.create({
41
54
  email: 'johnny@appleseed.com',
42
- card: 'void_card_token'
55
+ card: stripe_helper.generate_card_token
43
56
  })
44
57
  expect(customer.email).to eq('johnny@appleseed.com')
45
58
  end
46
59
  end
47
60
  ```
48
61
 
62
+ ## Test Helpers
63
+
64
+ Some Stripe API calls require several parameters. StripeMock helps you keep your test brief with some helpers:
65
+
66
+ ```ruby
67
+ describe MyApp do
68
+ let(:stripe_helper) { StripeMock.create_test_helper }
69
+
70
+ it "creates a stripe plan" do
71
+ plan = stripe_helper.create_plan(:id => 'my_plan', :amount => 1500)
72
+
73
+ # The above line replaces the following:
74
+ # plan = Stripe::Plan.create(
75
+ # :id => 'my_plan',
76
+ # :name => 'StripeMock Default Plan ID',
77
+ # :amount => 1500,
78
+ # :currency => 'usd',
79
+ # :interval => 'month'
80
+ # )
81
+ expect(plan.id).to eq('my_plan')
82
+ expect(plan.amount).to eq(1500)
83
+ end
84
+ end
85
+ ```
86
+
87
+ The [available helpers](lib/stripe_mock/test_strategies/) are:
88
+
89
+ ```ruby
90
+ stripe_helper.create_plan(my_plan_params)
91
+ stripe_helper.delete_plan(my_plan_params)
92
+ stripe_helper.generate_card_token(my_card_params)
93
+ ```
94
+
95
+ For everything else, use Stripe as you normally would (i.e. use Stripe as if you were not using StripeMock).
96
+
97
+ ## Live Testing
98
+
99
+ Every once in a while you want to make sure your tests are actually valid. StripeMock has a switch that allows you to run your test suite (or a subset thereof) against Stripe's live test servers.
100
+
101
+ Here is an example of setting up your RSpec (2.x) test suite to run live with a command line switch:
102
+
103
+ ```ruby
104
+ RSpec.configure do |c|
105
+ if c.filter_manager.inclusions.keys.include?(:live)
106
+ puts "Running **live** tests against Stripe..."
107
+ StripeMock.toggle_live(true)
108
+ end
109
+ end
110
+ ```
111
+
112
+ With this you can run live tests by running `rspec -t live`
113
+
49
114
  ## Mocking Card Errors
50
115
 
51
116
  Tired of manually inputting fake credit card numbers to test against errors? Tire no more!
@@ -97,7 +162,7 @@ customer = Stripe::Customer.create
97
162
  customer.cards.create
98
163
  ```
99
164
 
100
- `:new_charge` and `:create_card` are names of methods in the [StripeMock request handlers](lib/stripe_mock/request_handlers). You can also set `StripeMock.debug(true)` to see the event name for each Stripe request made in your tests.
165
+ `:new_charge` and `:create_card` are names of methods in the [StripeMock request handlers](lib/stripe_mock/request_handlers). You can also set `StripeMock.toggle_debug(true)` to see the event name for each Stripe request made in your tests.
101
166
 
102
167
  ### Custom Errors
103
168
 
@@ -289,6 +354,7 @@ StripeMock.global_id_prefix = 'my_app_'
289
354
  * Cover all stripe urls/methods
290
355
  * Throw useful errors that emulate Stripe's requirements
291
356
  * For example: "You must supply either a card or a customer id" for `Stripe::Charge`
357
+ * Fingerprinting for other resources besides Cards
292
358
 
293
359
  ## Developing stripe-ruby-mock
294
360
 
@@ -296,6 +362,7 @@ To run the tests:
296
362
 
297
363
  $ bundle install
298
364
  $ bundle exec rspec
365
+ $ bundle exec rspec -t live # Runs certain tests against Stripe's servers
299
366
 
300
367
  Patches are welcome and greatly appreciated! If you're contributing to fix a problem,
301
368
  be sure to write tests that illustrate the problem being fixed.
data/Rakefile CHANGED
@@ -14,7 +14,7 @@ rescue LoadError => e
14
14
  end
15
15
 
16
16
  begin
17
- gem 'rspec', '~> 2.4'
17
+ gem 'rspec', '~> 3.1'
18
18
  require 'rspec/core/rake_task'
19
19
 
20
20
  RSpec::Core::RakeTask.new
@@ -3,6 +3,7 @@ module StripeMock
3
3
  def self.client; @client; end
4
4
 
5
5
  def self.start_client(port=4999)
6
+ return false if @state == 'live'
6
7
  return @client unless @client.nil?
7
8
 
8
9
  alias_stripe_method :request, StripeMock.method(:redirect_to_mock_server)
@@ -5,6 +5,7 @@ module StripeMock
5
5
  @original_request_method = Stripe.method(:request)
6
6
 
7
7
  def self.start
8
+ return false if @state == 'live'
8
9
  @instance = Instance.new
9
10
  alias_stripe_method :request, @instance.method(:mock_request)
10
11
  @state = 'local'
@@ -0,0 +1,15 @@
1
+ module StripeMock
2
+
3
+ def self.toggle_live(toggle)
4
+ if @state != 'ready' && @state != 'live'
5
+ raise "You cannot toggle StripeMock live when it has already started."
6
+ end
7
+ if toggle
8
+ @state = 'live'
9
+ StripeMock.set_default_test_helper_strategy(:live)
10
+ else
11
+ @state = 'ready'
12
+ StripeMock.set_default_test_helper_strategy(:mock)
13
+ end
14
+ end
15
+ end
@@ -1,30 +1,33 @@
1
1
  module StripeMock
2
2
 
3
- @default_pid_path = './stripe-mock-server.pid'
4
- @default_log_path = './stripe-mock-server.log'
3
+ @default_server_pid_path = './stripe-mock-server.pid'
4
+ @default_server_log_path = './stripe-mock-server.log'
5
5
 
6
- def self.default_server_pid_path; @default_pid_path; end
7
- def self.default_server_pid_path=(new_path)
8
- @default_pid_path = new_path
9
- end
6
+ class << self
7
+ attr_writer :default_server_pid_path, :default_server_log_path
10
8
 
9
+ ["pid", "log"].each do |config_type|
10
+ define_method("default_server_#{config_type}_path") do
11
+ instance_variable_get("@default_server_#{config_type}_path") || "./stripe-mock-server.#{config_type}"
12
+ end
13
+ end
11
14
 
12
- def self.spawn_server(opts={})
13
- pid_path = opts[:pid_path] || @default_pid_path
14
- log_path = opts[:log_path] || @default_log_path
15
+ def spawn_server(opts={})
16
+ pid_path = opts[:pid_path] || default_server_pid_path
17
+ log_path = opts[:log_path] || default_server_log_path
15
18
 
16
- Dante::Runner.new('stripe-mock-server').execute(
17
- :daemonize => true, :pid_path => pid_path, :log_path => log_path
18
- ){
19
- StripeMock::Server.start_new(opts)
20
- }
21
- at_exit { kill_server(pid_path) }
22
- end
19
+ Dante::Runner.new('stripe-mock-server').execute(
20
+ :daemonize => true, :pid_path => pid_path, :log_path => log_path
21
+ ){
22
+ StripeMock::Server.start_new(opts)
23
+ }
24
+ at_exit { kill_server(pid_path) }
25
+ end
23
26
 
24
- def self.kill_server(pid_path=nil)
25
- puts "Killing server at #{pid_path}"
26
- path = pid_path || @default_pid_path
27
- Dante::Runner.new('stripe-mock-server').execute(:kill => true, :pid_path => path)
27
+ def kill_server(pid_path=nil)
28
+ puts "Killing server at #{pid_path}"
29
+ path = pid_path || default_server_pid_path
30
+ Dante::Runner.new('stripe-mock-server').execute(:kill => true, :pid_path => path)
31
+ end
28
32
  end
29
-
30
33
  end
@@ -0,0 +1,24 @@
1
+ module StripeMock
2
+
3
+ def self.create_test_helper(strategy=nil)
4
+ if strategy
5
+ get_test_helper_strategy(strategy).new
6
+ elsif @__test_strat
7
+ @__test_strat.new
8
+ else
9
+ TestStrategies::Mock.new
10
+ end
11
+ end
12
+
13
+ def self.set_default_test_helper_strategy(strategy)
14
+ @__test_strat = get_test_helper_strategy(strategy)
15
+ end
16
+
17
+ def self.get_test_helper_strategy(strategy)
18
+ case strategy.to_sym
19
+ when :mock then TestStrategies::Mock
20
+ when :live then TestStrategies::Live
21
+ else raise "Invalid test helper strategy: #{strategy.inspect}"
22
+ end
23
+ end
24
+ end
@@ -40,14 +40,6 @@ module StripeMock
40
40
  timeout_wrap { @pipe.debug? }
41
41
  end
42
42
 
43
- def set_server_strict(toggle)
44
- timeout_wrap { @pipe.set_strict(toggle) }
45
- end
46
-
47
- def server_strict?
48
- timeout_wrap { @pipe.strict? }
49
- end
50
-
51
43
  def set_server_global_id_prefix(value)
52
44
  timeout_wrap { @pipe.set_global_id_prefix(value) }
53
45
  end
@@ -68,6 +60,10 @@ module StripeMock
68
60
  timeout_wrap { Stripe::Util.symbolize_names @pipe.generate_webhook_event(event_data) }
69
61
  end
70
62
 
63
+ def destroy_resource(type, id)
64
+ timeout_wrap { @pipe.destroy_resource(type, id) }
65
+ end
66
+
71
67
  def clear_server_data
72
68
  timeout_wrap { @pipe.clear_data }
73
69
  end
@@ -31,8 +31,9 @@ module StripeMock
31
31
  end
32
32
 
33
33
  def self.mock_charge(params={})
34
+ charge_id = params[:id] || "ch_1fD6uiR9FAA2zc"
34
35
  {
35
- id: "ch_1fD6uiR9FAA2zc",
36
+ id: charge_id,
36
37
  object: "charge",
37
38
  created: 1366194027,
38
39
  livemode: false,
@@ -47,6 +48,7 @@ module StripeMock
47
48
  object: "card",
48
49
  last4: "4242",
49
50
  type: "Visa",
51
+ brand: "Visa",
50
52
  exp_month: 12,
51
53
  exp_year: 2013,
52
54
  fingerprint: "3TQGpK9JoY1GgXPw",
@@ -63,29 +65,37 @@ module StripeMock
63
65
  address_zip_check: nil
64
66
  },
65
67
  captured: params.has_key?(:capture) ? params.delete(:capture) : true,
68
+ refunds: {
69
+ object: "list",
70
+ total_count: 0,
71
+ has_more: false,
72
+ url: "/v1/charges/#{charge_id}/refunds",
73
+ data: []
74
+ },
75
+ balance_transaction: "txn_2dyYXXP90MN26R",
66
76
  failure_message: nil,
77
+ failure_code: nil,
67
78
  amount_refunded: 0,
68
79
  customer: nil,
69
80
  invoice: nil,
70
81
  description: nil,
71
- dispute: nil
82
+ dispute: nil,
83
+ metadata: {
84
+ }
72
85
  }.merge(params)
73
86
  end
74
87
 
75
88
  def self.mock_refund(params={})
76
- mock_charge.merge({
77
- refunded: true,
78
- refunds: [
79
- {
80
- amount: params[:amount],
81
- currency: "usd",
82
- created: 1380208998,
83
- object: "refund",
84
- balance_transaction: "txn_2dyYXXP90MN26R"
85
- }
86
- ],
87
- amount_refunded: params[:amount]
88
- })
89
+ {
90
+ id: "re_4fWhgUh5si7InF",
91
+ amount: 1,
92
+ currency: "usd",
93
+ created: 1409165988,
94
+ object: "refund",
95
+ balance_transaction: "txn_4fWh2RKvgxcXqV",
96
+ metadata: {},
97
+ charge: "ch_4fWhYjzQ23UFWT"
98
+ }.merge(params)
89
99
  end
90
100
 
91
101
  def self.mock_charge_array
@@ -102,6 +112,7 @@ module StripeMock
102
112
  object: "card",
103
113
  last4: "4242",
104
114
  type: "Visa",
115
+ brand: "Visa",
105
116
  exp_month: 4,
106
117
  exp_year: 2016,
107
118
  fingerprint: "wXWJT135mEK107G8",
@@ -170,7 +181,8 @@ module StripeMock
170
181
  :trial_start => 1308595038,
171
182
  :trial_end => 1308681468,
172
183
  :customer => "c_test_customer",
173
- :quantity => 1
184
+ :quantity => 1,
185
+ :metadata => {}
174
186
  }, params)
175
187
  end
176
188
 
@@ -230,7 +242,7 @@ module StripeMock
230
242
 
231
243
  def self.mock_invoice_item(params = {})
232
244
  {
233
- id: "ii_test",
245
+ id: "test_ii",
234
246
  object: "invoiceitem",
235
247
  date: 1349738920,
236
248
  amount: 1099,
@@ -279,21 +291,32 @@ module StripeMock
279
291
  }.merge(params)
280
292
  end
281
293
 
282
- def self.mock_recipient(params={})
294
+ def self.mock_recipient(cards, params={})
295
+ rp_id = params[:id] || "test_rp_default"
296
+ cards.each {|card| card[:recipient] = rp_id}
283
297
  {
284
- :name => "Stripe User",
285
- :type => "individual",
286
- :livemode => false,
287
- :object => "recipient",
288
- :id => "rp_test_recipient",
289
- :active_account => {
290
- :last4 => "6789",
291
- :bank_name => "STRIPE TEST BANK",
292
- :country => "US",
293
- :object => "bank_account"
298
+ name: "Stripe User",
299
+ type: "individual",
300
+ livemode: false,
301
+ object: "recipient",
302
+ id: rp_id,
303
+ active_account: {
304
+ last4: "6789",
305
+ bank_name: "STRIPE TEST BANK",
306
+ country: "US",
307
+ object: "bank_account"
308
+ },
309
+ created: 1304114758,
310
+ verified: true,
311
+ metadata: {
312
+ },
313
+ cards: {
314
+ object: "list",
315
+ count: cards.count,
316
+ url: "/v1/recipients/#{rp_id}/cards",
317
+ data: cards
294
318
  },
295
- :created => 1304114758,
296
- :verified => true
319
+ default_card: nil
297
320
  }.merge(params)
298
321
  end
299
322
 
@@ -317,6 +340,7 @@ module StripeMock
317
340
  :object => 'card',
318
341
  :last4 => '2222',
319
342
  :type => 'Visa',
343
+ :brand => 'Visa',
320
344
  :exp_month => 9,
321
345
  :exp_year => 2017,
322
346
  :fingerprint => 'JRRLXGh38NiYygM7',
@@ -2,6 +2,7 @@ module StripeMock
2
2
  class Instance
3
3
 
4
4
  include StripeMock::RequestHandlers::Helpers
5
+ include StripeMock::RequestHandlers::ParamValidators
5
6
 
6
7
  # Handlers are ordered by priority
7
8
  @@handlers = []
@@ -31,9 +32,9 @@ module StripeMock
31
32
 
32
33
 
33
34
  attr_reader :bank_tokens, :charges, :coupons, :customers, :events,
34
- :invoices, :plans, :recipients, :subscriptions
35
+ :invoices, :invoice_items, :plans, :recipients, :subscriptions
35
36
 
36
- attr_accessor :error_queue, :debug, :strict
37
+ attr_accessor :error_queue, :debug
37
38
 
38
39
  def initialize
39
40
  @bank_tokens = {}
@@ -43,6 +44,7 @@ module StripeMock
43
44
  @coupons = {}
44
45
  @events = {}
45
46
  @invoices = {}
47
+ @invoice_items = {}
46
48
  @plans = {}
47
49
  @recipients = {}
48
50
  @subscriptions = {}
@@ -50,7 +52,10 @@ module StripeMock
50
52
  @debug = false
51
53
  @error_queue = ErrorQueue.new
52
54
  @id_counter = 0
53
- @strict = true
55
+ @balance_transaction_counter = 0
56
+
57
+ # This is basically a cache for ParamValidators
58
+ @base_strategy = TestStrategies::Base.new
54
59
  end
55
60
 
56
61
  def mock_request(method, url, api_key, params={}, headers={})
@@ -63,6 +68,7 @@ module StripeMock
63
68
 
64
69
  if handler = Instance.handler_for_method_url(method_url)
65
70
  if @debug == true
71
+ puts "- - - - " * 8
66
72
  puts "[StripeMock req]::#{handler[:name]} #{method} #{url}"
67
73
  puts " #{params}"
68
74
  end
@@ -90,12 +96,11 @@ module StripeMock
90
96
  private
91
97
 
92
98
  def assert_existance(type, id, obj, message=nil)
93
- return unless @strict == true
94
-
95
99
  if obj.nil?
96
100
  msg = message || "No such #{type}: #{id}"
97
101
  raise Stripe::InvalidRequestError.new(msg, type.to_s, 404)
98
102
  end
103
+ obj
99
104
  end
100
105
 
101
106
  def new_id(prefix)
@@ -103,6 +108,11 @@ module StripeMock
103
108
  "#{StripeMock.global_id_prefix}#{prefix}_#{@id_counter += 1}"
104
109
  end
105
110
 
111
+ def new_balance_transaction(prefix)
112
+ # balance transaction ids must be strings
113
+ "#{StripeMock.global_id_prefix}#{prefix}_#{@balance_transaction_counter += 1}"
114
+ end
115
+
106
116
  def symbolize_names(hash)
107
117
  Stripe::Util.symbolize_names(hash)
108
118
  end
@@ -3,53 +3,64 @@ module StripeMock
3
3
  module Cards
4
4
 
5
5
  def Cards.included(klass)
6
+ klass.add_handler 'get /v1/customers/(.*)/cards', :retrieve_cards
6
7
  klass.add_handler 'post /v1/customers/(.*)/cards', :create_card
7
8
  klass.add_handler 'get /v1/customers/(.*)/cards/(.*)', :retrieve_card
8
9
  klass.add_handler 'delete /v1/customers/(.*)/cards/(.*)', :delete_card
9
10
  klass.add_handler 'post /v1/customers/(.*)/cards/(.*)', :update_card
11
+ klass.add_handler 'get /v1/recipients/(.*)/cards/(.*)', :retrieve_recipient_card
10
12
  end
11
13
 
12
14
  def create_card(route, method_url, params, headers)
13
15
  route =~ method_url
14
-
15
- customer = customers[$1]
16
- assert_existance :customer, $1, customer
16
+ customer = assert_existance :customer, $1, customers[$1]
17
17
 
18
18
  card = card_from_params(params[:card])
19
- add_card_to_customer(card, customer)
19
+ add_card_to_object(:customer, card, customer)
20
+ end
21
+
22
+ def retrieve_cards(route, method_url, params, headers)
23
+ route =~ method_url
24
+ customer = assert_existance :customer, $1, customers[$1]
25
+
26
+ cards = customer[:cards]
27
+ cards[:count] = cards[:data].length
28
+ cards
20
29
  end
21
30
 
22
31
  def retrieve_card(route, method_url, params, headers)
23
32
  route =~ method_url
33
+ customer = assert_existance :customer, $1, customers[$1]
24
34
 
25
- customer = customers[$1]
26
- assert_existance :customer, $1, customer
27
- card = get_customer_card(customer, $2)
28
- assert_existance :card, $2, card
29
- card
35
+ assert_existance :card, $2, get_card(customer, $2)
36
+ end
37
+
38
+ def retrieve_recipient_card(route, method_url, params, headers)
39
+ route =~ method_url
40
+ recipient = assert_existance :recipient, $1, recipients[$1]
41
+
42
+ assert_existance :card, $2, get_card(recipient, $2, "Recipient")
30
43
  end
31
44
 
32
45
  def delete_card(route, method_url, params, headers)
33
46
  route =~ method_url
47
+ customer = assert_existance :customer, $1, customers[$1]
48
+
49
+ assert_existance :card, $2, get_card(customer, $2)
34
50
 
35
- customer = customers[$1]
36
- assert_existance :customer, $1, customer
37
- card = get_customer_card(customer, $2)
38
- assert_existance :card, $2, card
39
51
  card = { id: $2, deleted: true }
40
- customer[:cards][:data].reject!{|cc|
52
+ customer[:cards][:data].reject!{|cc|
41
53
  cc[:id] == card[:id]
42
54
  }
55
+ customer[:default_card] = customer[:cards][:data].count > 0 ? customer[:cards][:data].first[:id] : nil
43
56
  card
44
57
  end
45
58
 
46
59
  def update_card(route, method_url, params, headers)
47
60
  route =~ method_url
61
+ customer = assert_existance :customer, $1, customers[$1]
48
62
 
49
- customer = customers[$1]
50
- assert_existance :customer, $1, customer
51
- card = get_customer_card(customer, $2)
52
- assert_existance :card, $2, card
63
+ card = assert_existance :card, $2, get_card(customer, $2)
53
64
  card.merge!(params)
54
65
  card
55
66
  end
@@ -8,6 +8,7 @@ module StripeMock
8
8
  klass.add_handler 'get /v1/charges/(.*)', :get_charge
9
9
  klass.add_handler 'post /v1/charges/(.*)/capture', :capture_charge
10
10
  klass.add_handler 'post /v1/charges/(.*)/refund', :refund_charge
11
+ klass.add_handler 'post /v1/charges/(.*)/refunds', :create_refund
11
12
  end
12
13
 
13
14
  def new_charge(route, method_url, params, headers)
@@ -15,9 +16,11 @@ module StripeMock
15
16
 
16
17
  if params[:card] && params[:card].is_a?(String)
17
18
  params[:card] = get_card_by_token(params[:card])
19
+ elsif params[:card] && params[:card][:id]
20
+ raise Stripe::InvalidRequestError.new("Invalid token id: #{params[:card]}", 'card', 400)
18
21
  end
19
22
 
20
- charges[id] = Data.mock_charge(params.merge :id => id)
23
+ charges[id] = Data.mock_charge(params.merge :id => id, :balance_transaction => new_balance_transaction('txn'))
21
24
  end
22
25
 
23
26
  def get_charges(route, method_url, params, headers)
@@ -36,21 +39,46 @@ module StripeMock
36
39
  def get_charge(route, method_url, params, headers)
37
40
  route =~ method_url
38
41
  assert_existance :charge, $1, charges[$1]
39
- charges[$1] ||= Data.mock_charge(:id => $1)
40
42
  end
41
43
 
42
44
  def capture_charge(route, method_url, params, headers)
43
45
  route =~ method_url
44
- charge = charges[$1]
45
- assert_existance :charge, $1, charge
46
+ charge = assert_existance :charge, $1, charges[$1]
47
+
48
+ if params[:amount]
49
+ refund = Data.mock_refund(
50
+ :balance_transaction => new_balance_transaction('txn'),
51
+ :id => new_id('re'),
52
+ :amount => charge[:amount] - params[:amount]
53
+ )
54
+ add_refund_to_charge(refund, charge)
55
+ end
46
56
 
47
57
  charge[:captured] = true
48
58
  charge
49
59
  end
50
60
 
51
61
  def refund_charge(route, method_url, params, headers)
52
- route =~ method_url
53
- charge = Data.mock_refund(params)
62
+ charge = get_charge(route, method_url, params, headers)
63
+
64
+ refund = Data.mock_refund params.merge(
65
+ :balance_transaction => new_balance_transaction('txn'),
66
+ :id => new_id('re')
67
+ )
68
+ add_refund_to_charge(refund, charge)
69
+ charge
70
+ end
71
+
72
+ def create_refund(route, method_url, params, headers)
73
+ charge = get_charge(route, method_url, params, headers)
74
+
75
+ refund = Data.mock_refund params.merge(
76
+ :balance_transaction => new_balance_transaction('txn'),
77
+ :id => new_id('re'),
78
+ :charge => charge[:id]
79
+ )
80
+ add_refund_to_charge(refund, charge)
81
+ refund
54
82
  end
55
83
 
56
84
  end
@@ -17,13 +17,11 @@ module StripeMock
17
17
  def get_coupon(route, method_url, params, headers)
18
18
  route =~ method_url
19
19
  assert_existance :coupon, $1, coupons[$1]
20
- coupons[$1] ||= Data.mock_coupon(:id => $1)
21
20
  end
22
21
 
23
22
  def delete_coupon(route, method_url, params, headers)
24
23
  route =~ method_url
25
- assert_existance :coupon, $1, coupons[$1]
26
- coupons.delete($1)
24
+ assert_existance :coupon, $1, coupons.delete($1)
27
25
  end
28
26
 
29
27
  def list_coupons(route, method_url, params, headers)