stripe-ruby-mock 2.1.1 → 2.2.0

Sign up to get free protection for your applications and to get access to all the features.
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({