stripe-ruby-mock 1.10.1.7 → 2.0.0

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.
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)