stripe 3.2.0 → 5.16.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (230) hide show
  1. checksums.yaml +5 -5
  2. data/.editorconfig +10 -0
  3. data/.gitignore +3 -0
  4. data/.rubocop.yml +80 -0
  5. data/.rubocop_todo.yml +33 -0
  6. data/.travis.yml +9 -7
  7. data/.vscode/extensions.json +7 -0
  8. data/.vscode/settings.json +8 -0
  9. data/CHANGELOG.md +876 -0
  10. data/CODE_OF_CONDUCT.md +77 -0
  11. data/Gemfile +21 -21
  12. data/History.txt +1 -678
  13. data/README.md +195 -53
  14. data/Rakefile +18 -12
  15. data/VERSION +1 -1
  16. data/bin/stripe-console +5 -3
  17. data/lib/stripe/api_operations/create.rb +3 -1
  18. data/lib/stripe/api_operations/delete.rb +26 -2
  19. data/lib/stripe/api_operations/list.rb +3 -12
  20. data/lib/stripe/api_operations/nested_resource.rb +72 -0
  21. data/lib/stripe/api_operations/request.rb +33 -15
  22. data/lib/stripe/api_operations/save.rb +18 -9
  23. data/lib/stripe/api_resource.rb +60 -10
  24. data/lib/stripe/connection_manager.rb +159 -0
  25. data/lib/stripe/error_object.rb +94 -0
  26. data/lib/stripe/errors.rb +39 -19
  27. data/lib/stripe/instrumentation.rb +82 -0
  28. data/lib/stripe/list_object.rb +54 -22
  29. data/lib/stripe/multipart_encoder.rb +131 -0
  30. data/lib/stripe/oauth.rb +22 -14
  31. data/lib/stripe/object_types.rb +96 -0
  32. data/lib/stripe/{account.rb → resources/account.rb} +72 -34
  33. data/lib/stripe/resources/account_link.rb +9 -0
  34. data/lib/stripe/resources/alipay_account.rb +34 -0
  35. data/lib/stripe/{apple_pay_domain.rb → resources/apple_pay_domain.rb} +4 -2
  36. data/lib/stripe/resources/application_fee.rb +13 -0
  37. data/lib/stripe/resources/application_fee_refund.rb +30 -0
  38. data/lib/stripe/{balance.rb → resources/balance.rb} +3 -1
  39. data/lib/stripe/{balance_transaction.rb → resources/balance_transaction.rb} +3 -5
  40. data/lib/stripe/resources/bank_account.rb +42 -0
  41. data/lib/stripe/{bitcoin_receiver.rb → resources/bitcoin_receiver.rb} +6 -5
  42. data/lib/stripe/resources/bitcoin_transaction.rb +15 -0
  43. data/lib/stripe/resources/capability.rb +33 -0
  44. data/lib/stripe/resources/card.rb +37 -0
  45. data/lib/stripe/resources/charge.rb +22 -0
  46. data/lib/stripe/resources/checkout/session.rb +12 -0
  47. data/lib/stripe/{country_spec.rb → resources/country_spec.rb} +3 -5
  48. data/lib/stripe/{coupon.rb → resources/coupon.rb} +4 -2
  49. data/lib/stripe/resources/credit_note.rb +32 -0
  50. data/lib/stripe/resources/credit_note_line_item.rb +7 -0
  51. data/lib/stripe/resources/customer.rb +35 -0
  52. data/lib/stripe/resources/customer_balance_transaction.rb +30 -0
  53. data/lib/stripe/resources/discount.rb +7 -0
  54. data/lib/stripe/resources/dispute.rb +21 -0
  55. data/lib/stripe/resources/ephemeral_key.rb +19 -0
  56. data/lib/stripe/{event.rb → resources/event.rb} +3 -1
  57. data/lib/stripe/resources/exchange_rate.rb +9 -0
  58. data/lib/stripe/resources/file.rb +34 -0
  59. data/lib/stripe/resources/file_link.rb +11 -0
  60. data/lib/stripe/resources/invoice.rb +73 -0
  61. data/lib/stripe/{invoice_item.rb → resources/invoice_item.rb} +4 -2
  62. data/lib/stripe/{invoice_line_item.rb → resources/invoice_line_item.rb} +3 -1
  63. data/lib/stripe/resources/issuing/authorization.rb +33 -0
  64. data/lib/stripe/resources/issuing/card.rb +24 -0
  65. data/lib/stripe/resources/issuing/card_details.rb +9 -0
  66. data/lib/stripe/resources/issuing/cardholder.rb +13 -0
  67. data/lib/stripe/resources/issuing/dispute.rb +13 -0
  68. data/lib/stripe/resources/issuing/transaction.rb +12 -0
  69. data/lib/stripe/resources/login_link.rb +14 -0
  70. data/lib/stripe/resources/mandate.rb +7 -0
  71. data/lib/stripe/resources/order.rb +32 -0
  72. data/lib/stripe/{order_return.rb → resources/order_return.rb} +3 -5
  73. data/lib/stripe/resources/payment_intent.rb +42 -0
  74. data/lib/stripe/resources/payment_method.rb +32 -0
  75. data/lib/stripe/resources/payout.rb +22 -0
  76. data/lib/stripe/resources/person.rb +31 -0
  77. data/lib/stripe/{plan.rb → resources/plan.rb} +3 -1
  78. data/lib/stripe/{product.rb → resources/product.rb} +5 -3
  79. data/lib/stripe/resources/radar/early_fraud_warning.rb +11 -0
  80. data/lib/stripe/resources/radar/value_list.rb +14 -0
  81. data/lib/stripe/resources/radar/value_list_item.rb +13 -0
  82. data/lib/stripe/{recipient.rb → resources/recipient.rb} +5 -6
  83. data/lib/stripe/resources/recipient_transfer.rb +7 -0
  84. data/lib/stripe/{refund.rb → resources/refund.rb} +3 -1
  85. data/lib/stripe/resources/reporting/report_run.rb +12 -0
  86. data/lib/stripe/resources/reporting/report_type.rb +12 -0
  87. data/lib/stripe/resources/reversal.rb +29 -0
  88. data/lib/stripe/resources/review.rb +20 -0
  89. data/lib/stripe/resources/setup_intent.rb +32 -0
  90. data/lib/stripe/resources/sigma/scheduled_query_run.rb +15 -0
  91. data/lib/stripe/{sku.rb → resources/sku.rb} +5 -3
  92. data/lib/stripe/resources/source.rb +46 -0
  93. data/lib/stripe/resources/source_transaction.rb +7 -0
  94. data/lib/stripe/resources/subscription.rb +25 -0
  95. data/lib/stripe/resources/subscription_item.rb +25 -0
  96. data/lib/stripe/resources/subscription_schedule.rb +32 -0
  97. data/lib/stripe/resources/tax_id.rb +26 -0
  98. data/lib/stripe/resources/tax_rate.rb +11 -0
  99. data/lib/stripe/resources/terminal/connection_token.rb +11 -0
  100. data/lib/stripe/resources/terminal/location.rb +14 -0
  101. data/lib/stripe/resources/terminal/reader.rb +14 -0
  102. data/lib/stripe/{three_d_secure.rb → resources/three_d_secure.rb} +3 -1
  103. data/lib/stripe/{token.rb → resources/token.rb} +3 -1
  104. data/lib/stripe/resources/topup.rb +22 -0
  105. data/lib/stripe/resources/transfer.rb +26 -0
  106. data/lib/stripe/resources/usage_record.rb +7 -0
  107. data/lib/stripe/resources/usage_record_summary.rb +7 -0
  108. data/lib/stripe/resources/webhook_endpoint.rb +12 -0
  109. data/lib/stripe/resources.rb +79 -0
  110. data/lib/stripe/singleton_api_resource.rb +10 -4
  111. data/lib/stripe/stripe_client.rb +658 -337
  112. data/lib/stripe/stripe_object.rb +248 -126
  113. data/lib/stripe/stripe_response.rb +55 -21
  114. data/lib/stripe/util.rb +145 -187
  115. data/lib/stripe/version.rb +3 -1
  116. data/lib/stripe/webhook.rb +27 -16
  117. data/lib/stripe.rb +139 -90
  118. data/stripe.gemspec +26 -14
  119. data/test/openapi/README.md +9 -0
  120. data/test/stripe/account_link_test.rb +18 -0
  121. data/test/stripe/account_test.rb +311 -101
  122. data/test/stripe/alipay_account_test.rb +21 -1
  123. data/test/stripe/api_operations_test.rb +57 -8
  124. data/test/stripe/api_resource_test.rb +359 -271
  125. data/test/stripe/apple_pay_domain_test.rb +26 -11
  126. data/test/stripe/application_fee_refund_test.rb +10 -8
  127. data/test/stripe/application_fee_test.rb +49 -3
  128. data/test/stripe/balance_test.rb +4 -2
  129. data/test/stripe/balance_transaction_test.rb +20 -0
  130. data/test/stripe/bank_account_test.rb +11 -11
  131. data/test/stripe/capability_test.rb +45 -0
  132. data/test/stripe/charge_test.rb +25 -18
  133. data/test/stripe/checkout/session_test.rb +41 -0
  134. data/test/stripe/connection_manager_test.rb +163 -0
  135. data/test/stripe/country_spec_test.rb +6 -4
  136. data/test/stripe/coupon_test.rb +29 -10
  137. data/test/stripe/credit_note_test.rb +90 -0
  138. data/test/stripe/customer_balance_transaction_test.rb +37 -0
  139. data/test/stripe/customer_card_test.rb +13 -17
  140. data/test/stripe/customer_test.rb +161 -49
  141. data/test/stripe/dispute_test.rb +19 -8
  142. data/test/stripe/ephemeral_key_test.rb +23 -14
  143. data/test/stripe/errors_test.rb +32 -9
  144. data/test/stripe/exchange_rate_test.rb +20 -0
  145. data/test/stripe/file_link_test.rb +41 -0
  146. data/test/stripe/file_test.rb +87 -0
  147. data/test/stripe/instrumentation_test.rb +74 -0
  148. data/test/stripe/invoice_item_test.rb +31 -18
  149. data/test/stripe/invoice_line_item_test.rb +3 -1
  150. data/test/stripe/invoice_test.rb +158 -39
  151. data/test/stripe/issuing/authorization_test.rb +72 -0
  152. data/test/stripe/issuing/card_test.rb +62 -0
  153. data/test/stripe/issuing/cardholder_test.rb +53 -0
  154. data/test/stripe/issuing/dispute_test.rb +45 -0
  155. data/test/stripe/issuing/transaction_test.rb +48 -0
  156. data/test/stripe/list_object_test.rb +120 -88
  157. data/test/stripe/login_link_test.rb +16 -14
  158. data/test/stripe/mandate_test.rb +14 -0
  159. data/test/stripe/multipart_encoder_test.rb +130 -0
  160. data/test/stripe/oauth_test.rb +69 -50
  161. data/test/stripe/order_return_test.rb +7 -5
  162. data/test/stripe/order_test.rb +39 -14
  163. data/test/stripe/payment_intent_test.rb +107 -0
  164. data/test/stripe/payment_method_test.rb +84 -0
  165. data/test/stripe/payout_test.rb +18 -9
  166. data/test/stripe/person_test.rb +46 -0
  167. data/test/stripe/plan_test.rb +67 -19
  168. data/test/stripe/product_test.rb +28 -14
  169. data/test/stripe/radar/early_fraud_warning_test.rb +22 -0
  170. data/test/stripe/radar/value_list_item_test.rb +48 -0
  171. data/test/stripe/radar/value_list_test.rb +61 -0
  172. data/test/stripe/recipient_test.rb +27 -13
  173. data/test/stripe/refund_test.rb +11 -9
  174. data/test/stripe/reporting/report_run_test.rb +33 -0
  175. data/test/stripe/reporting/report_type_test.rb +22 -0
  176. data/test/stripe/reversal_test.rb +12 -10
  177. data/test/stripe/review_test.rb +27 -0
  178. data/test/stripe/setup_intent_test.rb +84 -0
  179. data/test/stripe/sigma/scheduled_query_run_test.rb +22 -0
  180. data/test/stripe/sku_test.rb +24 -12
  181. data/test/stripe/source_test.rb +70 -19
  182. data/test/stripe/stripe_client_test.rb +867 -326
  183. data/test/stripe/stripe_object_test.rb +284 -182
  184. data/test/stripe/stripe_response_test.rb +73 -24
  185. data/test/stripe/subscription_item_test.rb +47 -15
  186. data/test/stripe/subscription_schedule_test.rb +82 -0
  187. data/test/stripe/subscription_test.rb +41 -19
  188. data/test/stripe/tax_id_test.rb +31 -0
  189. data/test/stripe/tax_rate_test.rb +43 -0
  190. data/test/stripe/terminal/connection_token_test.rb +16 -0
  191. data/test/stripe/terminal/location_test.rb +68 -0
  192. data/test/stripe/terminal/reader_test.rb +62 -0
  193. data/test/stripe/three_d_secure_test.rb +4 -2
  194. data/test/stripe/topup_test.rb +62 -0
  195. data/test/stripe/transfer_test.rb +55 -8
  196. data/test/stripe/usage_record_summary_test.rb +29 -0
  197. data/test/stripe/util_test.rb +173 -84
  198. data/test/stripe/webhook_endpoint_test.rb +59 -0
  199. data/test/stripe/webhook_test.rb +21 -17
  200. data/test/stripe_mock.rb +78 -0
  201. data/test/stripe_test.rb +6 -15
  202. data/test/test_data.rb +28 -26
  203. data/test/test_helper.rb +48 -29
  204. metadata +183 -70
  205. data/lib/stripe/alipay_account.rb +0 -22
  206. data/lib/stripe/application_fee.rb +0 -22
  207. data/lib/stripe/application_fee_refund.rb +0 -20
  208. data/lib/stripe/bank_account.rb +0 -30
  209. data/lib/stripe/bitcoin_transaction.rb +0 -11
  210. data/lib/stripe/card.rb +0 -27
  211. data/lib/stripe/charge.rb +0 -82
  212. data/lib/stripe/customer.rb +0 -79
  213. data/lib/stripe/dispute.rb +0 -17
  214. data/lib/stripe/ephemeral_key.rb +0 -18
  215. data/lib/stripe/file_upload.rb +0 -33
  216. data/lib/stripe/invoice.rb +0 -29
  217. data/lib/stripe/login_link.rb +0 -9
  218. data/lib/stripe/order.rb +0 -29
  219. data/lib/stripe/payout.rb +0 -18
  220. data/lib/stripe/recipient_transfer.rb +0 -6
  221. data/lib/stripe/reversal.rb +0 -20
  222. data/lib/stripe/source.rb +0 -23
  223. data/lib/stripe/subscription.rb +0 -33
  224. data/lib/stripe/subscription_item.rb +0 -14
  225. data/lib/stripe/transfer.rb +0 -18
  226. data/test/api_stub_helpers.rb +0 -0
  227. data/test/stripe/bitcoin_receiver_test.rb +0 -67
  228. data/test/stripe/bitcoin_transaction_test.rb +0 -19
  229. data/test/stripe/file_upload_test.rb +0 -66
  230. data/test/stripe/recipient_card_test.rb +0 -44
