stripe-ruby-mock 2.4.0 → 2.5.8

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 (98) hide show
  1. checksums.yaml +4 -4
  2. data/.env +2 -0
  3. data/.travis.yml +8 -4
  4. data/README.md +12 -5
  5. data/lib/stripe_mock/api/account_balance.rb +14 -0
  6. data/lib/stripe_mock/api/client.rb +4 -4
  7. data/lib/stripe_mock/api/conversion_rate.rb +14 -0
  8. data/lib/stripe_mock/api/errors.rb +25 -14
  9. data/lib/stripe_mock/api/instance.rb +6 -6
  10. data/lib/stripe_mock/api/webhooks.rb +5 -1
  11. data/lib/stripe_mock/client.rb +18 -2
  12. data/lib/stripe_mock/data/list.rb +14 -2
  13. data/lib/stripe_mock/data.rb +217 -56
  14. data/lib/stripe_mock/instance.rb +93 -8
  15. data/lib/stripe_mock/request_handlers/accounts.rb +34 -2
  16. data/lib/stripe_mock/request_handlers/balance.rb +17 -0
  17. data/lib/stripe_mock/request_handlers/balance_transactions.rb +18 -2
  18. data/lib/stripe_mock/request_handlers/charges.rb +25 -17
  19. data/lib/stripe_mock/request_handlers/coupons.rb +5 -4
  20. data/lib/stripe_mock/request_handlers/customers.rb +26 -8
  21. data/lib/stripe_mock/request_handlers/ephemeral_key.rb +13 -0
  22. data/lib/stripe_mock/request_handlers/external_accounts.rb +55 -0
  23. data/lib/stripe_mock/request_handlers/helpers/bank_account_helpers.rb +1 -1
  24. data/lib/stripe_mock/request_handlers/helpers/card_helpers.rb +9 -7
  25. data/lib/stripe_mock/request_handlers/helpers/coupon_helpers.rb +10 -6
  26. data/lib/stripe_mock/request_handlers/helpers/external_account_helpers.rb +49 -0
  27. data/lib/stripe_mock/request_handlers/helpers/subscription_helpers.rb +55 -15
  28. data/lib/stripe_mock/request_handlers/helpers/token_helpers.rb +2 -2
  29. data/lib/stripe_mock/request_handlers/invoices.rb +93 -14
  30. data/lib/stripe_mock/request_handlers/orders.rb +5 -5
  31. data/lib/stripe_mock/request_handlers/payouts.rb +32 -0
  32. data/lib/stripe_mock/request_handlers/plans.rb +1 -0
  33. data/lib/stripe_mock/request_handlers/products.rb +43 -0
  34. data/lib/stripe_mock/request_handlers/refunds.rb +10 -7
  35. data/lib/stripe_mock/request_handlers/subscription_items.rb +36 -0
  36. data/lib/stripe_mock/request_handlers/subscriptions.rb +95 -34
  37. data/lib/stripe_mock/request_handlers/tax_rates.rb +36 -0
  38. data/lib/stripe_mock/request_handlers/tokens.rb +9 -3
  39. data/lib/stripe_mock/request_handlers/transfers.rb +11 -5
  40. data/lib/stripe_mock/request_handlers/validators/param_validators.rb +10 -1
  41. data/lib/stripe_mock/server.rb +14 -1
  42. data/lib/stripe_mock/test_strategies/base.rb +7 -5
  43. data/lib/stripe_mock/test_strategies/live.rb +5 -0
  44. data/lib/stripe_mock/test_strategies/mock.rb +8 -0
  45. data/lib/stripe_mock/util.rb +8 -2
  46. data/lib/stripe_mock/version.rb +1 -1
  47. data/lib/stripe_mock/webhook_fixtures/account.updated.json +1 -1
  48. data/lib/stripe_mock/webhook_fixtures/charge.dispute.funds_reinstated.json +88 -0
  49. data/lib/stripe_mock/webhook_fixtures/charge.dispute.funds_withdrawn.json +88 -0
  50. data/lib/stripe_mock/webhook_fixtures/charge.updated.json +58 -0
  51. data/lib/stripe_mock/webhook_fixtures/customer.subscription.created.json +40 -10
  52. data/lib/stripe_mock/webhook_fixtures/customer.subscription.deleted.json +39 -10
  53. data/lib/stripe_mock/webhook_fixtures/customer.subscription.trial_will_end.json +39 -10
  54. data/lib/stripe_mock/webhook_fixtures/customer.subscription.updated.json +40 -11
  55. data/lib/stripe_mock/webhook_fixtures/invoice.created.json +3 -2
  56. data/lib/stripe_mock/webhook_fixtures/invoice.payment_failed.json +1 -1
  57. data/lib/stripe_mock/webhook_fixtures/invoice.payment_succeeded.json +92 -85
  58. data/lib/stripe_mock/webhook_fixtures/invoice.updated.json +3 -2
  59. data/lib/stripe_mock/webhook_fixtures/plan.created.json +1 -1
  60. data/lib/stripe_mock/webhook_fixtures/plan.deleted.json +1 -1
  61. data/lib/stripe_mock/webhook_fixtures/plan.updated.json +1 -1
  62. data/lib/stripe_mock.rb +13 -0
  63. data/spec/instance_spec.rb +54 -4
  64. data/spec/integration_examples/prepare_error_examples.rb +6 -6
  65. data/spec/list_spec.rb +16 -3
  66. data/spec/readme_spec.rb +2 -0
  67. data/spec/server_spec.rb +6 -2
  68. data/spec/shared_stripe_examples/account_examples.rb +35 -0
  69. data/spec/shared_stripe_examples/balance_examples.rb +11 -0
  70. data/spec/shared_stripe_examples/balance_transaction_examples.rb +28 -0
  71. data/spec/shared_stripe_examples/bank_examples.rb +28 -1
  72. data/spec/shared_stripe_examples/card_examples.rb +10 -3
  73. data/spec/shared_stripe_examples/charge_examples.rb +73 -17
  74. data/spec/shared_stripe_examples/coupon_examples.rb +8 -2
  75. data/spec/shared_stripe_examples/customer_examples.rb +54 -2
  76. data/spec/shared_stripe_examples/dispute_examples.rb +19 -8
  77. data/spec/shared_stripe_examples/ephemeral_key_examples.rb +17 -0
  78. data/spec/shared_stripe_examples/error_mock_examples.rb +3 -3
  79. data/spec/shared_stripe_examples/external_account_examples.rb +170 -0
  80. data/spec/shared_stripe_examples/extra_features_examples.rb +2 -0
  81. data/spec/shared_stripe_examples/invoice_examples.rb +314 -51
  82. data/spec/shared_stripe_examples/payout_examples.rb +68 -0
  83. data/spec/shared_stripe_examples/plan_examples.rb +37 -5
  84. data/spec/shared_stripe_examples/product_example.rb +65 -0
  85. data/spec/shared_stripe_examples/recipient_examples.rb +7 -7
  86. data/spec/shared_stripe_examples/refund_examples.rb +17 -11
  87. data/spec/shared_stripe_examples/subscription_examples.rb +463 -33
  88. data/spec/shared_stripe_examples/subscription_items_examples.rb +75 -0
  89. data/spec/shared_stripe_examples/tax_rate_examples.rb +42 -0
  90. data/spec/shared_stripe_examples/transfer_examples.rb +72 -23
  91. data/spec/shared_stripe_examples/webhook_event_examples.rb +74 -5
  92. data/spec/spec_helper.rb +7 -6
  93. data/spec/stripe_mock_spec.rb +16 -3
  94. data/spec/support/stripe_examples.rb +7 -1
  95. data/spec/util_spec.rb +35 -1
  96. data/stripe-ruby-mock.gemspec +1 -1
  97. metadata +34 -7
  98. data/ChangeLog.rdoc +0 -4
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 2dc4a01998c2f9e1cd85aee1281cf75d5b4aa436
4
- data.tar.gz: 045708a8af619fc7b299055f0822eed79f8cae1f
3
+ metadata.gz: a15c09639e0a93df5b15cc5a45646c0fb189460e
4
+ data.tar.gz: b8cdf0692aba8099229f66e1906e691dd40075aa
5
5
  SHA512:
