stripe-ruby-mock 2.1.1 → 2.2.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 (44) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +1 -0
  3. data/.travis.yml +7 -2
  4. data/README.md +22 -4
  5. data/lib/stripe_mock.rb +2 -0
  6. data/lib/stripe_mock/api/errors.rb +23 -11
  7. data/lib/stripe_mock/api/webhooks.rb +4 -4
  8. data/lib/stripe_mock/data.rb +19 -4
  9. data/lib/stripe_mock/data/list.rb +2 -5
  10. data/lib/stripe_mock/instance.rb +7 -3
  11. data/lib/stripe_mock/request_handlers/accounts.rb +35 -0
  12. data/lib/stripe_mock/request_handlers/charges.rb +28 -0
  13. data/lib/stripe_mock/request_handlers/coupons.rb +3 -2
  14. data/lib/stripe_mock/request_handlers/customers.rb +25 -2
  15. data/lib/stripe_mock/request_handlers/helpers/card_helpers.rb +3 -3
  16. data/lib/stripe_mock/request_handlers/helpers/coupon_helpers.rb +13 -0
  17. data/lib/stripe_mock/request_handlers/invoices.rb +1 -0
  18. data/lib/stripe_mock/request_handlers/subscriptions.rb +30 -2
  19. data/lib/stripe_mock/request_handlers/transfers.rb +5 -0
  20. data/lib/stripe_mock/request_handlers/validators/param_validators.rb +1 -1
  21. data/lib/stripe_mock/test_strategies/base.rb +35 -0
  22. data/lib/stripe_mock/test_strategies/live.rb +13 -0
  23. data/lib/stripe_mock/version.rb +1 -1
  24. data/lib/stripe_mock/webhook_fixtures/{customer.card.created.json → customer.source.created.json} +2 -2
  25. data/lib/stripe_mock/webhook_fixtures/{customer.card.deleted.json → customer.source.deleted.json} +2 -2
  26. data/lib/stripe_mock/webhook_fixtures/{customer.card.updated.json → customer.source.updated.json} +2 -2
  27. data/lib/stripe_mock/webhook_fixtures/transfer.created.json +1 -0
  28. data/lib/stripe_mock/webhook_fixtures/transfer.failed.json +1 -0
  29. data/lib/stripe_mock/webhook_fixtures/transfer.paid.json +1 -0
  30. data/lib/stripe_mock/webhook_fixtures/transfer.updated.json +1 -0
  31. data/spec/integration_examples/charge_token_examples.rb +16 -14
  32. data/spec/integration_examples/prepare_error_examples.rb +20 -0
  33. data/spec/shared_stripe_examples/account_examples.rb +17 -0
  34. data/spec/shared_stripe_examples/card_examples.rb +2 -1
  35. data/spec/shared_stripe_examples/charge_examples.rb +64 -0
  36. data/spec/shared_stripe_examples/coupon_examples.rb +68 -84
  37. data/spec/shared_stripe_examples/customer_examples.rb +57 -2
  38. data/spec/shared_stripe_examples/plan_examples.rb +1 -1
  39. data/spec/shared_stripe_examples/subscription_examples.rb +65 -0
  40. data/spec/shared_stripe_examples/transfer_examples.rb +14 -0
  41. data/spec/spec_helper.rb +18 -3
  42. data/spec/support/stripe_examples.rb +2 -0
  43. data/stripe-ruby-mock.gemspec +1 -1
  44. metadata +31 -41
@@ -23,14 +23,14 @@ module StripeMock
23
23
 
24
24
  is_customer = object.has_key?(:sources)
25
25
 
26
- if replace_current
26
+ if replace_current && cards_or_sources[:data]
27
27
  cards_or_sources[:data].delete_if {|card| card[:id] == object[:default_card]}
28
28
  object[:default_card] = card[:id] unless is_customer
29
29
  object[:default_source] = card[:id] if is_customer
30
30
  cards_or_sources[:data] = [card]
31
31
  else
32
- cards_or_sources[:total_count] += 1
33
- cards_or_sources[:data] << card
32
+ cards_or_sources[:total_count] = cards_or_sources[:total_count] || 0 + 1
33
+ (cards_or_sources[:data] ||= []) << card
34
34
  end
35
35
 
36
36
  object[:default_card] = card[:id] if !is_customer && object[:default_card].nil?