@@ -1,11 +1,13 @@
1
- require File.expand_path('../../test_helper', __FILE__)
1
+ # frozen_string_literal: true
2
+
3
+ require ::File.expand_path("../test_helper", __dir__)
2
4
 
3
5
  module Stripe
4
6
  class StripeObjectTest < Test::Unit::TestCase
5
7
  should "implement #==" do
6
- obj1 = Stripe::StripeObject.construct_from({ :id => 1, :foo => "bar" })
7
- obj2 = Stripe::StripeObject.construct_from({ :id => 1, :foo => "bar" })
8
- obj3 = Stripe::StripeObject.construct_from({ :id => 1, :foo => "rab" })
8
+ obj1 = Stripe::StripeObject.construct_from(id: 1, foo: "bar")
9
+ obj2 = Stripe::StripeObject.construct_from(id: 1, foo: "bar")
10
+ obj3 = Stripe::StripeObject.construct_from(id: 1, foo: "rab")
9
11
 
10
12
  assert obj1 == obj2
11
13
  refute obj1 == obj3
@@ -15,66 +17,187 @@ module Stripe
15
17
  obj = Stripe::StripeObject.construct_from({})
16
18
  refute obj.deleted?
17
19
 
18
- obj = Stripe::StripeObject.construct_from({ :deleted => false })
20
+ obj = Stripe::StripeObject.construct_from(deleted: false)
19
21
  refute obj.deleted?
