stripe-ruby-mock 2.5.8 → 4.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 (159) hide show
  1. checksums.yaml +5 -5
  2. data/.github/workflows/rspec_tests.yml +38 -0
  3. data/.gitignore +1 -1
  4. data/.rspec +2 -1
  5. data/CHANGELOG.md +77 -0
  6. data/Gemfile +1 -5
  7. data/README.md +19 -11
  8. data/lib/stripe_mock/api/client.rb +2 -2
  9. data/lib/stripe_mock/api/errors.rb +34 -28
  10. data/lib/stripe_mock/api/instance.rb +1 -1
  11. data/lib/stripe_mock/api/webhooks.rb +68 -24
  12. data/lib/stripe_mock/client.rb +2 -1
  13. data/lib/stripe_mock/data/list.rb +42 -9
  14. data/lib/stripe_mock/data.rb +359 -21
  15. data/lib/stripe_mock/instance.rb +23 -5
  16. data/lib/stripe_mock/request_handlers/account_links.rb +15 -0
  17. data/lib/stripe_mock/request_handlers/accounts.rb +17 -6
  18. data/lib/stripe_mock/request_handlers/balance_transactions.rb +2 -2
  19. data/lib/stripe_mock/request_handlers/charges.rb +31 -5
  20. data/lib/stripe_mock/request_handlers/checkout_session.rb +179 -0
  21. data/lib/stripe_mock/request_handlers/customers.rb +47 -19
  22. data/lib/stripe_mock/request_handlers/ephemeral_key.rb +1 -1
  23. data/lib/stripe_mock/request_handlers/events.rb +30 -3
  24. data/lib/stripe_mock/request_handlers/express_login_links.rb +15 -0
  25. data/lib/stripe_mock/request_handlers/helpers/coupon_helpers.rb +6 -0
  26. data/lib/stripe_mock/request_handlers/helpers/search_helpers.rb +67 -0
  27. data/lib/stripe_mock/request_handlers/helpers/subscription_helpers.rb +36 -12
  28. data/lib/stripe_mock/request_handlers/helpers/token_helpers.rb +1 -1
  29. data/lib/stripe_mock/request_handlers/invoices.rb +26 -6
  30. data/lib/stripe_mock/request_handlers/payment_intents.rb +202 -0
  31. data/lib/stripe_mock/request_handlers/payment_methods.rb +124 -0
  32. data/lib/stripe_mock/request_handlers/plans.rb +1 -1
  33. data/lib/stripe_mock/request_handlers/prices.rb +71 -0
  34. data/lib/stripe_mock/request_handlers/products.rb +15 -5
  35. data/lib/stripe_mock/request_handlers/promotion_codes.rb +43 -0
  36. data/lib/stripe_mock/request_handlers/refunds.rb +13 -2
  37. data/lib/stripe_mock/request_handlers/setup_intents.rb +100 -0
  38. data/lib/stripe_mock/request_handlers/sources.rb +12 -6
  39. data/lib/stripe_mock/request_handlers/subscriptions.rb +146 -25
  40. data/lib/stripe_mock/request_handlers/tokens.rb +6 -4
  41. data/lib/stripe_mock/request_handlers/transfers.rb +12 -1
  42. data/lib/stripe_mock/request_handlers/validators/param_validators.rb +124 -9
  43. data/lib/stripe_mock/server.rb +2 -2
  44. data/lib/stripe_mock/test_strategies/base.rb +98 -12
  45. data/lib/stripe_mock/test_strategies/live.rb +23 -12
  46. data/lib/stripe_mock/test_strategies/mock.rb +6 -2
  47. data/lib/stripe_mock/version.rb +1 -1
  48. data/lib/stripe_mock/webhook_fixtures/account.updated.json +1 -1
  49. data/lib/stripe_mock/webhook_fixtures/balance.available.json +27 -15
  50. data/lib/stripe_mock/webhook_fixtures/charge.captured.json +143 -0
  51. data/lib/stripe_mock/webhook_fixtures/charge.dispute.created.json +63 -16
  52. data/lib/stripe_mock/webhook_fixtures/charge.failed.json +101 -44
  53. data/lib/stripe_mock/webhook_fixtures/charge.refund.updated.json +35 -0
  54. data/lib/stripe_mock/webhook_fixtures/charge.refunded.json +145 -50
  55. data/lib/stripe_mock/webhook_fixtures/charge.succeeded.json +114 -43
  56. data/lib/stripe_mock/webhook_fixtures/checkout.session.completed.json +79 -0
  57. data/lib/stripe_mock/webhook_fixtures/checkout.session.completed.payment_mode.json +53 -0
  58. data/lib/stripe_mock/webhook_fixtures/checkout.session.completed.setup_mode.json +45 -0
  59. data/lib/stripe_mock/webhook_fixtures/customer.created.json +37 -45
  60. data/lib/stripe_mock/webhook_fixtures/customer.deleted.json +36 -32
  61. data/lib/stripe_mock/webhook_fixtures/customer.source.created.json +31 -22
  62. data/lib/stripe_mock/webhook_fixtures/customer.source.updated.json +36 -25
  63. data/lib/stripe_mock/webhook_fixtures/customer.subscription.created.json +135 -47
  64. data/lib/stripe_mock/webhook_fixtures/customer.subscription.deleted.json +134 -45
  65. data/lib/stripe_mock/webhook_fixtures/customer.subscription.updated.json +135 -56
  66. data/lib/stripe_mock/webhook_fixtures/customer.updated.json +38 -46
  67. data/lib/stripe_mock/webhook_fixtures/invoice.created.json +176 -49
  68. data/lib/stripe_mock/webhook_fixtures/invoice.finalized.json +171 -0
  69. data/lib/stripe_mock/webhook_fixtures/invoice.paid.json +171 -0
  70. data/lib/stripe_mock/webhook_fixtures/invoice.payment_action_required.json +171 -0
  71. data/lib/stripe_mock/webhook_fixtures/invoice.payment_failed.json +149 -83
  72. data/lib/stripe_mock/webhook_fixtures/invoice.payment_succeeded.json +149 -90
  73. data/lib/stripe_mock/webhook_fixtures/invoice.upcoming.json +70 -0
  74. data/lib/stripe_mock/webhook_fixtures/invoice.updated.json +178 -50
  75. data/lib/stripe_mock/webhook_fixtures/invoiceitem.created.json +87 -13
  76. data/lib/stripe_mock/webhook_fixtures/invoiceitem.updated.json +88 -14
  77. data/lib/stripe_mock/webhook_fixtures/mandate.updated.json +34 -0
  78. data/lib/stripe_mock/webhook_fixtures/payment_intent.amount_capturable_updated.json +170 -0
  79. data/lib/stripe_mock/webhook_fixtures/payment_intent.canceled.json +73 -0
  80. data/lib/stripe_mock/webhook_fixtures/payment_intent.created.json +86 -0
  81. data/lib/stripe_mock/webhook_fixtures/payment_intent.payment_failed.json +225 -0
  82. data/lib/stripe_mock/webhook_fixtures/payment_intent.processing.json +162 -0
  83. data/lib/stripe_mock/webhook_fixtures/payment_intent.requires_action.json +191 -0
  84. data/lib/stripe_mock/webhook_fixtures/payment_intent.succeeded.json +196 -0
  85. data/lib/stripe_mock/webhook_fixtures/payment_link.created.json +47 -0
  86. data/lib/stripe_mock/webhook_fixtures/payment_link.updated.json +50 -0
  87. data/lib/stripe_mock/webhook_fixtures/payment_method.attached.json +63 -0
  88. data/lib/stripe_mock/webhook_fixtures/payment_method.detached.json +62 -0
  89. data/lib/stripe_mock/webhook_fixtures/payout.created.json +40 -0
  90. data/lib/stripe_mock/webhook_fixtures/payout.paid.json +40 -0
  91. data/lib/stripe_mock/webhook_fixtures/payout.updated.json +46 -0
  92. data/lib/stripe_mock/webhook_fixtures/plan.created.json +30 -13
  93. data/lib/stripe_mock/webhook_fixtures/plan.deleted.json +30 -13
  94. data/lib/stripe_mock/webhook_fixtures/plan.updated.json +34 -14
  95. data/lib/stripe_mock/webhook_fixtures/price.created.json +42 -0
  96. data/lib/stripe_mock/webhook_fixtures/price.deleted.json +42 -0
  97. data/lib/stripe_mock/webhook_fixtures/price.updated.json +48 -0
  98. data/lib/stripe_mock/webhook_fixtures/product.created.json +40 -0
  99. data/lib/stripe_mock/webhook_fixtures/product.deleted.json +40 -0
  100. data/lib/stripe_mock/webhook_fixtures/product.updated.json +47 -0
  101. data/lib/stripe_mock/webhook_fixtures/quote.accepted.json +92 -0
  102. data/lib/stripe_mock/webhook_fixtures/quote.canceled.json +92 -0
  103. data/lib/stripe_mock/webhook_fixtures/quote.created.json +92 -0
  104. data/lib/stripe_mock/webhook_fixtures/quote.finalized.json +92 -0
  105. data/lib/stripe_mock/webhook_fixtures/setup_intent.canceled.json +46 -0
  106. data/lib/stripe_mock/webhook_fixtures/setup_intent.created.json +51 -0
  107. data/lib/stripe_mock/webhook_fixtures/setup_intent.setup_failed.json +100 -0
  108. data/lib/stripe_mock/webhook_fixtures/setup_intent.succeeded.json +46 -0
  109. data/lib/stripe_mock/webhook_fixtures/subscription_schedule.canceled.json +119 -0
  110. data/lib/stripe_mock/webhook_fixtures/subscription_schedule.created.json +114 -0
  111. data/lib/stripe_mock/webhook_fixtures/subscription_schedule.released.json +111 -0
  112. data/lib/stripe_mock/webhook_fixtures/subscription_schedule.updated.json +125 -0
  113. data/lib/stripe_mock/webhook_fixtures/tax_rate.created.json +32 -0
  114. data/lib/stripe_mock/webhook_fixtures/tax_rate.updated.json +37 -0
  115. data/lib/stripe_mock.rb +11 -0
  116. data/spec/instance_spec.rb +13 -13
  117. data/spec/integration_examples/completing_checkout_sessions_example.rb +37 -0
  118. data/spec/list_spec.rb +38 -0
  119. data/spec/readme_spec.rb +1 -1
  120. data/spec/server_spec.rb +6 -3
  121. data/spec/shared_stripe_examples/account_examples.rb +10 -2
  122. data/spec/shared_stripe_examples/account_link_examples.rb +16 -0
  123. data/spec/shared_stripe_examples/balance_examples.rb +6 -0
  124. data/spec/shared_stripe_examples/balance_transaction_examples.rb +3 -3
  125. data/spec/shared_stripe_examples/bank_examples.rb +3 -3
  126. data/spec/shared_stripe_examples/bank_token_examples.rb +5 -7
  127. data/spec/shared_stripe_examples/card_examples.rb +4 -4
  128. data/spec/shared_stripe_examples/card_token_examples.rb +17 -21
  129. data/spec/shared_stripe_examples/charge_examples.rb +106 -22
  130. data/spec/shared_stripe_examples/checkout_session_examples.rb +99 -0
  131. data/spec/shared_stripe_examples/coupon_examples.rb +1 -1
  132. data/spec/shared_stripe_examples/customer_examples.rb +149 -53
  133. data/spec/shared_stripe_examples/dispute_examples.rb +2 -2
  134. data/spec/shared_stripe_examples/error_mock_examples.rb +8 -7
  135. data/spec/shared_stripe_examples/express_login_link_examples.rb +12 -0
  136. data/spec/shared_stripe_examples/external_account_examples.rb +3 -3
  137. data/spec/shared_stripe_examples/invoice_examples.rb +148 -40
  138. data/spec/shared_stripe_examples/invoice_item_examples.rb +1 -1
  139. data/spec/shared_stripe_examples/payment_intent_examples.rb +283 -0
  140. data/spec/shared_stripe_examples/payment_method_examples.rb +454 -0
  141. data/spec/shared_stripe_examples/payout_examples.rb +2 -2
  142. data/spec/shared_stripe_examples/plan_examples.rb +135 -92
  143. data/spec/shared_stripe_examples/price_examples.rb +292 -0
  144. data/spec/shared_stripe_examples/product_examples.rb +215 -0
  145. data/spec/shared_stripe_examples/promotion_code_examples.rb +68 -0
  146. data/spec/shared_stripe_examples/refund_examples.rb +38 -21
  147. data/spec/shared_stripe_examples/setup_intent_examples.rb +85 -0
  148. data/spec/shared_stripe_examples/subscription_examples.rb +706 -324
  149. data/spec/shared_stripe_examples/subscription_items_examples.rb +3 -2
  150. data/spec/shared_stripe_examples/transfer_examples.rb +16 -7
  151. data/spec/shared_stripe_examples/webhook_event_examples.rb +62 -16
  152. data/spec/spec_helper.rb +8 -5
  153. data/spec/stripe_mock_spec.rb +4 -4
  154. data/spec/support/shared_contexts/stripe_validator_spec.rb +8 -0
  155. data/spec/support/stripe_examples.rb +11 -1
  156. data/stripe-ruby-mock.gemspec +9 -5
  157. metadata +115 -47
  158. data/.travis.yml +0 -28
  159. data/spec/shared_stripe_examples/product_example.rb +0 -65
