mustwin-stripe-ruby-mock 1.8.4.10

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 (89) hide show
  1. data/.gitignore +5 -0
  2. data/.rspec +1 -0
  3. data/.travis.yml +5 -0
  4. data/ChangeLog.rdoc +4 -0
  5. data/Gemfile +7 -0
  6. data/LICENSE.txt +22 -0
  7. data/README.md +264 -0
  8. data/Rakefile +28 -0
  9. data/bin/stripe-mock-server +19 -0
  10. data/lib/stripe_mock.rb +46 -0
  11. data/lib/stripe_mock/api/card_tokens.rb +22 -0
  12. data/lib/stripe_mock/api/client.rb +37 -0
  13. data/lib/stripe_mock/api/debug.rb +11 -0
  14. data/lib/stripe_mock/api/errors.rb +41 -0
  15. data/lib/stripe_mock/api/instance.rb +27 -0
  16. data/lib/stripe_mock/api/server.rb +24 -0
  17. data/lib/stripe_mock/api/strict.rb +11 -0
  18. data/lib/stripe_mock/api/webhooks.rb +64 -0
  19. data/lib/stripe_mock/client.rb +84 -0
  20. data/lib/stripe_mock/data.rb +317 -0
  21. data/lib/stripe_mock/error_queue.rb +23 -0
  22. data/lib/stripe_mock/errors/closed_client_connection_error.rb +9 -0
  23. data/lib/stripe_mock/errors/server_timeout_error.rb +12 -0
  24. data/lib/stripe_mock/errors/stripe_mock_error.rb +15 -0
  25. data/lib/stripe_mock/errors/uninitialized_instance_error.rb +9 -0
  26. data/lib/stripe_mock/errors/unstarted_state_error.rb +9 -0
  27. data/lib/stripe_mock/errors/unsupported_request_error.rb +4 -0
  28. data/lib/stripe_mock/instance.rb +108 -0
  29. data/lib/stripe_mock/request_handlers/charges.rb +33 -0
  30. data/lib/stripe_mock/request_handlers/customers.rb +107 -0
  31. data/lib/stripe_mock/request_handlers/invoice_items.rb +15 -0
  32. data/lib/stripe_mock/request_handlers/plans.rb +43 -0
  33. data/lib/stripe_mock/server.rb +58 -0
  34. data/lib/stripe_mock/util.rb +22 -0
  35. data/lib/stripe_mock/version.rb +4 -0
  36. data/lib/stripe_mock/webhook_fixtures/account.application.deauthorized.json +12 -0
  37. data/lib/stripe_mock/webhook_fixtures/account.updated.json +24 -0
  38. data/lib/stripe_mock/webhook_fixtures/charge.dispute.closed.json +21 -0
  39. data/lib/stripe_mock/webhook_fixtures/charge.dispute.created.json +21 -0
  40. data/lib/stripe_mock/webhook_fixtures/charge.dispute.updated.json +24 -0
  41. data/lib/stripe_mock/webhook_fixtures/charge.failed.json +57 -0
  42. data/lib/stripe_mock/webhook_fixtures/charge.refunded.json +57 -0
  43. data/lib/stripe_mock/webhook_fixtures/charge.succeeded.json +57 -0
  44. data/lib/stripe_mock/webhook_fixtures/coupon.created.json +22 -0
  45. data/lib/stripe_mock/webhook_fixtures/coupon.deleted.json +22 -0
  46. data/lib/stripe_mock/webhook_fixtures/customer.created.json +40 -0
  47. data/lib/stripe_mock/webhook_fixtures/customer.deleted.json +40 -0
  48. data/lib/stripe_mock/webhook_fixtures/customer.discount.created.json +28 -0
  49. data/lib/stripe_mock/webhook_fixtures/customer.discount.deleted.json +28 -0
  50. data/lib/stripe_mock/webhook_fixtures/customer.discount.updated.json +43 -0
  51. data/lib/stripe_mock/webhook_fixtures/customer.subscription.created.json +34 -0
  52. data/lib/stripe_mock/webhook_fixtures/customer.subscription.deleted.json +34 -0
  53. data/lib/stripe_mock/webhook_fixtures/customer.subscription.trial_will_end.json +34 -0
  54. data/lib/stripe_mock/webhook_fixtures/customer.subscription.updated.json +47 -0
  55. data/lib/stripe_mock/webhook_fixtures/customer.updated.json +43 -0
  56. data/lib/stripe_mock/webhook_fixtures/invoice.created.json +64 -0
  57. data/lib/stripe_mock/webhook_fixtures/invoice.payment_failed.json +64 -0
  58. data/lib/stripe_mock/webhook_fixtures/invoice.payment_succeeded.json +64 -0
  59. data/lib/stripe_mock/webhook_fixtures/invoice.updated.json +67 -0
  60. data/lib/stripe_mock/webhook_fixtures/invoiceitem.created.json +21 -0
  61. data/lib/stripe_mock/webhook_fixtures/invoiceitem.deleted.json +21 -0
  62. data/lib/stripe_mock/webhook_fixtures/invoiceitem.updated.json +24 -0
  63. data/lib/stripe_mock/webhook_fixtures/plan.created.json +20 -0
  64. data/lib/stripe_mock/webhook_fixtures/plan.deleted.json +20 -0
  65. data/lib/stripe_mock/webhook_fixtures/plan.updated.json +23 -0
  66. data/lib/stripe_mock/webhook_fixtures/transfer.created.json +23 -0
  67. data/lib/stripe_mock/webhook_fixtures/transfer.failed.json +23 -0
  68. data/lib/stripe_mock/webhook_fixtures/transfer.paid.json +23 -0
  69. data/lib/stripe_mock/webhook_fixtures/transfer.updated.json +26 -0
  70. data/lib/trollop.rb +782 -0
  71. data/spec/_dummy/webhooks/dummy.event.json +6 -0
  72. data/spec/fixtures/stripe_webhooks/account.updated.json +7 -0
  73. data/spec/fixtures/stripe_webhooks/custom.account.updated.json +5 -0
  74. data/spec/instance_spec.rb +49 -0
  75. data/spec/readme_spec.rb +72 -0
  76. data/spec/server_spec.rb +131 -0
  77. data/spec/shared_stripe_examples/card_token_examples.rb +28 -0
  78. data/spec/shared_stripe_examples/charge_examples.rb +123 -0
  79. data/spec/shared_stripe_examples/customer_examples.rb +218 -0
  80. data/spec/shared_stripe_examples/error_mock_examples.rb +152 -0
  81. data/spec/shared_stripe_examples/invoice_item_examples.rb +17 -0
  82. data/spec/shared_stripe_examples/plan_examples.rb +123 -0
  83. data/spec/spec_helper.rb +11 -0
  84. data/spec/stripe_mock_spec.rb +40 -0
  85. data/spec/support/stripe_examples.rb +18 -0
  86. data/spec/util_spec.rb +45 -0
  87. data/spec/webhook_spec.rb +77 -0
  88. data/stripe-ruby-mock.gemspec +27 -0
  89. metadata +253 -0