20
22
 
21
- obj = Stripe::StripeObject.construct_from({ :deleted => true })
23
+ obj = Stripe::StripeObject.construct_from(deleted: true)
22
24
  assert obj.deleted?
23
25
  end
24
26
 
25
27
  should "implement #respond_to" do
26
- obj = Stripe::StripeObject.construct_from({ :id => 1, :foo => 'bar' })
28
+ obj = Stripe::StripeObject.construct_from(id: 1, foo: "bar")
27
29
  assert obj.respond_to?(:id)
28
30
  assert obj.respond_to?(:foo)
29
31
  assert !obj.respond_to?(:baz)
30
32
  end
31
33
 
32
34
  should "marshal be insensitive to strings vs. symbols when constructin" do
33
- obj = Stripe::StripeObject.construct_from({ :id => 1, 'name' => 'Stripe' })
35
+ obj = Stripe::StripeObject.construct_from(:id => 1, "name" => "Stripe")
34
36
  assert_equal 1, obj[:id]
35
- assert_equal 'Stripe', obj[:name]
37
+ assert_equal "Stripe", obj[:name]
36
38
  end
37
39
 
38
- should "marshal a stripe object correctly" do
39
- obj = Stripe::StripeObject.construct_from(
40
- { :id => 1, :name => 'Stripe' },
41
- {
42
- :api_key => 'apikey',
43
- # StripeClient is not serializable and is expected to be removed
44
- # when marshalling StripeObjects
45
- :client => StripeClient.active_client,
40
+ context "#deep_copy" do
41
+ should "produce a deep copy" do
42
+ opts = {
43
+ api_base: Stripe.api_base,
44
+ api_key: "apikey",
46
45
  }
47
- )
48
- m = Marshal.load(Marshal.dump(obj))
49
- assert_equal 1, m.id
50
- assert_equal 'Stripe', m.name
51
- expected_hash = {:api_key => 'apikey'}
52
- assert_equal expected_hash, m.instance_variable_get('@opts')
46
+ values = {
47
+ id: 1,
48
+ name: "Stripe",
49
+ arr: [
50
+ StripeObject.construct_from({ id: "index0" }, opts),
51
+ "index1",
52
+ 2,
53
+ ],
54
+ map: {
55
+ "0": StripeObject.construct_from({ id: "index0" }, opts),
56
+ "1": "index1",
57
+ "2": 2,
58
+ },
59
+ }
60
+
61
+ # it's not good to test methods with `#send` like this, but I've done
62
+ # it in the interest of trying to keep `.deep_copy` as internal as
63
+ # possible
64
+ copy_values = Stripe::StripeObject.send(:deep_copy, values)
65
+
66
+ # we can't compare the hashes directly because they have embedded
67
+ # objects which are different from each other
68
+ assert_equal values[:id], copy_values[:id]
69
+ assert_equal values[:name], copy_values[:name]
70
+
71
+ assert_equal values[:arr].length, copy_values[:arr].length
72
+
73
+ # internal values of the copied StripeObject should be the same
74
+ # (including opts), but the object itself should be new (hence the
75
+ # refutation of equality on #object_id)
76
+ assert_equal values[:arr][0][:id], copy_values[:arr][0][:id]
77
+ refute_equal values[:arr][0].object_id, copy_values[:arr][0].object_id
78
+ assert_equal values[:arr][0].instance_variable_get(:@opts),
79
+ copy_values[:arr][0].instance_variable_get(:@opts)
80
+
81
+ # scalars however, can be compared
82
+ assert_equal values[:arr][1], copy_values[:arr][1]
83
+ assert_equal values[:arr][2], copy_values[:arr][2]
84
+
85
+ # and a similar story with the hash
86
+ assert_equal values[:map].keys, copy_values[:map].keys
87
+ assert_equal values[:map][:"0"][:id], copy_values[:map][:"0"][:id]
88
+ refute_equal values[:map][:"0"].object_id, copy_values[:map][:"0"].object_id
89
+ assert_equal values[:map][:"0"].instance_variable_get(:@opts),
90
+ copy_values[:map][:"0"].instance_variable_get(:@opts)
91
+ assert_equal values[:map][:"1"], copy_values[:map][:"1"]
92
+ assert_equal values[:map][:"2"], copy_values[:map][:"2"]
93
+ end
94
+
95
+ should "not copy a client" do
96
+ opts = {
97
+ api_key: "apikey",
98
+ client: StripeClient.active_client,
99
+ }
100
+ values = { id: 1, name: "Stripe" }
101
+
102
+ obj = Stripe::StripeObject.construct_from(values, opts)
103
+ copy_obj = Stripe::StripeObject.send(:deep_copy, obj)
104
+
105
+ assert_equal values, copy_obj.instance_variable_get(:@values)
106
+ assert_equal opts.reject { |k, _v| k == :client },
107
+ copy_obj.instance_variable_get(:@opts)
108
+ end
109
+
110
+ should "return an instance of the same class" do
111
+ class TestObject < Stripe::StripeObject; end
112
+
113
+ obj = TestObject.construct_from(id: 1)
114
+ copy_obj = obj.class.send(:deep_copy, obj)
115
+
116
+ assert_equal obj.class, copy_obj.class
117
+ end
53
118
  end
54
119
 
55
- should "recursively call to_hash on its values" do
56
- # deep nested hash (when contained in an array) or StripeObject
57
- nested_hash = { :id => 7, :foo => 'bar' }
58
- nested = Stripe::StripeObject.construct_from(nested_hash)
120
+ context "#eql?" do
121
+ should "produce true for two equivalent Stripe objects" do
122
+ obj1 = Stripe::StripeObject.construct_from(id: 1, name: "Stripe")
123
+ obj2 = Stripe::StripeObject.construct_from(id: 1, name: "Stripe")
124
+ assert obj1.eql?(obj2)
125
+ end
59
126
 
60
- obj = Stripe::StripeObject.construct_from({
61
- :id => 1,
62
- # simple hash that contains a StripeObject to help us test deep
63
- # recursion
64
- :nested => { :object => 'list', :data => [nested] },
65
- :list => [nested]
66
- })
127
+ should "produce false for non-equivalent Stripe objects" do
128
+ obj1 = Stripe::StripeObject.construct_from(id: 1, name: "Stripe")
129
+ obj2 = Stripe::StripeObject.construct_from(id: 2, name: "Stripe")
130
+ refute obj1.eql?(obj2)
131
+ end
132
+
133
+ should "produce false for different types" do
134
+ obj1 = Stripe::StripeObject.construct_from(id: 1, name: "Stripe")
135
+ obj2 = 7
136
+ refute obj1.eql?(obj2)
137
+ end
138
+ end
139
+
140
+ context "#hash" do
141
+ should "produce the same hash for two equivalent Stripe objects" do
142
+ obj1 = Stripe::StripeObject.construct_from(id: 1, name: "Stripe")
143
+ obj2 = Stripe::StripeObject.construct_from(id: 1, name: "Stripe")
144
+ assert_equal obj1.hash, obj2.hash
145
+ end
146
+
147
+ should "produce different hashes for non-equivalent Stripe objects" do
148
+ obj1 = Stripe::StripeObject.construct_from(id: 1, name: "Stripe")
149
+ obj2 = Stripe::StripeObject.construct_from(id: 2, name: "Stripe")
150
+ refute_equal obj1.hash, obj2.hash
151
+ end
152
+
153
+ should "produce different hashes for different types" do
154
+ obj1 = Stripe::StripeObject.construct_from(id: 1, name: "Stripe")
155
+ obj2 = 7
156
+ refute_equal obj1.hash, obj2.hash
157
+ end
158
+ end
67
159
 
68
- expected_hash = {
69
- :id => 1,
70
- :nested => { :object => 'list', :data => [nested_hash] },
71
- :list => [nested_hash]
72
- }
73
- assert_equal expected_hash, obj.to_hash
160
+ context "#to_hash" do
161
+ should "skip calling to_hash on nil" do
162
+ begin
163
+ module NilWithToHash
164
+ def to_hash
165
+ raise "Can't call to_hash on nil"
166
+ end
167
+ end
168
+ ::NilClass.include NilWithToHash
169
+
170
+ hash_with_nil = { id: 3, foo: nil }
171
+ obj = StripeObject.construct_from(hash_with_nil)
172
+ expected_hash = { id: 3, foo: nil }
173
+ assert_equal expected_hash, obj.to_hash
174
+ ensure
175
+ ::NilClass.send(:undef_method, :to_hash)
176
+ end
177
+ end
178
+
179
+ should "recursively call to_hash on its values" do
180
+ # deep nested hash (when contained in an array) or StripeObject
181
+ nested_hash = { id: 7, foo: "bar" }
182
+ nested = Stripe::StripeObject.construct_from(nested_hash)
183
+
184
+ obj = Stripe::StripeObject.construct_from(id: 1,
185
+ # simple hash that contains a StripeObject to help us test deep
186
+ # recursion
187
+ nested: { object: "list", data: [nested] },
188
+ list: [nested])
189
+
190
+ expected_hash = {
191
+ id: 1,
192
+ nested: { object: "list", data: [nested_hash] },
193
+ list: [nested_hash],
194
+ }
195
+ assert_equal expected_hash, obj.to_hash
196
+ end
74
197
  end
75
198
 
76
199
  should "assign question mark accessors for booleans" do
77
- obj = Stripe::StripeObject.construct_from({ :id => 1, :bool => true, :not_bool => 'bar' })
200
+ obj = Stripe::StripeObject.construct_from(id: 1, bool: true, not_bool: "bar")
78
201
  assert obj.respond_to?(:bool?)
79
202
  assert obj.bool?
80
203
  refute obj.respond_to?(:not_bool?)
@@ -88,53 +211,42 @@ module Stripe
88
211
  end
89
212
 
90
213
  should "mass assign values with #update_attributes" do
91
- obj = Stripe::StripeObject.construct_from({ :id => 1, :name => 'Stripe' })
92
- obj.update_attributes(:name => 'STRIPE')
214
+ obj = Stripe::StripeObject.construct_from(id: 1, name: "Stripe")
215
+
216
+ obj.update_attributes({ name: "STRIPE" })
217
+
93
218
  assert_equal "STRIPE", obj.name
94
219
 
95
220
  # unfortunately, we even assign unknown properties to duplicate the
96
221
  # behavior that we currently have via magic accessors with
97
222
  # method_missing
98
- obj.update_attributes(:unknown => 'foo')
223
+ obj.update_attributes({ unknown: "foo" })
224
+
99
225
  assert_equal "foo", obj.unknown
100
226
  end
101
227
 
102
228
  should "#update_attributes with a hash" do
103
229
  obj = Stripe::StripeObject.construct_from({})
104
- obj.update_attributes(:metadata => { :foo => 'bar' })
230
+ obj.update_attributes({ metadata: { foo: "bar" } })
105
231
  assert_equal Stripe::StripeObject, obj.metadata.class
106
232
  end
107
233
 
108
234
  should "create accessors when #update_attributes is called" do
109
235
  obj = Stripe::StripeObject.construct_from({})
110
236
  assert_equal false, obj.send(:metaclass).method_defined?(:foo)
111
- obj.update_attributes(:foo => 'bar')
237
+ obj.update_attributes({ foo: "bar" })
112
238
  assert_equal true, obj.send(:metaclass).method_defined?(:foo)
113
239
  end
114
240
 
115
- should "warn that #refresh_from is deprecated" do
116
- old_stderr = $stderr
117
- $stderr = StringIO.new
118
- begin
119
- obj = Stripe::StripeObject.construct_from({})
120
- obj.refresh_from({}, {})
121
- message = "NOTE: Stripe::StripeObject#refresh_from is " +
122
- "deprecated; use #update_attributes instead"
123
- assert_match Regexp.new(message), $stderr.string
124
- ensure
125
- $stderr = old_stderr
126
- end
127
- end
128
-
129
241
  should "pass opts down to children when initializing" do
130
- opts = { :custom => "opts" }
242
+ opts = { custom: "opts" }
131
243
 
132
244
  # customer comes with a `sources` list that makes a convenient object to
133
245
  # perform tests on
134
246
  obj = Stripe::StripeObject.construct_from({
135
247
  sources: [
136
- {}
137
- ]
248
+ {},
249
+ ],
138
250
  }, opts)