@@ -1,93 +1,73 @@
1
1
  require 'spec_helper'
2
2
 
3
3
  shared_examples 'Plan API' do
4
+ let(:product) { stripe_helper.create_product }
5
+ let(:product_id) { product.id }
6
+
7
+ let(:plan_attributes) { {
8
+ :id => "plan_abc123",
9
+ :product => product_id,
10
+ :nickname => "My Mock Plan",
11
+ :amount => 9900,
12
+ :currency => "usd",
13
+ :interval => "month"
14
+ } }
15
+ let(:plan) { Stripe::Plan.create(plan_attributes) }
16
+
17
+ let(:plan_attributes_without_id){ plan_attributes.merge(id: nil) }
18
+ let(:plan_without_id){ Stripe::Plan.create(plan_attributes_without_id) }
19
+
20
+ let(:plan_attributes_with_trial) { plan_attributes.merge(id: "prod_TRIAL", :trial_period_days => 30) }
21
+ let(:plan_with_trial) { Stripe::Plan.create(plan_attributes_with_trial) }
22
+
23
+ let(:metadata) { {:description => "desc text", :info => "info text"} }
24
+ let(:plan_attributes_with_metadata) { plan_attributes.merge(id: "prod_META", metadata: metadata) }
25
+ let(:plan_with_metadata) { Stripe::Plan.create(plan_attributes_with_metadata) }
26
+
27
+ before(:each) do
28
+ product
29
+ end
4
30
 