6
- metadata.gz: 918999885f3cf5e32133f85b535e76ecbe7c482b106b4fe70e9a8de03fcd95132bfd4d43496bc397492da84bfb5eded5c46807e70c2562ee38923e202bf6dd89
7
- data.tar.gz: b9ab01a438f10f7148470641a0b0fddcd32b0fedfc28969a8f52020d483ed64e045e384f1acda6ec422680c54f34c36ace6dcb89b2a01949053e96269e9953a6
6
+ metadata.gz: 9d70a5de8ae26c090632d00c1013d5ca63933fee41e40561b2e713b511a1c1347b21485b1d1c4eb8ee6837b6f4ec9a9f8e857a7bfa0785ac2182b8190180bfbb
7
+ data.tar.gz: 542f7a6f6c8743269e0337c1fc0b4fabef97003fe4d945c077ab4e16fe908bf7c21996dcb8c25ade7a4975a273a51972621d8d997e35a86f00dcb5287ae63d89
data/.env ADDED
@@ -0,0 +1,2 @@
1
+ STRIPE_TEST_SECRET_KEY=sk_test_eFvAvN5rz4GqAbsWxg63Jx79
2
+ STRIPE_TEST_OAUTH_ACCESS_TOKEN=sk_test_WnZmEBIHhMcDltNe98sqWN7z
data/.travis.yml CHANGED
@@ -1,10 +1,14 @@
1
+ dist: trusty
2
+ group: deprecated-2017Q2
3
+ sudo: required
1
4
  language: ruby