@@ -0,0 +1,13 @@
1
+ module StripeMock
2
+ module RequestHandlers
3
+ module Helpers
4
+
5
+ def add_coupon_to_customer(customer, coupon)
6
+ customer[:discount] = { coupon: coupon }
7
+
8
+ customer
9
+ end
10
+
11
+ end
12
+ end
13
+ end
@@ -20,6 +20,7 @@ module StripeMock
20
20
 
21
21
  def update_invoice(route, method_url, params, headers)
22
22
  route =~ method_url
23
+ params.delete(:lines) if params[:lines]
23
24
  assert_existence :invoice, $1, invoices[$1]
24
25
  invoices[$1].merge!(params)
25
26
  end
@@ -28,8 +28,23 @@ module StripeMock
28
28
 
29
29
  subscription = Data.mock_subscription({ id: (params[:id] || new_id('su')) })
30
30
  subscription.merge!(custom_subscription_params(plan, customer, params))
31
+
32
+ if params[:coupon]
33
+ coupon_id = params[:coupon]
34
+
35
+ raise Stripe::InvalidRequestError.new("No such coupon: #{coupon_id}", 'coupon', 400) unless coupons[coupon_id]
36
+
37
+ # FIXME assert_existence returns 404 error code but Stripe returns 400
38
+ # coupon = assert_existence :coupon, coupon_id, coupons[coupon_id]
39
+
40
+ coupon = Data.mock_coupon({ id: coupon_id })
41
+
42
+ subscription[:discount] = Stripe::Util.convert_to_stripe_object({ coupon: coupon }, {})
43
+ end
44
+
31
45
  add_subscription_to_customer(customer, subscription)
32
46
 
47
+
33
48
  subscription
34
49
  end
35
50
 
@@ -61,9 +76,21 @@ module StripeMock
61
76
  end
62
77
 
63
78
  # expand the plan for addition to the customer object
64
- plan_name = params[:plan] || subscription[:plan][:id]
79
+ plan_name = params[:plan] if params[:plan] && params[:plan] != {}
80
+ plan_name ||= subscription[:plan][:id]
65
81
  plan = plans[plan_name]
66
82
 
83
+ if params[:coupon]
84
+ coupon_id = params[:coupon]
85
+ raise Stripe::InvalidRequestError.new("No such coupon: #{coupon_id}", 'coupon', 400) unless coupons[coupon_id]
86
+
87
+ # FIXME assert_existence returns 404 error code but Stripe returns 400
88
+ # coupon = assert_existence :coupon, coupon_id, coupons[coupon_id]
89
+
90
+ coupon = Data.mock_coupon({ id: coupon_id })
91
+ subscription[:discount] = Stripe::Util.convert_to_stripe_object({ coupon: coupon }, {})
92
+ end
93
+
67
94
  assert_existence :plan, plan_name, plan
68
95
  params[:plan] = plan if params[:plan]
69
96
  verify_card_present(customer, plan)
@@ -111,7 +138,8 @@ module StripeMock
111
138
  private
112
139
 
113
140
  def verify_card_present(customer, plan, params={})
114
- if customer[:default_source].nil? && plan[:trial_period_days].nil? && plan[:amount] != 0 && plan[:trial_end].nil? && params[:trial_end].nil?
141
+ if customer[:default_source].nil? && customer[:trial_end].nil? && plan[:trial_period_days].nil? &&
142
+ plan[:amount] != 0 && plan[:trial_end].nil? && params[:trial_end].nil?
115
143
  raise Stripe::InvalidRequestError.new('You must supply a valid card xoxo', nil, 400)
116
144
  end
117
145
  end
@@ -34,6 +34,11 @@ module StripeMock
34
34
  if params[:bank_account]
35
35
  params[:account] = get_bank_by_token(params.delete(:bank_account))
36
36
  end
37
+
38
+ unless params[:amount].is_a?(Integer) || (params[:amount].is_a?(String) && /^\d+$/.match(params[:amount]))
39
+ raise Stripe::InvalidRequestError.new("Invalid integer: #{params[:amount]}", 'amount', 400)
40
+ end
41
+
37
42
  transfers[id] = Data.mock_transfer(params.merge :id => id)
38
43
  end
39
44
 
@@ -6,7 +6,7 @@ module StripeMock
6
6
  params[:id] = params[:id].to_s
7
7
 
8
8
  @base_strategy.create_plan_params.keys.each do |name|