@@ -0,0 +1,23 @@
1
+ module StripeMock
2
+ class ErrorQueue
3
+
4
+ def initialize
5
+ @queue = []
6
+ end
7
+
8
+ def queue(error, handler_names)
9
+ @queue << handler_names.map {|n| [n, error]}
10
+ end
11
+
12
+ def error_for_handler_name(handler_name)
13
+ return nil if @queue.count == 0
14
+ triggers = @queue.first
15
+ (triggers.assoc(:all) || triggers.assoc(handler_name) || [])[1]
16
+ end
17
+
18
+ def dequeue
19
+ @queue.shift
20
+ end
21
+
22
+ end
23
+ end
@@ -0,0 +1,9 @@
1
+ module StripeMock
2
+ class ClosedClientConnectionError < StripeMockError
3
+
4
+ def initialize
5
+ super("This StripeMock client has already been closed.")
6
+ end
7
+
8
+ end
9
+ end
@@ -0,0 +1,12 @@
1
+ module StripeMock
2
+ class ServerTimeoutError < StripeMockError
3
+
4
+ attr_reader :associated_error
5
+
6
+ def initialize(associated_error)
7
+ @associated_error = associated_error
8
+ super("Unable to connect to stripe mock server (did you forget to run `$ stripe-mock-server`?)")
9
+ end
10
+
11
+ end
12
+ end
@@ -0,0 +1,15 @@
1
+ module StripeMock
2
+ class StripeMockError < StandardError
3
+
4
+ attr_reader :message
5
+
6
+ def initialize(message)
7
+ @message = message
8
+ end
9
+
10
+ def to_s
11
+ @message
12
+ end
13
+
14
+ end
15
+ end
@@ -0,0 +1,9 @@
1
+ module StripeMock
2
+ class UninitializedInstanceError < StripeMockError
3
+
4
+ def initialize
5
+ super("StripeMock instance is nil (did you forget to call `StripeMock.start`?)")
6
+ end
7
+
8
+ end
9
+ end
@@ -0,0 +1,9 @@
1
+ module StripeMock
2
+ class UnstartedStateError < StripeMockError
3
+
4
+ def initialize
5
+ super("StripeMock has not been started. Please call StripeMock.start or StripeMock.start_client")
6
+ end
7
+
8
+ end
9
+ end
@@ -0,0 +1,4 @@
1
+ module StripeMock
2
+ class UnsupportedRequestError < StripeMockError
3
+ end
4
+ end
@@ -0,0 +1,108 @@
1
+ module StripeMock
2
+ class Instance
3
+
4
+ # Handlers are ordered by priority
5
+ @@handlers = []
6
+
7
+ def self.add_handler(route, name)
8
+ @@handlers << {
9
+ :route => %r{^#{route}$},
10
+ :name => name
11
+ }
12
+ end
13
+
14
+ def self.handler_for_method_url(method_url)
15
+ @@handlers.find {|h| method_url =~ h[:route] }
16
+ end
17
+
18
+ include StripeMock::RequestHandlers::Charges
19
+ include StripeMock::RequestHandlers::Customers
20
+ include StripeMock::RequestHandlers::InvoiceItems
21
+ include StripeMock::RequestHandlers::Plans
22
+
23
+
24
+ attr_reader :charges, :customers, :plans, :error_queue
25
+ attr_accessor :debug, :strict
26
+
27
+ def initialize
28
+ @customers = {}
29
+ @charges = {}
30
+ @plans = {}
31
+ @recipient_tokens = {}
32
+ @card_tokens = {}
33
+
34
+ @id_counter = 0
35
+ @error_queue = ErrorQueue.new
36
+ @debug = false
37
+ @strict = true
38
+ end
39
+
40
+ def mock_request(method, url, api_key, params={}, headers={})
41
+ return {} if method == :xtest
42
+
43
+ # Ensure params hash has symbols as keys
44
+ params = Stripe::Util.symbolize_names(params)
45
+
46
+ method_url = "#{method} #{url}"
47
+
48
+ if handler = Instance.handler_for_method_url(method_url)
49
+ if @debug == true
50
+ puts "[StripeMock req]::#{handler[:name]} #{method} #{url}"
51
+ puts " #{params}"
52
+ end
53
+
54
+ if mock_error = @error_queue.error_for_handler_name(handler[:name])
55
+ @error_queue.dequeue
56
+ raise mock_error
57
+ else
58
+ res = self.send(handler[:name], handler[:route], method_url, params, headers)
59
+ puts " [res] #{res}" if @debug == true
60
+ [res, api_key]
61
+ end
62
+ else
63
+ puts "WARNING: Unrecognized method + url: [#{method} #{url}]"
64
+ puts " params: #{params}"
65
+ [{}, api_key]
66
+ end
67
+ end
68
+
69
+ def generate_recipient_token(recipient_params)
70
+ token = new_id 'tok'
71
+ recipient_params[:id] = new_id 'rec'
72
+ @recipient_tokens[token] = Data.mock_card(recipient_params)
73
+ token
74
+ end
75
+
76
+ def generate_card_token(card_params)
77
+ token = new_id 'tok'
78
+ card_params[:id] = new_id 'cc'
79
+ @card_tokens[token] = Data.mock_card(card_params)
80
+ token
81
+ end
82
+
83
+ def get_card_by_token(token)
84
+ if token.nil? || @card_tokens[token].nil?
85
+ Data.mock_card :id => new_id('cc')
86
+ else
87
+ @card_tokens.delete(token)
88
+ end
89
+ end
90
+
91
+ private
92
+
93
+ def assert_existance(type, id, obj, message=nil)
94
+ return unless @strict == true
95
+
96
+ if obj.nil?
97
+ msg = message || "No such #{type}: #{id}"
98
+ raise Stripe::InvalidRequestError.new(msg, type.to_s, 404)
99
+ end
100
+ end
101
+
102
+ def new_id(prefix)
103
+ # Stripe ids must be strings
104
+ "test_#{prefix}_#{@id_counter += 1}"
105
+ end
106
+
107
+ end
108
+ end
@@ -0,0 +1,33 @@
1
+ module StripeMock
2
+ module RequestHandlers
3
+ module Charges
4
+
5
+ def Charges.included(klass)
6
+ klass.add_handler 'post /v1/charges', :new_charge
7
+ klass.add_handler 'get /v1/charges/(.*)', :get_charge
8
+ klass.add_handler 'post /v1/charges/(.*)/capture', :capture_charge
9
+ end
10
+
11
+ def new_charge(route, method_url, params, headers)
12
+ id = new_id('ch')
13
+ charges[id] = Data.mock_charge(params.merge :id => id)
14
+ end
15
+
16
+ def get_charge(route, method_url, params, headers)
17
+ route =~ method_url
18
+ assert_existance :charge, $1, charges[$1]
19
+ charges[$1] ||= Data.mock_charge(:id => $1)
20
+ end
21
+
22
+ def capture_charge(route, method_url, params, headers)
23
+ route =~ method_url
24
+ charge = charges[$1]
25
+ assert_existance :charge, $1, charge
26
+
27
+ charge[:captured] = true
28
+ charge
29
+ end
30
+
31
+ end
32
+ end
33
+ end
@@ -0,0 +1,107 @@
1
+ module StripeMock
2
+ module RequestHandlers
3
+ module Customers
4
+
5
+ def Customers.included(klass)
6
+ klass.add_handler 'post /v1/customers', :new_customer
7
+ klass.add_handler 'post /v1/customers/(.*)/subscription', :update_subscription
8
+ klass.add_handler 'delete /v1/customers/(.*)/subscription', :cancel_subscription
9
+ klass.add_handler 'post /v1/customers/(.*)', :update_customer
10
+ klass.add_handler 'get /v1/customers/(.*)', :get_customer
11
+ klass.add_handler 'delete /v1/customers/(.*)', :delete_customer
12
+ klass.add_handler 'get /v1/customers', :list_customers
13
+ end
14
+
15
+ def new_customer(route, method_url, params, headers)
16
+ params[:id] ||= new_id('cus')
17
+ cards = []
18
+ if params[:card]
19
+ cards << get_card_by_token(params.delete(:card))
20
+ params[:default_card] = cards.first[:id]
21
+ end
22
+ customers[ params[:id] ] = Data.mock_customer(cards, params)
23
+ end
24
+
25
+ def update_subscription(route, method_url, params, headers)
26
+ route =~ method_url
27
+
28
+ customer = customers[$1]
29
+ assert_existance :customer, $1, customer
30
+
31
+ plan = plans[ params[:plan] ]
32
+ assert_existance :plan, params[:plan], plan
33
+
34
+ # Ensure customer has card to charge if plan has no trial and is not free
35
+ if customer[:default_card].nil? && plan[:trial_period_days].nil? && plan[:amount] != 0
36
+ raise Stripe::InvalidRequestError.new('You must supply a valid card', nil, 400)
37
+ end
38
+
39
+ sub = Data.mock_subscription id: new_id('su'), plan: plan, customer: $1
40
+ customer[:subscription] = sub
41
+ end
42
+
43
+ def cancel_subscription(route, method_url, params, headers)
44
+ route =~ method_url
45
+
46
+ customer = customers[$1]
47
+ assert_existance :customer, $1, customer
48
+
49
+ sub = customer[:subscription]
50
+ assert_existance nil, nil, sub, "No active subscription for customer: #{$1}"
51
+
52
+ customer[:subscription] = nil
53
+
54
+ plan = plans[ sub[:plan][:id] ]
55
+ assert_existance :plan, params[:plan], plan
56
+
57
+ Data.mock_delete_subscription(id: sub[:id])
58
+ end
59
+
60
+ def update_customer(route, method_url, params, headers)
61
+ route =~ method_url
62
+ assert_existance :customer, $1, customers[$1]
63
+
64
+ cus = customers[$1] ||= Data.mock_customer([], :id => $1)
65
+ cus.merge!(params)
66
+
67
+ if params[:card]
68
+ new_card = get_card_by_token(params.delete(:card))
69
+
70
+ if cus[:cards][:count] == 0
71
+ cus[:cards][:count] += 1
72
+ else
73
+ cus[:cards][:data].delete_if {|card| card[:id] == cus[:default_card]}
74
+ end
75
+
76
+ cus[:cards][:data] << new_card
77
+ cus[:default_card] = new_card[:id]
78
+ end
79
+
80
+ cus
81
+ end
82
+
83
+ def delete_customer(route, method_url, params, headers)
84
+ route =~ method_url
85
+ assert_existance :customer, $1, customers[$1]
86
+
87
+ customers[$1] = {
88
+ id: customers[$1][:id],
89
+ deleted: true
90
+ }
91
+
92
+ customers[$1]
93
+ end
94
+
95
+ def get_customer(route, method_url, params, headers)
96
+ route =~ method_url
97
+ assert_existance :customer, $1, customers[$1]
98
+ customers[$1] ||= Data.mock_customer([], :id => $1)
99
+ end
100
+
101
+ def list_customers(route, method_url, params, headers)
102
+ customers.values
103
+ end
104
+
105
+ end
106
+ end
107
+ end
@@ -0,0 +1,15 @@
1
+ module StripeMock
2
+ module RequestHandlers
3
+ module InvoiceItems
4
+
5
+ def InvoiceItems.included(klass)
6
+ klass.add_handler 'post /v1/invoiceitems', :new_invoice_item
7
+ end
8
+
9
+ def new_invoice_item(route, method_url, params, headers)
10
+ Data.mock_invoice(params)
11
+ end
12
+
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,43 @@
1
+ module StripeMock
2
+ module RequestHandlers
3
+ module Plans
4
+
5
+ def Plans.included(klass)
6
+ klass.add_handler 'post /v1/plans', :new_plan
7
+ klass.add_handler 'post /v1/plans/(.*)', :update_plan
8
+ klass.add_handler 'get /v1/plans/(.*)', :get_plan
9
+ klass.add_handler 'delete /v1/plans/(.*)', :delete_plan
10
+ klass.add_handler 'get /v1/plans', :list_plans
11
+ end
12
+
13
+ def new_plan(route, method_url, params, headers)
14
+ params[:id] ||= new_id('plan')
15
+ plans[ params[:id] ] = Data.mock_plan(params)
16
+ end
17
+
18
+ def update_plan(route, method_url, params, headers)
19
+ route =~ method_url
20
+ assert_existance :plan, $1, plans[$1]
21
+ plans[$1] ||= Data.mock_plan(:id => $1)
22
+ plans[$1].merge!(params)
23
+ end
24
+
25
+ def get_plan(route, method_url, params, headers)
26
+ route =~ method_url
27
+ assert_existance :plan, $1, plans[$1]
28
+ plans[$1] ||= Data.mock_plan(:id => $1)
29
+ end
30
+
31
+ def delete_plan(route, method_url, params, headers)
32
+ route =~ method_url
33
+ assert_existance :plan, $1, plans[$1]
34
+ plans.delete($1)
35
+ end
36
+
37
+ def list_plans(route, method_url, params, headers)
38
+ plans.values
39
+ end
40
+
41
+ end
42
+ end
43
+ end
@@ -0,0 +1,58 @@
1
+ require 'jimson-temp'
2
+
3
+ module StripeMock
4
+
5
+ class Server
6
+ extend Jimson::Handler
7
+
8
+ def self.start_new(opts)
9
+ server = Jimson::Server.new(Server.new,
10
+ :host => opts[:host] || '0.0.0.0',
11
+ :port => opts[:port] || 4999,
12
+ :server => opts[:server] || :thin,
13
+ :show_errors => true
14
+ )
15
+ server.start
16
+ end
17
+
18
+ def initialize
19
+ self.clear_data
20
+ end
21
+
22
+ def mock_request(*args)
23
+ begin
24
+ @instance.mock_request(*args)
25
+ rescue Stripe::InvalidRequestError => e
26
+ {
27
+ :error_raised => 'invalid_request',
28
+ :error_params => [e.message, e.param, e.http_status, e.http_body, e.json_body]
29
+ }
30
+ end
31
+ end
32
+
33
+ def get_data(key)
34
+ @instance.send(key)
35
+ end
36
+
37
+ def clear_data
38
+ @instance = Instance.new
39
+ end
40
+
41
+ def set_debug(toggle)
42
+ @instance.debug = toggle
43
+ end
44
+
45
+ def set_strict(toggle)
46
+ @instance.strict = toggle
47
+ end
48
+
49
+ def generate_card_token(card_params)
50
+ @instance.generate_card_token(card_params)
51
+ end
52
+
53
+ def debug?; @instance.debug; end
54
+ def strict?; @instance.strict; end
55
+ def ping; true; end
56
+ end
57
+
58
+ end