139
251
 
140
252
  source = obj.sources.first
@@ -152,80 +264,64 @@ module Stripe
152
264
 
153
265
  should "#serialize_params on a new object with a subobject" do
154
266
  obj = Stripe::StripeObject.new
155
- obj.metadata = { :foo => "bar" }
156
- assert_equal({ :metadata => { :foo => "bar" } },
157
- obj.serialize_params)
267
+ obj.metadata = { foo: "bar" }
268
+ assert_equal({ metadata: { foo: "bar" } },
269
+ obj.serialize_params)
158
270
  end
159
271
 
160
272
  should "#serialize_params on a basic object" do
161
- obj = Stripe::StripeObject.construct_from({ :foo => nil })
162
- obj.update_attributes(:foo => "bar")
163
- assert_equal({ :foo => "bar" }, obj.serialize_params)
273
+ obj = Stripe::StripeObject.construct_from(foo: nil)
274
+ obj.update_attributes({ foo: "bar" })
275
+ assert_equal({ foo: "bar" }, obj.serialize_params)
164
276
  end
165
277
 
166
278
  should "#serialize_params on a more complex object" do
167
- obj = Stripe::StripeObject.construct_from({
168
- :foo => Stripe::StripeObject.construct_from({
169
- :bar => nil,
170
- :baz => nil,
171
- }),
172
- })
279
+ obj = Stripe::StripeObject.construct_from(foo: Stripe::StripeObject.construct_from(bar: nil,
280
+ baz: nil))
173
281
  obj.foo.bar = "newbar"