9
- raise Stripe::InvalidRequestError.new("Missing required param: #{name}", name) if params[name].nil?
9
+ raise Stripe::InvalidRequestError.new("Missing required param: #{name}.", name) if params[name].nil?
10
10
  end
11
11
  if plans[ params[:id] ]
12
12
  raise Stripe::InvalidRequestError.new("Plan already exists.", :id)
@@ -21,6 +21,41 @@ module StripeMock
21
21
  stripe_token.id
22
22
  end
23
23
 
24
+ def create_coupon_params(params = {})
25
+ {
26
+ id: '10BUCKS',
27
+ amount_off: 1000,
28
+ currency: 'usd',
29
+ max_redemptions: 100,
30
+ metadata: {
31
+ created_by: 'admin_acct_1'
32
+ },
33
+ duration: 'once'
34
+ }.merge(params)
35
+ end
36
+
37
+ def create_coupon_percent_of_params(params = {})
38
+ {
39
+ id: '25PERCENT',
40
+ percent_off: 25,
41
+ redeem_by: nil,
42
+ duration_in_months: 3,
43
+ duration: :repeating
44
+ }.merge(params)
45
+ end
46
+
47
+ def create_coupon(params = {})
48
+ Stripe::Coupon.create create_coupon_params(params)
49
+ end
50
+
51
+ def delete_all_coupons
52
+ coupons = Stripe::Coupon.all
53
+ coupons.data.map(&:delete) if coupons.data.count > 0
54
+ end
55
+
56
+ def prepare_card_error
57
+ StripeMock.prepare_card_error(:card_error, :new_customer) if StripeMock.state == 'local'
58
+ end
24
59
  end
25
60
  end
26
61
  end
@@ -17,6 +17,19 @@ module StripeMock
17
17
  end
18
18
  end
19
19
 
20
+ def create_coupon(params={})
21
+ delete_coupon create_coupon_params(params)[:id]
22
+ super
23
+ end
24
+
25
+ def delete_coupon(id)
26
+ begin
27
+ coupon = Stripe::Coupon.retrieve(id)
28
+ coupon.delete
29
+ rescue Stripe::StripeError
30
+ # do nothing
31
+ end
32
+ end
20
33
  end
21
34
  end
22
35
  end
@@ -1,4 +1,4 @@
1
1
  module StripeMock
2
2
  # stripe-ruby-mock version
3
- VERSION = "2.1.1"
3
+ VERSION = "2.2.0"
4
4
  end
@@ -2,7 +2,7 @@
2
2
  "created": 1326853478,
3
3
  "livemode": false,
4
4
  "id": "evt_00000000000000",
5
- "type": "customer.card.created",
5
+ "type": "customer.source.created",
6
6
  "object": "event",
7
7
  "data": {
8
8
  "object": {
@@ -29,4 +29,4 @@
29
29
  "address_zip_check": null
30
30
  }
31
31
  }
32
- }
32
+ }
@@ -2,7 +2,7 @@
2
2
  "created": 1326853478,
3
3
  "livemode": false,
4
4
  "id": "evt_00000000000000",
5
- "type": "customer.card.deleted",
5
+ "type": "customer.source.deleted",
6
6
  "object": "event",
7
7
  "data": {
8
8
  "object": {
@@ -29,4 +29,4 @@
29
29
  "address_zip_check": null
30
30
  }
31
31
  }
32
- }
32
+ }
@@ -2,7 +2,7 @@
2
2
  "created": 1326853478,
3
3
  "livemode": false,
4
4
  "id": "evt_00000000000000",
5
- "type": "customer.card.updated",
5
+ "type": "customer.source.updated",
6
6
  "object": "event",
7
7
  "data": {
8
8
  "object": {
@@ -33,4 +33,4 @@
33
33
  "name": "Testy Tester Jr."
34
34
  }
35
35
  }
36
- }
36
+ }
@@ -52,6 +52,7 @@
52
52
  "object": "list",
53
53
  "count": 1,
54
54
  "url": "/v1/transfers/tr_2h8RC13PPvwDZs/transactions",