5
31
  it "creates a stripe plan" do
6
- plan = Stripe::Plan.create(
7
- :id => 'pid_1',
8
- :name => 'The Mock Plan',
9
- :amount => 9900,
10
- :currency => 'USD',
11
- :interval => 1,
12
- :product => {
13
- :name => 'A product'
14
- },
15
- :metadata => {
16
- :description => "desc text",
17
- :info => "info text"
18
- },
19
- :trial_period_days => 30
20
- )
21
-
22
- expect(plan.id).to eq('pid_1')
23
- expect(plan.name).to eq('The Mock Plan')
32
+ expect(plan.id).to eq('plan_abc123')
33
+ expect(plan.nickname).to eq('My Mock Plan')
24
34
  expect(plan.amount).to eq(9900)
25
35
 
26
- expect(plan.currency).to eq('USD')
27
- expect(plan.interval).to eq(1)
36
+ expect(plan.currency).to eq('usd')
37
+ expect(plan.interval).to eq("month")
28
38
 
29
- expect(plan.metadata.description).to eq('desc text')
30
- expect(plan.metadata.info).to eq('info text')
39
+ expect(plan_with_metadata.metadata.description).to eq('desc text')
40
+ expect(plan_with_metadata.metadata.info).to eq('info text')
31
41
 