174
- assert_equal({ :foo => { :bar => "newbar" } },
175
- obj.serialize_params)
282
+ assert_equal({ foo: { bar: "newbar" } },
283
+ obj.serialize_params)
176
284
  end
177
285
 
178
286
  should "#serialize_params on an array" do
179
- obj = Stripe::StripeObject.construct_from({
180
- :foo => nil,
181
- })
287
+ obj = Stripe::StripeObject.construct_from(foo: nil)
182
288
  obj.foo = ["new-value"]
183
- assert_equal({ :foo => ["new-value"] },
184
- obj.serialize_params)
289
+ assert_equal({ foo: ["new-value"] },
290
+ obj.serialize_params)
185
291
  end
186
292
 
187
293
  should "#serialize_params on an array that shortens" do
188
- obj = Stripe::StripeObject.construct_from({
189
- :foo => ["0-index", "1-index", "2-index"],
190
- })
294
+ obj = Stripe::StripeObject.construct_from(foo: %w[0-index 1-index 2-index])
191
295
  obj.foo = ["new-value"]
192
- assert_equal({ :foo => ["new-value"] },
193
- obj.serialize_params)
296
+ assert_equal({ foo: ["new-value"] },
297
+ obj.serialize_params)
194
298
  end
195
299
 
196
300
  should "#serialize_params on an array that lengthens" do