2
5
  rvm:
3
- - 1.9.3
4
6
  - 2.0.0
5
- - 2.1.6
7
+ - 2.1.10
8
+ - 2.2.7
9
+ - 2.3.4
6
10
  before_install:
7
- - rvm 1.9.3 do gem install mime-types -v 2.6.2
11
+ - rvm 2.1.10 do gem install mime-types -v 2.6.2
8
12
  - gem install bundler
9
13
  before_script:
10
14
  - "sudo touch /var/log/stripe-mock-server.log"
@@ -13,7 +17,7 @@ script: "bundle exec rspec && bundle exec rspec -t live"
13
17
 
14
18
  env:
15
19
  global:
16
- - 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
20
+ - IS_TRAVIS=true STRIPE_TEST_SECRET_KEY_A=sk_test_Ut2MSlZANdT3iDALdGhyLymy STRIPE_TEST_SECRET_KEY_B=sk_test_JXtzss9tHOG1ofIyEZgoUP4Q STRIPE_TEST_SECRET_KEY_C=sk_test_ZR5nVz9p3ivsqVa7mYB0sFep STRIPE_TEST_SECRET_KEY_D=sk_test_ZR5nVz9p3ivsqVa7mYB0sFep
17
21
 
18
22
  notifications:
19
23
  webhooks:
data/README.md CHANGED
@@ -12,7 +12,7 @@ This gem has unexpectedly grown in popularity and I've gotten pretty busy, so I'
12
12
 
13
13
  In your gemfile:
14
14
 
15
- gem 'stripe-ruby-mock', '~> 2.4.0', :require => 'stripe_mock'
15
+ gem 'stripe-ruby-mock', '~> 2.5.8', :require => 'stripe_mock'
16
16
 
17
17
  ## Features
18
18
 
@@ -21,12 +21,18 @@ In your gemfile:
21
21
  * Mock and customize stripe webhooks
22
22
  * Flip a switch to run your tests against Stripe's **live test servers**
23
23
 
24
+ ### Requirements
25
+
26
+ * ruby >= 2.0.0
27
+ * stripe >= 2.0.3
28
+
24
29
  ### Specifications
25
30
 
26
- **STRIPE API TARGET VERSION:** 2015-09-08 (master)
31
+ **STRIPE API TARGET VERSION:** 2017-06-05 (master)
27
32
 
28
33
  Older API version branches:
29
34
 