32
- expect(plan.trial_period_days).to eq(30)
42
+ expect(plan_with_trial.trial_period_days).to eq(30)
33
43
  end
34
44
 
35
-
36
45
  it "creates a stripe plan without specifying ID" do
37
- plan = Stripe::Plan.create(
38
- :name => 'The Mock Plan',
39
- :amount => 9900,
40
- :currency => 'USD',
41
- :interval => 1,
42
- :product => {
43
- :name => 'A product'
44
- }
45
- )
46
-
47
- expect(plan.id).to match(/^test_plan/)
46
+ expect(plan_attributes_without_id[:id]).to be_nil
47
+ expect(plan_without_id.id).to match(/^test_plan_1/)
48
48
  end
49
49
 
50
50
  it "stores a created stripe plan in memory" do
51
- plan = Stripe::Plan.create(
52
- :id => 'pid_2',
53
- :name => 'The Memory Plan',
54
- :amount => 1100,
55
- :currency => 'USD',
56
- :interval => 1,
57
- :product => {
58
- :name => 'A product'
59
- }
60
- )
61
- plan2 = Stripe::Plan.create(
62
- :id => 'pid_3',
63
- :name => 'The Bonk Plan',
64
- :amount => 7777,
65
- :currency => 'USD',
66
- :interval => 1,
67
- :product => {
68
- :name => 'A product'
69
- }
70
- )
51
+ plan
52
+ plan2 = Stripe::Plan.create(plan_attributes.merge(id: "plan_def456", amount: 299))
53
+
71
54
  data = test_data_source(:plans)
72
55
  expect(data[plan.id]).to_not be_nil
73
- expect(data[plan.id][:amount]).to eq(1100)
74
-
56
+ expect(data[plan.id][:amount]).to eq(9900)
75
57
  expect(data[plan2.id]).to_not be_nil
76
- expect(data[plan2.id][:amount]).to eq(7777)
58
+ expect(data[plan2.id][:amount]).to eq(299)
77
59
  end
78
60
 
79
-
80
61
  it "retrieves a stripe plan" do
81
- original = stripe_helper.create_plan(amount: 1331)
62
+ original = stripe_helper.create_plan(product: product_id, amount: 1331, id: 'plan_943843')
82
63
  plan = Stripe::Plan.retrieve(original.id)
83
64
 
84
65
  expect(plan.id).to eq(original.id)
85
66
  expect(plan.amount).to eq(original.amount)
86
67
  end
87
68
 
88
-
89
69
  it "updates a stripe plan" do
90
- stripe_helper.create_plan(id: 'super_member', amount: 111)
70
+ stripe_helper.create_plan(id: 'super_member', product: product_id, amount: 111)
91
71
 
92
72
  plan = Stripe::Plan.retrieve('super_member')
93
73
  expect(plan.amount).to eq(111)
@@ -98,7 +78,6 @@ shared_examples 'Plan API' do
98
78
  expect(plan.amount).to eq(789)
99
79
  end
100
80
 
101
-
102
81
  it "cannot retrieve a stripe plan that doesn't exist" do