197
- obj = Stripe::StripeObject.construct_from({
198
- :foo => ["0-index", "1-index", "2-index"],
199
- })
301
+ obj = Stripe::StripeObject.construct_from(foo: %w[0-index 1-index 2-index])
200
302
  obj.foo = ["new-value"] * 4
201
- assert_equal({ :foo => ["new-value"] * 4 },
202
- obj.serialize_params)
303
+ assert_equal({ foo: ["new-value"] * 4 },
304
+ obj.serialize_params)
203
305
  end
204
306
 
205
307
  should "#serialize_params on an array of hashes" do
206
- obj = Stripe::StripeObject.construct_from({
207
- :foo => nil,
208
- })
308
+ obj = Stripe::StripeObject.construct_from(foo: nil)
209
309
  obj.foo = [
210
- Stripe::StripeObject.construct_from({
211
- :bar => nil
212
- })
310
+ Stripe::StripeObject.construct_from(bar: nil),
213
311
  ]
214
312
  obj.foo[0].bar = "baz"
215
- assert_equal({ :foo => [{ :bar => "baz" }] },
216
- obj.serialize_params)
313
+ assert_equal({ foo: [{ bar: "baz" }] },
314
+ obj.serialize_params)
217
315
  end
218
316
 
219
317
  should "#serialize_params doesn't include unchanged values" do