35
+ - api-2015-09-08 - use gem version 2.4.1
30
36
  - [api-2014-06-17](https://github.com/rebelidealist/stripe-ruby-mock/tree/api-2014-06-17)
31
37
 
32
38
  ### Versioning System
@@ -62,7 +68,7 @@ describe MyApp do
62
68
  # Specify :source in place of :card (with same value) to return customer with source data
63
69
  customer = Stripe::Customer.create({
64
70
  email: 'johnny@appleseed.com',
65
- card: stripe_helper.generate_card_token
71
+ source: stripe_helper.generate_card_token
66
72
  })
67
73
  expect(customer.email).to eq('johnny@appleseed.com')
68
74
  end
@@ -164,6 +170,7 @@ StripeMock.prepare_card_error(:incorrect_cvc)
164
170
  StripeMock.prepare_card_error(:card_declined)
165
171
  StripeMock.prepare_card_error(:missing)
166
172
  StripeMock.prepare_card_error(:processing_error)
173
+ StripeMock.prepare_card_error(:incorrect_zip)
167
174
  ```
168
175
 
169
176
  You can see the details of each error in [lib/stripe_mock/api/errors.rb](lib/stripe_mock/api/errors.rb)
@@ -294,9 +301,9 @@ it "mocks a stripe webhook" do
294
301
  end
295
302
 
296
303
  it "mocks stripe connect webhooks" do
297
- event = StripeMock.mock_webhook_event('customer.created', user_id: 'acc_123123')
304
+ event = StripeMock.mock_webhook_event('customer.created', account: 'acc_123123')
298
305
 
299
- expect(event.user_id).to eq('acc_123123')
306
+ expect(event.account).to eq('acc_123123')
300
307
  end
301
308
  ```
302
309
 
@@ -0,0 +1,14 @@
1
+ module StripeMock
2
+
3
+ def self.set_account_balance(value)
4
+ case @state
5
+ when 'local'
6
+ instance.account_balance = value
7
+ when 'remote'
8
+ client.set_account_balance(value)
9
+ else
10
+ raise UnstartedStateError
11
+ end
12
+ end
13
+
14
+ end
@@ -8,7 +8,7 @@ module StripeMock
8
8
  return false if @state == 'live'
9
9
  return @client unless @client.nil?
10
10
 
11
- alias_stripe_method :request, StripeMock.method(:redirect_to_mock_server)
11
+ Stripe::StripeClient.send(:define_method, :execute_request) { |*args| StripeMock.redirect_to_mock_server(*args) }
12
12
  @client = StripeMock::Client.new(port)
13
13
  @state = 'remote'
14
14
  @client
@@ -18,7 +18,7 @@ module StripeMock
18
18
  return false unless @state == 'remote'
19
19
  @state = 'ready'
20
20
 
21
- alias_stripe_method :request, @original_request_method
21
+ restore_stripe_execute_request_method
22
22
  @client.clear_server_data if opts[:clear_server_data] == true
23
23
  @client.cleanup
24
24
  @client = nil
@@ -27,7 +27,7 @@ module StripeMock
27
27
 
28
28
  private
29
29
 
30
- def self.redirect_to_mock_server(method, url, api_key, params={}, headers={}, api_base_url=nil)
30
+ def self.redirect_to_mock_server(method, url, api_key: nil, api_base: nil, params: {}, headers: {})
31
31
  handler = Instance.handler_for_method_url("#{method} #{url}")
32
32
 
33
33
  if mock_error = client.error_queue.error_for_handler_name(handler[:name])
@@ -35,7 +35,7 @@ module StripeMock
35
35
  raise mock_error
36
36
  end
37
37
 
38
- Stripe::Util.symbolize_names client.mock_request(method, url, api_key, params, headers)
38
+ Stripe::Util.symbolize_names client.mock_request(method, url, api_key: api_key, params: params, headers: headers)
39
39
  end
40
40
 
41
41
  end
@@ -0,0 +1,14 @@
1
+ module StripeMock
2
+
3
+ def self.set_conversion_rate(value)
4
+ case @state
5
+ when 'local'
6
+ instance.conversion_rate = value
7
+ when 'remote'
8
+ client.set_conversion_rate(value)
9
+ else
10
+ raise UnstartedStateError
11
+ end
12
+ end
13
+
14
+ end
@@ -24,29 +24,40 @@ module StripeMock
24
24
 
25
25
  def self.argument_map
26
26
  @__map ||= {
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(['The card number is not a valid credit card number.', 'number', 'invalid_number', 402]),
38
- incorrect_zip: add_json_body(['The zip code you supplied failed validation.', 'address_zip', 'incorrect_zip', 402])
27
+ incorrect_number: add_json_body(["The card number is incorrect", 'number', 'incorrect_number', http_status: 402]),
28
+ invalid_number: add_json_body(["The card number is not a valid credit card number", 'number', 'invalid_number', http_status: 402]),
29
+ invalid_expiry_month: add_json_body(["The card's expiration month is invalid", 'exp_month', 'invalid_expiry_month', http_status: 402]),
30
+ invalid_expiry_year: add_json_body(["The card's expiration year is invalid", 'exp_year', 'invalid_expiry_year', http_status: 402]),
31
+ invalid_cvc: add_json_body(["The card's security code is invalid", 'cvc', 'invalid_cvc', http_status: 402]),
32
+ expired_card: add_json_body(["The card has expired", 'exp_month', 'expired_card', http_status: 402]),
33
+ incorrect_cvc: add_json_body(["The card's security code is incorrect", 'cvc', 'incorrect_cvc', http_status: 402]),
34
+ card_declined: add_json_body(["The card was declined", nil, 'card_declined', http_status: 402]),
35
+ missing: add_json_body(["There is no card on a customer that is being charged.", nil, 'missing', http_status: 402]),
36
+ processing_error: add_json_body(["An error occurred while processing the card", nil, 'processing_error', http_status: 402]),
37
+ card_error: add_json_body(['The card number is not a valid credit card number.', 'number', 'invalid_number', http_status: 402]),
38
+ incorrect_zip: add_json_body(['The zip code you supplied failed validation.', 'address_zip', 'incorrect_zip', http_status: 402])
39
39
  }
40
40
  end
41
41
 
42
+ def self.get_decline_code(code)
43
+ decline_code_map = {
44
+ card_declined: 'do_not_honor',
45
+ missing: nil
46
+ }
47
+ decline_code_map.default = code.to_s
48
+
49
+ code_key = code.to_sym
50
+ decline_code_map[code_key]
51
+ end
52
+
42
53
  def self.add_json_body(error_values)
43
54
  error_keys = [:message, :param, :code]
44
55
 
45
56
  json_hash = Hash[error_keys.zip error_values]
46
57
  json_hash[:type] = 'card_error'
58
+ json_hash[:decline_code] = get_decline_code(json_hash[:code])
47
59
 
48
- error_values.push(error: json_hash) # http_body
49
- error_values.push(error: json_hash) # json_body
60
+ error_values.last.merge!(json_body: { error: json_hash }, http_body: { error: json_hash })
50
61
 
51
62
  error_values
52
63
  end
@@ -2,18 +2,18 @@ module StripeMock
2
2
 
3
3
  @state = 'ready'
4
4
  @instance = nil
5
- @original_request_method = Stripe.method(:request)
5
+ @original_execute_request_method = Stripe::StripeClient.instance_method(:execute_request)
6
6
 
7
7
  def self.start
8
8
  return false if @state == 'live'
9
- @instance = Instance.new
10
- alias_stripe_method :request, @instance.method(:mock_request)
9
+ @instance = instance = Instance.new
10
+ Stripe::StripeClient.send(:define_method, :execute_request) { |*args| instance.mock_request(*args) }
11
11
  @state = 'local'
12
12
  end
13
13
 
14
14
  def self.stop
15
15
  return unless @state == 'local'
16
- alias_stripe_method :request, @original_request_method
16
+ restore_stripe_execute_request_method
17
17
  @instance = nil
18
18
  @state = 'ready'
19
19
  end
@@ -28,8 +28,8 @@ module StripeMock
28
28
  end
29
29
  end
30
30
 
31
- def self.alias_stripe_method(new_name, method_object)
32
- Stripe.define_singleton_method(new_name) {|*args| method_object.call(*args) }
31
+ def self.restore_stripe_execute_request_method
32
+ Stripe::StripeClient.send(:define_method, :execute_request, @original_execute_request_method)
33
33
  end
34
34
 
35
35
  def self.instance; @instance; end
@@ -15,9 +15,10 @@ module StripeMock
15
15
 
16
16
  json = Stripe::Util.symbolize_names(json)
17
17
  params = Stripe::Util.symbolize_names(params)
18
- json[:user_id] = params.delete(:user_id) if params.key?(:user_id)
18
+ json[:account] = params.delete(:account) if params.key?(:account)
19
19
  json[:data][:object] = Util.rmerge(json[:data][:object], params)
20
20
  json.delete(:id)
21
+ json[:created] = params[:created] || Time.now.to_i
21
22
 
22
23
  if @state == 'local'
23
24
  event_data = instance.generate_webhook_event(json)
@@ -43,11 +44,14 @@ module StripeMock
43
44
  'account.external_account.deleted',
44
45
  'balance.available',
45
46
  'charge.succeeded',
47
+ 'charge.updated',
46
48
  'charge.failed',
47
49
  'charge.refunded',
48
50
  'charge.dispute.created',
49
51
  'charge.dispute.updated',
50
52
  'charge.dispute.closed',
53
+ 'charge.dispute.funds_reinstated',
54
+ 'charge.dispute.funds_withdrawn',
51
55
  'customer.source.created',
52
56
  'customer.source.deleted',
53
57
  'customer.source.updated',
@@ -13,9 +13,9 @@ module StripeMock
13
13
  @state = 'ready'
14
14
  end
15
15
 
16
- def mock_request(method, url, api_key, params={}, headers={})
16
+ def mock_request(method, url, api_key: nil, params: {}, headers: {})
17
17
  timeout_wrap do
18
- @pipe.mock_request(method, url, api_key, params, headers).tap {|result|
18
+ @pipe.mock_request(method, url, api_key: api_key, params: params, headers: headers).tap {|result|
19
19
  response, api_key = result
20
20
  if response.is_a?(Hash) && response[:error_raised] == 'invalid_request'
21
21
  raise Stripe::InvalidRequestError.new(*response[:error_params])
@@ -65,6 +65,18 @@ module StripeMock
65
65
  timeout_wrap { Stripe::Util.symbolize_names @pipe.generate_webhook_event(event_data) }
66
66
  end
67
67
 
68
+ def get_conversion_rate
69
+ timeout_wrap { @pipe.get_data(:conversion_rate) }
70
+ end
71
+
72
+ def set_conversion_rate(value)
73
+ timeout_wrap { @pipe.set_conversion_rate(value) }
74
+ end
75
+
76
+ def set_account_balance(value)
77
+ timeout_wrap { @pipe.set_account_balance(value) }
78
+ end
79
+
68
80
  def destroy_resource(type, id)
69
81
  timeout_wrap { @pipe.destroy_resource(type, id) }
70
82
  end
@@ -73,6 +85,10 @@ module StripeMock
73
85
  timeout_wrap { @pipe.clear_data }
74
86
  end
75
87
 
88
+ def upsert_stripe_object(object, attributes)
89
+ timeout_wrap { @pipe.upsert_stripe_object(object, attributes) }
90
+ end
91
+
76
92
  def close!
77
93
  self.cleanup
78
94
  StripeMock.stop_client(:clear_server_data => false)
@@ -1,12 +1,20 @@
1
1
  module StripeMock
2
2
  module Data
3
3
  class List
4
- attr_reader :data, :limit, :offset, :starting_after
4
+ attr_reader :data, :limit, :offset, :starting_after, :ending_before
5
5
 
6
6
  def initialize(data, options = {})
7
7
  @data = Array(data.clone)
8
8
  @limit = [[options[:limit] || 10, 100].min, 1].max # restrict @limit to 1..100
9
9
  @starting_after = options[:starting_after]
10
+ @ending_before = options[:ending_before]
11
+ if @data.first.is_a?(Hash) && @data.first[:created]
12
+ @data.sort_by! { |x| x[:created] }
13
+ @data.reverse!
14
+ elsif @data.first.respond_to?(:created)
15
+ @data.sort_by { |x| x.created }
16
+ @data.reverse!
17
+ end
10
18
  end
11
19
 
12
20
  def url
@@ -39,9 +47,13 @@ module StripeMock
39
47
  private
40
48
 
41
49
  def offset
42
- if starting_after
50
+ case
51
+ when starting_after
43
52
  index = data.index { |datum| datum[:id] == starting_after }
44
53
  (index || raise("No such object id: #{starting_after}")) + 1
54
+ when ending_before
55
+ index = data.index { |datum| datum[:id] == ending_before }
56
+ (index || raise("No such object id: #{ending_before}")) - 1
45
57
  else
46
58
  0
47
59
  end