103
82
  expect { Stripe::Plan.retrieve('nope') }.to raise_error {|e|
104
83
  expect(e).to be_a Stripe::InvalidRequestError
@@ -108,7 +87,7 @@ shared_examples 'Plan API' do
108
87
  end
109
88
 
110
89
  it "deletes a stripe plan" do
111
- stripe_helper.create_plan(id: 'super_member', amount: 111)
90
+ stripe_helper.create_plan(id: 'super_member', product: product_id, amount: 111)
112
91
 
113
92
  plan = Stripe::Plan.retrieve('super_member')
114
93
  expect(plan).to_not be_nil
@@ -123,10 +102,10 @@ shared_examples 'Plan API' do
123
102
  end
124
103
 
125
104
  it "retrieves all plans" do
126
- stripe_helper.create_plan(id: 'Plan One', amount: 54321)
127
- stripe_helper.create_plan(id: 'Plan Two', amount: 98765)
105
+ stripe_helper.create_plan(id: 'Plan One', product: product_id, amount: 54321)
106
+ stripe_helper.create_plan(id: 'Plan Two', product: product_id, amount: 98765)
128
107
 
129
- all = Stripe::Plan.all
108
+ all = Stripe::Plan.list
130
109
  expect(all.count).to eq(2)
131
110
  expect(all.map &:id).to include('Plan One', 'Plan Two')
132
111
  expect(all.map &:amount).to include(54321, 98765)
@@ -134,33 +113,31 @@ shared_examples 'Plan API' do
134
113
 
135
114
  it 'retrieves plans with limit' do
136
115
  101.times do | i|
137
- stripe_helper.create_plan(id: "Plan #{i}", amount: 11)
116
+ stripe_helper.create_plan(id: "Plan #{i}", product: product_id, amount: 11)
138
117
  end
139
- all = Stripe::Plan.all(limit: 100)
118
+ all = Stripe::Plan.list(limit: 100)
140
119
 
141
120
  expect(all.count).to eq(100)
142
121
  end
143
122
 
144
- it 'validates the amount' do
145
- expect {
146
- Stripe::Plan.create(
147
- :id => 'pid_1',
148
- :name => 'The Mock Plan',
149
- :amount => 99.99,
150
- :currency => 'USD',
151
- :interval => 'month',
152
- :product => {
153
- :name => 'A product'
154
- }
155
- )
156
- }.to raise_error(Stripe::InvalidRequestError, "Invalid integer: 99.99")
157
- end
158
-
159
- describe "Validation", :live => true do
160
- let(:params) { stripe_helper.create_plan_params }
123
+ describe "Validations", :live => true do
124
+ include_context "stripe validator"
125
+ let(:params) { stripe_helper.create_plan_params(product: product_id) }
161
126
  let(:subject) { Stripe::Plan.create(params) }
162
127
 
163
- describe "Required Parameters" do
128
+ describe "Associations" do
129
+ let(:not_found_product_id){ "prod_NONEXIST" }
130
+ let(:not_found_message) { stripe_validator.not_found_message(Stripe::Product, not_found_product_id) }
131
+ let(:params) { stripe_helper.create_plan_params(product: not_found_product_id) }
132
+ let(:products) { stripe_helper.list_products(100).data }
133
+
134
+ it "validates associated product" do
135
+ expect(products.map(&:id)).to_not include(not_found_product_id)
136
+ expect { subject }.to raise_error(Stripe::InvalidRequestError, not_found_message)
137
+ end
138
+ end
139
+
140
+ describe "Presence" do
164
141
  after do
165
142
  params.delete(@name)
166
143
  message =
@@ -172,13 +149,49 @@ shared_examples 'Plan API' do
172
149
  expect { subject }.to raise_error(Stripe::InvalidRequestError, message)
173
150
  end
174
151
 
175
- it("requires a product") { @name = :product }
176
- it("requires an amount") { @name = :amount }
177
- it("requires a currency") { @name = :currency }
178
- it("requires an interval") { @name = :interval }
152
+ it("validates presence of interval") { @name = :interval }
153
+ it("validates presence of currency") { @name = :currency }
154
+ it("validates presence of product") { @name = :product }
155
+ it("validates presence of amount") { @name = :amount }
156
+ end
157
+
158
+ describe "Inclusion" do
159
+ let(:invalid_interval) { "OOPS" }
160
+ let(:invalid_interval_message) { stripe_validator.invalid_plan_interval_message }
161
+ let(:invalid_interval_params) { params.merge({interval: invalid_interval}) }
162
+ let(:plan_with_invalid_interval) { Stripe::Plan.create(invalid_interval_params) }
163
+
164
+ before(:each) do
165
+ product
166
+ end
167
+
168
+ it "validates inclusion of interval" do
169
+ expect { plan_with_invalid_interval }.to raise_error(Stripe::InvalidRequestError, invalid_interval_message)
170
+ end
171
+
172
+ let(:invalid_currency) { "OOPS" }
173
+ let(:invalid_currency_message) { stripe_validator.invalid_currency_message(invalid_currency) }
174
+ let(:invalid_currency_params) { params.merge({currency: invalid_currency}) }
175
+ let(:plan_with_invalid_currency) { Stripe::Plan.create(invalid_currency_params) }
176
+
177
+ it "validates inclusion of currency" do
178
+ expect { plan_with_invalid_currency }.to raise_error(Stripe::InvalidRequestError, invalid_currency_message)
179
+ end
180
+ end
181
+
182
+ describe "Numericality" do
183
+ let(:invalid_integer) { 99.99 }
184
+ let(:invalid_integer_message) { stripe_validator.invalid_integer_message(invalid_integer)}
185
+
186
+ it 'validates amount is an integer' do
187
+ expect {
188
+ Stripe::Plan.create( plan_attributes.merge({amount: invalid_integer}) )
189
+ }.to raise_error(Stripe::InvalidRequestError, invalid_integer_message)
190
+ end
179
191
  end
180
192
 
181
193
  describe "Uniqueness" do
194
+ let(:already_exists_message) { stripe_validator.already_exists_message(Stripe::Plan) }
182
195
 
183
196
  it "validates for uniqueness" do
184
197
  stripe_helper.delete_plan(params[:id])
@@ -186,9 +199,39 @@ shared_examples 'Plan API' do
186
199
  Stripe::Plan.create(params)
187
200
  expect {
188
201
  Stripe::Plan.create(params)
189
- }.to raise_error(Stripe::InvalidRequestError, "Plan already exists.")
202
+ }.to raise_error(Stripe::InvalidRequestError, already_exists_message)
190
203
  end