220
- obj = Stripe::StripeObject.construct_from({ :foo => nil })
318
+ obj = Stripe::StripeObject.construct_from(foo: nil)
221
319
  assert_equal({}, obj.serialize_params)
222
320
  end
223
321
 
224
322
  should "#serialize_params on an array that is unchanged" do
225
- obj = Stripe::StripeObject.construct_from({
226
- :foo => ["0-index", "1-index", "2-index"],
227
- })
228
- obj.foo = ["0-index", "1-index", "2-index"]
323
+ obj = Stripe::StripeObject.construct_from(foo: %w[0-index 1-index 2-index])
324
+ obj.foo = %w[0-index 1-index 2-index]
229
325
  assert_equal({}, obj.serialize_params)
230
326
  end
231
327
 
@@ -235,39 +331,52 @@ module Stripe
235
331
  # using an #update_attributes will end up converting a Hash into a
236
332
  # StripeObject
237
333
  obj.metadata =
238
- Stripe::StripeObject.construct_from({ :foo => 'bar' })
334
+ Stripe::StripeObject.construct_from(foo: "bar")
239
335
 
240
336
  serialized = obj.serialize_params
241
- assert_equal({ :foo => "bar" }, serialized[:metadata])
337
+ assert_equal({ foo: "bar" }, serialized[:metadata])
242
338
  end
243
339
 
244
- should "#serialize_params with a StripeObject that's been replaced" do
245
- obj = Stripe::StripeObject.construct_from({
246
- :metadata => Stripe::StripeObject.construct_from({ :bar => 'foo' })
247
- })
340
+ should "#serialize_params with StripeObject that's been replaced" do
341
+ obj = Stripe::StripeObject.construct_from(source: Stripe::StripeObject.construct_from(bar: "foo"))
342
+
343
+ # Here we replace the object wholesale.
344
+ obj.source =
345
+ Stripe::StripeObject.construct_from(baz: "foo")
346
+
347
+ serialized = obj.serialize_params
348
+ assert_equal({ baz: "foo" }, serialized[:source])
349
+ end
248
350
 
249
- # Here we replace the object wholesale which means that the client must
250
- # be able to blank out the values that were in the old object, but which
251
- # are no longer present in the new one.
351
+ should "#serialize_params with StripeObject that's been replaced which is `metadata`" do
352
+ class WithAdditiveObjectParam < Stripe::StripeObject
353
+ additive_object_param :metadata
354
+ end
355
+
356
+ obj = WithAdditiveObjectParam.construct_from(metadata: Stripe::StripeObject.construct_from(bar: "foo"))
357
+
358
+ # Here we replace the object wholesale. Because it's `metadata`, the
359
+ # client must be able to blank out the values that were in the old
360
+ # object, but which are no longer present in the new one.
252
361
  obj.metadata =
253
- Stripe::StripeObject.construct_from({ :baz => 'foo' })
362
+ Stripe::StripeObject.construct_from(baz: "foo")
254
363
 
255
364
  serialized = obj.serialize_params
256
- assert_equal({ :bar => "", :baz => 'foo' }, serialized[:metadata])
365
+ assert_equal({ bar: "", baz: "foo" }, serialized[:metadata])
257
366
  end
258
367
 
259
368
  should "#serialize_params with an array of StripeObjects" do
260
369
  obj = Stripe::StripeObject.construct_from({})
261
370
  obj.metadata = [
262
- Stripe::StripeObject.construct_from({ :foo => 'bar' })
371
+ Stripe::StripeObject.construct_from(foo: "bar"),
263
372
  ]
264
373
 
265
374
  serialized = obj.serialize_params
266
- assert_equal([{ :foo => "bar" }], serialized[:metadata])
375
+ assert_equal([{ foo: "bar" }], serialized[:metadata])
267
376
  end
268
377
 
269
378
  should "#serialize_params and embed an API resource that's been set and has an ID" do
270
- customer = Customer.construct_from({ :id => "cus_123" })
379
+ customer = Customer.construct_from(id: "cus_123")
271
380
  obj = Stripe::StripeObject.construct_from({})
272
381
 
273
382
  # the key here is that the property is set explicitly (and therefore
@@ -275,14 +384,12 @@ module Stripe
275
384
  obj.customer = customer
276
385
 
277
386
  serialized = obj.serialize_params
278
- assert_equal({ :customer => customer }, serialized)
387
+ assert_equal({ customer: customer }, serialized)
279
388
  end
280
389
 
281
390
  should "#serialize_params and not include API resources that have not been set" do
282
- customer = Customer.construct_from({ :id => "cus_123" })
283
- obj = Stripe::StripeObject.construct_from({
284
- :customer => customer
285
- })
391
+ customer = Customer.construct_from(id: "cus_123")
392
+ obj = Stripe::StripeObject.construct_from(customer: customer)
286
393
 
287
394
  serialized = obj.serialize_params
288
395
  assert_equal({}, serialized)
@@ -292,12 +399,10 @@ module Stripe
292
399
  c = Customer.construct_from({})
293
400
  c.save_with_parent = true
294
401
 
295
- obj = Stripe::StripeObject.construct_from({
296
- :customer => c,
297
- })
402
+ obj = Stripe::StripeObject.construct_from(customer: c)
298
403
 
299
404
  serialized = obj.serialize_params
300
- assert_equal({ :customer => {} }, serialized)
405
+ assert_equal({ customer: {} }, serialized)
301
406
  end
302
407
 
303
408
  should "#serialize_params should raise an error on other embedded API resources" do