55
+ "has_more": false,
55
56
  "data": [
56
57
  {
57
58
  "id": "ch_2fb4RERw49oI8s",
@@ -52,6 +52,7 @@
52
52
  "object": "list",
53
53
  "count": 1,
54
54
  "url": "/v1/transfers/tr_2h8RC13PPvwDZs/transactions",
55
+ "has_more": false,
55
56
  "data": [
56
57
  {
57
58
  "id": "ch_2fb4RERw49oI8s",
@@ -52,6 +52,7 @@
52
52
  "object": "list",
53
53
  "count": 1,
54
54
  "url": "/v1/transfers/tr_2h8RC13PPvwDZs/transactions",
55
+ "has_more": false,
55
56
  "data": [
56
57
  {
57
58
  "id": "ch_2fb4RERw49oI8s",
@@ -52,6 +52,7 @@
52
52
  "object": "list",
53
53
  "count": 1,
54
54
  "url": "/v1/transfers/tr_2h8RC13PPvwDZs/transactions",
55
+ "has_more": false,
55
56
  "data": [
56
57
  {
57
58
  "id": "ch_2fb4RERw49oI8s",
@@ -2,45 +2,47 @@ require 'spec_helper'
2
2
 
3
3
  shared_examples 'Charging with Tokens' do
4
4
 
5
- describe "With OAuth" do
5
+ describe "With OAuth", :oauth => true do
6
6
 
7
- before do
8
- @cus = Stripe::Customer.create(
7
+ let(:cus) do
8
+ Stripe::Customer.create(
9
9
  :source => stripe_helper.generate_card_token({ :number => '4242424242424242', :brand => 'Visa' })
10
10
  )
11
+ end
11
12
 
12
- @card_token = Stripe::Token.create({
13
- :customer => @cus.id,
14
- :source => @cus.sources.first.id
13
+ let(:card_token) do
14
+ Stripe::Token.create({
15
+ :customer => cus.id,
16
+ :source => cus.sources.first.id
15
17
  }, ENV['STRIPE_TEST_OAUTH_ACCESS_TOKEN'])
16
18
  end
17
19
 
18
- it "creates with an oauth access token", :oauth => true do
20
+ it "creates with an oauth access token" do
19
21
  charge = Stripe::Charge.create({
20
22
  :amount => 1099,
21
23
  :currency => 'usd',
22
- :source => @card_token.id
24
+ :source => card_token.id
23
25
  }, ENV['STRIPE_TEST_OAUTH_ACCESS_TOKEN'])
24
26
 
25
- expect(charge.source.id).to_not eq @cus.sources.first.id
26
- expect(charge.source.fingerprint).to eq @cus.sources.first.fingerprint
27
+ expect(charge.source.id).to_not eq cus.sources.first.id
28
+ expect(charge.source.fingerprint).to eq cus.sources.first.fingerprint
27
29
  expect(charge.source.last4).to eq '4242'
28
30
  expect(charge.source.brand).to eq 'Visa'
29
31
 
30
32
  retrieved_charge = Stripe::Charge.retrieve(charge.id)
31
33
 
32
- expect(retrieved_charge.source.id).to_not eq @cus.sources.first.id
33
- expect(retrieved_charge.source.fingerprint).to eq @cus.sources.first.fingerprint
34
+ expect(retrieved_charge.source.id).to_not eq cus.sources.first.id
35
+ expect(retrieved_charge.source.fingerprint).to eq cus.sources.first.fingerprint
34
36
  expect(retrieved_charge.source.last4).to eq '4242'
35
37
  expect(retrieved_charge.source.brand).to eq 'Visa'
36
38
  end
37
39
 
38
- it "throws an error when the card is not an id", :oauth => true do
40
+ it "throws an error when the card is not an id" do
39
41
  expect {
40
42
  charge = Stripe::Charge.create({
41
43
  :amount => 1099,
42
44
  :currency => 'usd',
43
- :source => @card_token
45
+ :source => card_token
44
46
  }, ENV['STRIPE_TEST_OAUTH_ACCESS_TOKEN'])
45
47
  }.to raise_error(Stripe::InvalidRequestError, /Invalid token id/)
46
48
  end
@@ -15,4 +15,24 @@ shared_examples 'Card Error Prep' do
15
15
  # })
16
16
  # }.to raise_error Stripe::CardError
17
17
  # end
18
+
19
+ it 'is a valid card error', live: true do
20
+ stripe_helper.prepare_card_error
21
+
22
+ begin
23
+ Stripe::Customer.create(
24
+ email: 'alice@bob.com',
25
+ source: stripe_helper.generate_card_token(number: '123')
26
+ )
27
+ rescue Stripe::CardError => e
28
+ body = e.json_body
29
+ err = body[:error]
30
+
31
+ expect(body).to be_a(Hash)
32
+ expect(err[:type]).to eq 'card_error'
33
+ expect(err[:param]).to eq 'number'
34
+ expect(err[:code]).to eq 'invalid_number'
35
+ expect(err[:message]).to eq 'This card number looks invalid.'
36
+ end
37
+ end
18
38
  end
@@ -0,0 +1,17 @@
1
+ require 'spec_helper'
2
+
3
+ shared_examples 'Account API' do
4
+ it 'retrieves a stripe account', live: true do
5
+ account = Stripe::Account.retrieve
6
+
7
+ expect(account).to be_a Stripe::Account
8
+ expect(account.id).to match /acct\_/
9
+ end
10
+
11
+ it 'all', live: true do
12
+ accounts = Stripe::Account.all
13
+
14
+ expect(accounts).to be_a Stripe::ListObject
15
+ expect(accounts.data).to eq []
16
+ end
17
+ end
@@ -221,7 +221,8 @@ shared_examples 'Card API' do
221
221
  card_id = "card_123"
222
222
  expect { customer.sources.retrieve(card_id) }.to raise_error {|e|
223
223
  expect(e).to be_a Stripe::InvalidRequestError
224
- expect(e.message).to include "no source", card_id
224
+ expect(e.message).to match /no.*source/i
225
+ expect(e.message).to include card_id
225
226
  expect(e.param).to eq 'id'
226
227
  expect(e.http_status).to eq 404
227
228
  }
@@ -133,6 +133,46 @@ shared_examples 'Charge API' do
133
133
  }
134
134
  end
135
135
 
136
+ it "updates a stripe charge" do
137
+ original = Stripe::Charge.create({
138
+ amount: 777,
139
+ currency: 'USD',
140
+ source: stripe_helper.generate_card_token,
141
+ description: 'Original description',
142
+ })
143
+ charge = Stripe::Charge.retrieve(original.id)
144
+
145
+ charge.description = "Updated description"
146
+ charge.metadata[:receipt_id] = 1234
147
+ charge.receipt_email = "newemail@email.com"
148
+ charge.fraud_details = {"user_report" => "safe"}
149
+ charge.save
150
+
151
+ updated = Stripe::Charge.retrieve(original.id)
152
+
153
+ expect(updated.description).to eq(charge.description)
154
+ expect(updated.metadata.to_hash).to eq(charge.metadata.to_hash)
155
+ expect(updated.receipt_email).to eq(charge.receipt_email)
156
+ expect(updated.fraud_details.to_hash).to eq(charge.fraud_details.to_hash)
157
+ end
158
+
159
+ it "disallows most parameters on updating a stripe charge" do
160
+ original = Stripe::Charge.create({
161
+ amount: 777,
162
+ currency: 'USD',
163
+ source: stripe_helper.generate_card_token,
164
+ description: 'Original description',
165
+ })
166
+
167
+ charge = Stripe::Charge.retrieve(original.id)
168
+ charge.currency = "CAD"
169
+ charge.amount = 777
170
+ charge.source = {any: "source"}
171
+
172
+ expect { charge.save }.to raise_error(Stripe::InvalidRequestError, /Received unknown parameters: currency, amount, source/i)
173
+ end
174
+
175
+
136
176
  it "creates a unique balance transaction" do
137
177
  charge1 = Stripe::Charge.create(
138
178
  amount: 999,
@@ -184,6 +224,30 @@ shared_examples 'Charge API' do
184
224
  end
185
225
  end
186
226
 
227
+ it 'when use starting_after param', live: true do
228
+ cus = Stripe::Customer.create(
229
+ description: 'Customer for test@example.com',
230
+ source: {
231
+ object: 'card',
232
+ number: '4242424242424242',
233
+ exp_month: 12,
234
+ exp_year: 2024
235
+ }
236
+ )
237
+ 12.times do
238
+ Stripe::Charge.create(customer: cus.id, amount: 100, currency: "usd")
239
+ end
240
+
241
+ all = Stripe::Charge.all
242
+ default_limit = 10
243
+ half = Stripe::Charge.all(starting_after: all.data.at(1).id)
244
+
245
+ expect(half).to be_a(Stripe::ListObject)
246
+ expect(half.data.count).to eq(default_limit)
247
+ expect(half.data.first.id).to eq(all.data.at(2).id)
248
+ end
249
+
250
+
187
251
  describe 'captured status value' do
188
252
  it "reports captured by default" do
189
253
  charge = Stripe::Charge.create({