191
204
  end
205
+
206
+ end
207
+
208
+ describe "Mock Data" do
209
+ let(:mock_object) { StripeMock::Data.mock_plan }
210
+ let(:known_attributes) { [
211
+ :id,
212
+ :object,
213
+ :active,
214
+ :aggregate_usage,
215
+ :amount,
216
+ :billing_scheme,
217
+ :created,
218
+ :currency,
219
+ :interval,
220
+ :interval_count,
221
+ :livemode,
222
+ :metadata,
223
+ :nickname,
224
+ :product,
225
+ :tiers,
226
+ :tiers_mode,
227
+ :transform_usage,
228
+ :trial_period_days,
229
+ :usage_type
230
+ ] }
231
+
232
+ it "includes all retreived attributes" do
233
+ expect(mock_object.keys).to eql(known_attributes)
234
+ end
192
235
  end
193
236
 
194
237
  end
@@ -0,0 +1,292 @@
1
+ require 'spec_helper'
2
+
3
+ shared_examples 'Price API' do
4
+ let(:product_id) { "product_id_1" }
5
+ let(:product) { stripe_helper.create_product(id: product_id) }
6
+
7
+ let(:other_product_id) { "product_id_2" }
8
+ let(:other_product) { stripe_helper.create_product(id: other_product_id) }
9
+
10
+ let(:price_attributes) { {
11
+ :id => "price_abc123",
12
+ :product => product_id,
13
+ :nickname => "My Mock price",
14
+ :amount => 9900,
15
+ :currency => "usd",
16
+ :interval => "month"
17
+ } }
18
+ let(:price) { Stripe::Price.create(price_attributes) }
19
+
20
+ let(:price_attributes_without_id){ price_attributes.merge(id: nil) }
21
+ let(:price_without_id){ Stripe::Price.create(price_attributes_without_id) }
22
+
23
+ let(:price_attributes_with_trial) { price_attributes.merge(id: "prod_TRIAL", :trial_period_days => 30) }
24
+ let(:price_with_trial) { Stripe::Price.create(price_attributes_with_trial) }
25
+
26
+ let(:metadata) { {:description => "desc text", :info => "info text"} }
27
+ let(:price_attributes_with_metadata) { price_attributes.merge(id: "prod_META", metadata: metadata) }
28
+ let(:price_with_metadata) { Stripe::Price.create(price_attributes_with_metadata) }
29
+
30
+ before(:each) do
31
+ product
32
+ other_product
33
+ end
34
+
35
+ it "creates a stripe price" do
36
+ expect(price.id).to eq('price_abc123')
37
+ expect(price.nickname).to eq('My Mock price')
38
+ expect(price.amount).to eq(9900)
39
+
40
+ expect(price.currency).to eq('usd')
41
+ expect(price.interval).to eq("month")
42
+
43
+ expect(price_with_metadata.metadata.description).to eq('desc text')
44
+ expect(price_with_metadata.metadata.info).to eq('info text')
45
+
46
+ expect(price_with_trial.trial_period_days).to eq(30)
47
+ end
48
+
49
+ it "creates a stripe price without specifying ID" do
50
+ expect(price_attributes_without_id[:id]).to be_nil
51
+ expect(price_without_id.id).to match(/^test_price_1/)
52
+ end
53
+
54
+ it "stores a created stripe price in memory" do
55
+ price
56
+ price2 = Stripe::Price.create(price_attributes.merge(id: "price_def456", amount: 299))
57
+
58
+ data = test_data_source(:prices)
59
+ expect(data[price.id]).to_not be_nil
60
+ expect(data[price.id][:amount]).to eq(9900)
61
+ expect(data[price2.id]).to_not be_nil
62
+ expect(data[price2.id][:amount]).to eq(299)
63
+ end
64
+
65
+ it "retrieves a stripe price" do
66
+ original = stripe_helper.create_price(product: product_id, amount: 1331, id: 'price_943843')
67
+ price = Stripe::Price.retrieve(original.id)
68
+
69
+ expect(price.id).to eq(original.id)
70
+ expect(price.amount).to eq(original.amount)
71
+ end
72
+
73
+ it "updates a stripe price" do
74
+ stripe_helper.create_price(id: 'super_member', product: product_id, amount: 111)
75
+
76
+ price = Stripe::Price.retrieve('super_member')
77
+ expect(price.amount).to eq(111)
78
+
79
+ price.amount = 789
80
+ price.save
81
+ price = Stripe::Price.retrieve('super_member')
82
+ expect(price.amount).to eq(789)
83
+ end
84
+
85
+ it "cannot retrieve a stripe price that doesn't exist" do
86
+ expect { Stripe::Price.retrieve('nope') }.to raise_error {|e|
87
+ expect(e).to be_a Stripe::InvalidRequestError
88
+ expect(e.param).to eq('price')
89
+ expect(e.http_status).to eq(404)
90
+ }
91
+ end
92
+
93
+ it "retrieves all prices" do
94
+ stripe_helper.create_price(id: 'price One', product: product_id, amount: 54321)
95
+ stripe_helper.create_price(id: 'price Two', product: product_id, amount: 98765)
96
+
97
+ all = Stripe::Price.list
98
+ expect(all.count).to eq(2)
99
+ expect(all.map &:id).to include('price One', 'price Two')
100
+ expect(all.map &:amount).to include(54321, 98765)
101
+ end
102
+
103
+ it 'retrieves prices with limit' do
104
+ 101.times do | i|
105
+ stripe_helper.create_price(id: "price #{i}", product: product_id, amount: 11)
106
+ end
107
+ all = Stripe::Price.list(limit: 100)
108
+
109
+ expect(all.count).to eq(100)
110
+ end
111
+
112
+ it "retrieves prices with lookup keys" do
113
+ stripe_helper.create_price(id: 'price One', product: product_id, amount: 54321, lookup_key: 'one')
114
+ stripe_helper.create_price(id: 'price Two', product: product_id, amount: 98765, lookup_key: 'two')
115
+
116
+ all = Stripe::Price.list({lookup_keys: ['one', 'two']})
117
+ expect(all.count).to eq(2)
118
+ expect(all.map &:id).to include('price One', 'price Two')
119
+ expect(all.map &:amount).to include(54321, 98765)
120
+
121
+ one = Stripe::Price.list({lookup_keys: ['one']})
122
+ expect(one.count).to eq(1)
123
+ expect(one.map &:id).to include('price One')
124
+ expect(one.map &:amount).to include(54321)
125
+
126
+ two = Stripe::Price.list({lookup_keys: ['two']})
127
+ expect(two.count).to eq(1)
128
+ expect(two.map &:id).to include('price Two')
129
+ expect(two.map &:amount).to include(98765)
130
+ end
131
+
132
+ it "retrieves prices filtering by currency" do
133
+ 5.times do | i|
134
+ stripe_helper.create_price(id: "usd price #{i}", product: product_id, amount: 11, currency: 'usd')
135
+ stripe_helper.create_price(id: "brl price #{i}", product: product_id, amount: 11, currency: 'brl')
136
+ end
137
+
138
+ all = Stripe::Price.list()
139
+ expect(all.count).to eq(10)
140
+
141
+ usd = Stripe::Price.list({currency: 'usd'})
142
+ expect(usd.count).to eq(5)
143
+ expect(usd.all? {|p| p.currency == 'usd' }).to be_truthy
144
+
145
+ brl = Stripe::Price.list({currency: 'brl'})
146
+ expect(brl.count).to eq(5)
147
+ expect(brl.all? {|p| p.currency == 'brl' }).to be_truthy
148
+ end
149
+
150
+ it "retrieves prices filtering by product" do
151
+ 5.times do | i|
152
+ stripe_helper.create_price(id: "product 1 price #{i}", product: product_id)
153
+ stripe_helper.create_price(id: "product 2 price #{i}", product: other_product_id)
154
+ end
155
+
156
+ all = Stripe::Price.list()
157
+ expect(all.count).to eq(10)
158
+
159
+ product_prices = Stripe::Price.list({product: product.id})
160
+ expect(product_prices.count).to eq(5)
161
+ expect(product_prices.all? {|p| p.product == product.id }).to be_truthy
162
+
163
+ other_product_prices = Stripe::Price.list({product: other_product.id})
164
+ expect(other_product_prices.count).to eq(5)
165
+ expect(other_product_prices.all? {|p| p.product == other_product.id }).to be_truthy
166
+ end
167
+
168
+ context "searching prices" do
169
+ # the Search API requires about a minute between writes and reads, so add sleeps accordingly when running live
170
+ it "searches prices for exact matches", :aggregate_failures do
171
+ response = Stripe::Price.search({query: 'currency:"usd"'}, stripe_version: '2020-08-27')
172
+ expect(response.data.size).to eq(0)
173
+
174
+ one = stripe_helper.create_price(
175
+ amount: 100,
176
+ currency: 'usd',
177
+ lookup_key: 'one',
178
+ product: product_id,
179
+ metadata: {key: 'uno'},
180
+ type: "one_time",
181
+ )
182
+ two = stripe_helper.create_price(
183
+ active: false,
184
+ amount: 200,
185
+ currency: 'gbp',
186
+ lookup_key: 'two',
187
+ product: product_id,
188
+ recurring: {interval: 'month'},
189
+ metadata: {key: 'dos'},
190
+ )
191
+
192
+ response = Stripe::Price.search({query: 'active:"true"'}, stripe_version: '2020-08-27')
193
+ expect(response.data.map(&:id)).to match_array([one.id])
194
+
195
+ response = Stripe::Price.search({query: 'currency:"gbp"'}, stripe_version: '2020-08-27')
196
+ expect(response.data.map(&:id)).to match_array([two.id])
197
+
198
+ response = Stripe::Price.search({query: 'lookup_key:"one"'}, stripe_version: '2020-08-27')
199
+ expect(response.data.map(&:id)).to match_array([one.id])
200
+
201
+ response = Stripe::Price.search({query: %(product:"#{product.id}")}, stripe_version: '2020-08-27')
202
+ expect(response.data.map(&:id)).to match_array([one.id, two.id])
203
+
204
+ response = Stripe::Price.search({query: 'type:"recurring"'}, stripe_version: '2020-08-27')
205
+ expect(response.data.map(&:id)).to match_array([two.id])
206
+
207
+ response = Stripe::Price.search({query: 'metadata["key"]:"uno"'}, stripe_version: '2020-08-27')
208
+ expect(response.data.map(&:id)).to match_array([one.id])
209
+ end
210
+
211
+ it "respects limit", :aggregate_failures do
212
+ 11.times do
213
+ stripe_helper.create_price(product: product_id)
214
+ end
215
+
216
+ response = Stripe::Price.search({query: %(product:"#{product.id}")}, stripe_version: '2020-08-27')
217
+ expect(response.data.size).to eq(10)
218
+ response = Stripe::Price.search({query: %(product:"#{product.id}"), limit: 1}, stripe_version: '2020-08-27')
219
+ expect(response.data.size).to eq(1)
220
+ end
221
+
222
+ it "reports search errors", :aggregate_failures do
223
+ expect {
224
+ Stripe::Price.search({limit: 1}, stripe_version: '2020-08-27')
225
+ }.to raise_error(Stripe::InvalidRequestError, /Missing required param: query./)
226
+
227
+ expect {
228
+ Stripe::Price.search({query: 'asdf'}, stripe_version: '2020-08-27')
229
+ }.to raise_error(Stripe::InvalidRequestError, /We were unable to parse your search query./)
230
+
231
+ expect {
232
+ Stripe::Price.search({query: 'foo:"bar"'}, stripe_version: '2020-08-27')
233
+ }.to raise_error(Stripe::InvalidRequestError, /Field `foo` is an unsupported search field for resource `prices`./)
234
+ end
235
+ end
236
+
237
+ describe "Validations", :live => true do
238
+ include_context "stripe validator"
239
+ let(:params) { stripe_helper.create_price_params(product: product_id) }
240
+ let(:subject) { Stripe::Price.create(params) }
241
+
242
+ describe "Associations" do
243
+ let(:not_found_product_id){ "prod_NONEXIST" }
244
+ let(:not_found_message) { stripe_validator.not_found_message(Stripe::Product, not_found_product_id) }
245
+ let(:params) { stripe_helper.create_price_params(product: not_found_product_id) }
246
+ let(:products) { stripe_helper.list_products(100).data }
247
+
248
+ it "validates associated product" do
249
+ expect(products.map(&:id)).to_not include(not_found_product_id)
250
+ expect { subject }.to raise_error(Stripe::InvalidRequestError, not_found_message)
251
+ end
252
+ end
253
+
254
+ describe "Presence" do
255
+ after do
256
+ params.delete(@name)
257
+ message = "Missing required param: #{@name}."
258
+ expect { subject }.to raise_error(Stripe::InvalidRequestError, message)
259
+ end
260
+
261
+ it("validates presence of currency") { @name = :currency }
262
+ end
263
+ end
264
+
265
+ describe "Mock Data" do
266
+ let(:mock_object) { StripeMock::Data.mock_price }
267
+ let(:known_attributes) { [
268
+ :id,
269
+ :object,
270
+ :active,
271
+ :billing_scheme,
272
+ :created,
273
+ :currency,
274
+ :livemode,
275
+ :lookup_key,
276
+ :metadata,
277
+ :nickname,
278
+ :product,
279
+ :recurring,
280
+ :tiers_mode,
281
+ :transform_quantity,
282
+ :type,
283
+ :unit_amount,
284
+ :unit_amount_decimal
285
+ ] }
286
+
287
+ it "includes all retreived attributes" do
288
+ expect(mock_object.keys).to eql(known_attributes)
289
+ end
290
+ end
291
+
292
+ end