@@ -318,81 +423,78 @@ module Stripe
318
423
  end
319
424
 
320
425
  should "#serialize_params takes a force option" do
321
- obj = Stripe::StripeObject.construct_from({
322
- :id => 'id',
323
- :metadata => Stripe::StripeObject.construct_from({ :foo => 'bar' })
324
- })
426
+ obj = Stripe::StripeObject.construct_from(id: "id",
427
+ metadata: Stripe::StripeObject.construct_from(foo: "bar"))
325
428
 
326
- serialized = obj.serialize_params(:force => true)
327
- assert_equal({ :id => 'id', :metadata => { :foo => 'bar' } }, serialized)
429
+ serialized = obj.serialize_params(force: true)
430
+ assert_equal({ id: "id", metadata: { foo: "bar" } }, serialized)
328
431
  end
329
432
 
330
433
  should "#dirty! forces an object and its subobjects to be saved" do
331
- obj = Stripe::StripeObject.construct_from({
332
- :id => 'id',
333
- :metadata => Stripe::StripeObject.construct_from({ :foo => 'bar' })
334
- })
434
+ obj = Stripe::StripeObject.construct_from(id: "id",
435
+ metadata: Stripe::StripeObject.construct_from(foo: "bar"))
335
436
 
336
437
  # note that `force` and `dirty!` are for different things, but are
337
438
  # functionally equivalent
338
439
  obj.dirty!
339
440
 
340
441
  serialized = obj.serialize_params
341
- assert_equal({ :id => 'id', :metadata => { :foo => 'bar' } }, serialized)
442
+ assert_equal({ id: "id", metadata: { foo: "bar" } }, serialized)
342
443
  end
343
444
 
344
445
  should "#to_s will call to_s for all embedded stripe objects" do
345
- obj = Stripe::StripeObject.construct_from({
346
- id: 'id',
347
- #embeded list object
348
- refunds: Stripe::ListObject.construct_from({ data: [
349
- #embedded object in list
350
- Stripe::StripeObject.construct_from({
351
- id: 'id',
352
- #embedded object in an object in a list object
353
- metadata: Stripe::StripeObject.construct_from({
354
- foo: 'bar',
355
- })
356
- })
357
- ]}),
358
- # embeded stripe object
359
- metadata: Stripe::StripeObject.construct_from({
360
- foo: 'bar',
361
- })
362
- })
363
- expected = JSON.pretty_generate({
364
- id: 'id',
365
- refunds: {
366
- data: [
367
- {id: 'id', metadata: {foo: 'bar'}}
368
- ]
369
- },
370
- metadata: { foo: 'bar' }
371
- })
446
+ obj = Stripe::StripeObject.construct_from(id: "id",
447
+ # embedded list object
448
+ refunds: Stripe::ListObject.construct_from(data: [
449
+ # embedded object in list
450
+ Stripe::StripeObject.construct_from(id: "id",
451
+ # embedded object in an object in a list object
452
+ metadata: Stripe::StripeObject.construct_from(foo: "bar")),
453
+ ]),
454
+ # embedded stripe object
455
+ metadata: Stripe::StripeObject.construct_from(foo: "bar"))
456
+ expected = JSON.pretty_generate(id: "id",
457
+ refunds: {
458
+ data: [
459
+ { id: "id", metadata: { foo: "bar" } },
460
+ ],
461
+ },
462
+ metadata: { foo: "bar" })
372
463
 
373
464
  assert_equal(expected, obj.to_s)
374
465
  end
375
466
 
376
- should "warn that .serialize_params is deprecated" do
377
- old_stderr = $stderr
378
- $stderr = StringIO.new
379
- begin
380
- obj = Stripe::StripeObject.construct_from({})
381
- Stripe::StripeObject.serialize_params(obj)
382
- message = "NOTE: Stripe::StripeObject.serialize_params is " +
383
- "deprecated; use #serialize_params instead"
384
- assert_match Regexp.new(message), $stderr.string
385
- ensure
386
- $stderr = old_stderr
387
- end
388
- end
389
-
390
467
  should "error on setting a property to an empty string" do
391
- obj = Stripe::StripeObject.construct_from({ :foo => 'bar' })
468
+ obj = Stripe::StripeObject.construct_from(foo: "bar")
392
469
  e = assert_raises ArgumentError do
393
470
  obj.foo = ""
394
471
  end
395
- assert_match %r{\(object\).foo = nil}, e.message
472
+ assert_match(/\(object\).foo = nil/, e.message)
473
+ end
474
+
475
+ should "marshal and unmarshal using custom encoder and decoder" do
476
+ obj = Stripe::StripeObject.construct_from(
477
+ { id: 1, name: "Stripe" },
478
+ api_key: "apikey",
479
+ client: StripeClient.active_client
480
+ )
481
+ m = Marshal.load(Marshal.dump(obj))
482
+ assert_equal 1, m.id
483
+ assert_equal "Stripe", m.name
484
+ expected_hash = { api_key: "apikey" }
485
+ assert_equal expected_hash, m.instance_variable_get("@opts")
486
+ end
487
+
488
+ context "#method" do
489
+ should "act as a getter if no arguments are provided" do
490
+ obj = Stripe::StripeObject.construct_from(id: 1, method: "foo")
491
+ assert_equal "foo", obj.method
492
+ end
493
+
494
+ should "call Object#method if an argument is provided" do
495
+ obj = Stripe::StripeObject.construct_from(id: 1, method: "foo")
496
+ assert obj.method(:id).is_a?(Method)
497
+ end
396
498
  end
397
499
  end
398
500
  end