Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Allow stripe >=6 #1

Merged
merged 23 commits into from
Aug 20, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
b811935
Implement search API
adamstegman May 9, 2022
803419d
Updated gem to use Stripe gem v7. And, fixed rspecs.
smakani Nov 9, 2022
4d267ac
Updated Stripe gem reference to 7.1.0
smakani Nov 9, 2022
a414aa9
Final changes
smakani Nov 15, 2022
b05c1b2
Adds support for stripe-ruby v10
fabianoarruda Nov 26, 2023
2f0fbb8
Fixes compatibility with new param introduced in v10.3
fabianoarruda Jan 9, 2024
d3a6d39
Upgrade rspec to v3.12
fabianoarruda Jan 10, 2024
1c616c1
Adds optional `usage` introduced with stripe ruby v10.3
fabianoarruda Jan 10, 2024
844108e
Updated gems
alexmamonchik Feb 10, 2024
8c4bd51
Added ruby 3.2 to Github Actions
alexmamonchik Feb 10, 2024
c38f5b5
Merge branch 'init-v4' into search
alexmamonchik Feb 10, 2024
8034047
Merge pull request #830 from adamstegman/search
alexmamonchik Feb 10, 2024
1d08c8c
Update README.md
smakani Feb 10, 2024
415bbea
Merge branch 'init-v4' into master
smakani Feb 10, 2024
ab53d99
Updated Stripe version referenced in gemspec
smakani Feb 10, 2024
1714394
Merge pull request #848 from smakani/master
alexmamonchik Feb 10, 2024
d693f43
Revert "Upgrade rspec to v3.12"
fabianoarruda Nov 26, 2023
4f63f7d
Merge branch 'init-v4' into commits-from-fabio
alexmamonchik Feb 10, 2024
99d7430
Merge pull request #898 from stripe-ruby-mock/commits-from-fabio
alexmamonchik Feb 10, 2024
f67afb9
Added merged PRs to changelog
alexmamonchik Feb 10, 2024
84c8a50
Removed Subscription.delet in one test
alexmamonchik Feb 10, 2024
cbf5121
Allow Stripe SDK v11
stevenharman Apr 19, 2024
906200e
chore: minor README update
tferrerm Aug 5, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/rspec_tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ jobs:
runs-on: ubuntu-latest
strategy:
matrix:
ruby-version: ['2.6', '2.7', '3.0']
ruby-version: ['2.7', '3.0', '3.2']

steps:
- uses: actions/checkout@v3
Expand Down
6 changes: 6 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,11 @@
### Unreleased

- [#830](https://github.com/stripe-ruby-mock/stripe-ruby-mock/pull/830) Implement search API by [@adamstegman](https://github.com/adamstegman)
- [#848](https://github.com/stripe-ruby-mock/stripe-ruby-mock/pull/848) Extending runtime dependency on Stripe gem from version 5 through 11 by [@smakani](https://github.com/smakani)
- [#893](https://github.com/stripe-ruby-mock/stripe-ruby-mock/pull/893) Adds support for stripe-ruby v10 by [@fabianoarruda](https://github.com/fabianoarruda)


### 3.1.0 (2024-01-03)
- [#693](https://github.com/stripe-ruby-mock/stripe-ruby-mock/pull/693) gemspec: add change,issue,source_code URL by [@mtmail](https://github.com/mtmail)
- [#700](https://github.com/stripe-ruby-mock/stripe-ruby-mock/pull/700) update the balance API to respond with instant_available by [@iamnader](https://github.com/iamnader)
- [#687](https://github.com/stripe-ruby-mock/stripe-ruby-mock/pull/687) Add PaymentIntent Webhooks by [@klaustopher](https://github.com/klaustopher)
Expand Down
5 changes: 0 additions & 5 deletions Gemfile
Original file line number Diff line number Diff line change
@@ -1,10 +1,5 @@
source 'https://rubygems.org'

platforms :ruby_19 do
gem 'mime-types', '~> 2.6'
gem 'rest-client', '~> 1.8'
end

group :test do
gem 'rake'
gem 'dotenv'
Expand Down
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -29,8 +29,8 @@ version `3.0.0` has [breaking changes](https://github.com/stripe-ruby-mock/strip

### Requirements

* ruby >= 2.6.0
* stripe >= 5.0.0
* ruby >= 2.7.0
* stripe > 5 & < 12

### Specifications

Expand Down
1 change: 1 addition & 0 deletions lib/stripe_mock.rb
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@
require 'stripe_mock/request_handlers/helpers/card_helpers.rb'
require 'stripe_mock/request_handlers/helpers/charge_helpers.rb'
require 'stripe_mock/request_handlers/helpers/coupon_helpers.rb'
require 'stripe_mock/request_handlers/helpers/search_helpers.rb'
require 'stripe_mock/request_handlers/helpers/subscription_helpers.rb'
require 'stripe_mock/request_handlers/helpers/token_helpers.rb'

Expand Down
2 changes: 1 addition & 1 deletion lib/stripe_mock/api/client.rb
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ def self.stop_client(opts={})

private

def self.redirect_to_mock_server(method, url, api_key: nil, api_base: nil, params: {}, headers: {})
def self.redirect_to_mock_server(method, url, api_key: nil, api_base: nil, usage: [], params: {}, headers: {})
handler = Instance.handler_for_method_url("#{method} #{url}")

if mock_error = client.error_queue.error_for_handler_name(handler[:name])
Expand Down
2 changes: 1 addition & 1 deletion lib/stripe_mock/instance.rb
Original file line number Diff line number Diff line change
Expand Up @@ -109,7 +109,7 @@ def initialize
@base_strategy = TestStrategies::Base.new
end

def mock_request(method, url, api_key: nil, api_base: nil, params: {}, headers: {})
def mock_request(method, url, api_key: nil, api_base: nil, usage: [], params: {}, headers: {})
return {} if method == :xtest

api_key ||= (Stripe.api_key || DUMMY_API_KEY)
Expand Down
21 changes: 20 additions & 1 deletion lib/stripe_mock/request_handlers/charges.rb
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,8 @@ module Charges
def Charges.included(klass)
klass.add_handler 'post /v1/charges', :new_charge
klass.add_handler 'get /v1/charges', :get_charges
klass.add_handler 'get /v1/charges/(.*)', :get_charge
klass.add_handler 'get /v1/charges/search', :search_charges
klass.add_handler 'get /v1/charges/((?!search).*)', :get_charge
klass.add_handler 'post /v1/charges/(.*)/capture', :capture_charge
klass.add_handler 'post /v1/charges/(.*)/refund', :refund_charge
klass.add_handler 'post /v1/charges/(.*)/refunds', :refund_charge
Expand Down Expand Up @@ -90,6 +91,24 @@ def get_charges(route, method_url, params, headers)
Data.mock_list_object(clone.values, params)
end

SEARCH_FIELDS = [
"amount",
"currency",
"customer",
"payment_method_details.card.brand",
"payment_method_details.card.exp_month",
"payment_method_details.card.exp_year",
"payment_method_details.card.fingerprint",
"payment_method_details.card.last4",
"status",
].freeze
def search_charges(route, method_url, params, headers)
require_param(:query) unless params[:query]

results = search_results(charges.values, params[:query], fields: SEARCH_FIELDS, resource_name: "charges")
Data.mock_list_object(results, params)
end

def get_charge(route, method_url, params, headers)
route =~ method_url
charge_id = $1 || params[:charge]
Expand Down
13 changes: 12 additions & 1 deletion lib/stripe_mock/request_handlers/customers.rb
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,10 @@ module Customers
def Customers.included(klass)
klass.add_handler 'post /v1/customers', :new_customer
klass.add_handler 'post /v1/customers/([^/]*)', :update_customer
klass.add_handler 'get /v1/customers/([^/]*)', :get_customer
klass.add_handler 'get /v1/customers/((?!search)[^/]*)', :get_customer
klass.add_handler 'delete /v1/customers/([^/]*)', :delete_customer
klass.add_handler 'get /v1/customers', :list_customers
klass.add_handler 'get /v1/customers/search', :search_customers
klass.add_handler 'delete /v1/customers/([^/]*)/discount', :delete_customer_discount
end

Expand Down Expand Up @@ -140,6 +141,16 @@ def list_customers(route, method_url, params, headers)
Data.mock_list_object(customers[stripe_account]&.values, params)
end

SEARCH_FIELDS = ["email", "name", "phone"].freeze
def search_customers(route, method_url, params, headers)
require_param(:query) unless params[:query]

stripe_account = headers && headers[:stripe_account] || Stripe.api_key
all_customers = customers[stripe_account]&.values
results = search_results(all_customers, params[:query], fields: SEARCH_FIELDS, resource_name: "customers")
Data.mock_list_object(results, params)
end

def delete_customer_discount(route, method_url, params, headers)
stripe_account = headers && headers[:stripe_account] || Stripe.api_key
route =~ method_url
Expand Down
67 changes: 67 additions & 0 deletions lib/stripe_mock/request_handlers/helpers/search_helpers.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
module StripeMock
module RequestHandlers
module Helpers
# Only supports exact matches on a single field, e.g.
# - 'amount:100'
# - 'email:"[email protected]"'
# - 'name:"Foo Bar"'
# - 'metadata["foo"]:"bar"'
QUERYSTRING_PATTERN = /\A(?<field>[\w\.]+)(\[['"](?<metadata_key>[^'"]*)['"]\])?:['"]?(?<value>[^'"]*)['"]?\z/
def search_results(all_values, querystring, fields: [], resource_name:)
values = all_values.dup
query_match = QUERYSTRING_PATTERN.match(querystring)
raise Stripe::InvalidRequestError.new(
'We were unable to parse your search query.' \
' Try using the format `metadata["key"]:"value"` to query for metadata or key:"value" to query for other fields.',
nil,
http_status: 400,
) unless query_match

case query_match[:field]
when *fields
values = values.select { |resource|
exact_match?(actual: field_value(resource, field: query_match[:field]), expected: query_match[:value])
}
when "metadata"
values = values.select { |resource|
resource[:metadata] &&
exact_match?(actual: resource[:metadata][query_match[:metadata_key].to_sym], expected: query_match[:value])
}
else
raise Stripe::InvalidRequestError.new(
"Field `#{query_match[:field]}` is an unsupported search field for resource `#{resource_name}`." \
" See http://stripe.com/docs/search#query-fields-for-#{resource_name.gsub('_', '-')} for a list of supported fields.",
nil,
http_status: 400,
)
end

values
end

def exact_match?(actual:, expected:)
# allow comparisons of integers
if actual.respond_to?(:to_i) && actual.to_i == actual
expected = expected.to_i
end
# allow comparisons of boolean
case expected
when "true"
expected = true
when "false"
expected = false
end

actual == expected
end

def field_value(resource, field:)
value = resource
field.split('.').each do |segment|
value = value[segment.to_sym]
end
value
end
end
end
end
11 changes: 10 additions & 1 deletion lib/stripe_mock/request_handlers/invoices.rb
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,8 @@ def Invoices.included(klass)
klass.add_handler 'post /v1/invoices', :new_invoice
klass.add_handler 'get /v1/invoices/upcoming', :upcoming_invoice
klass.add_handler 'get /v1/invoices/(.*)/lines', :get_invoice_line_items
klass.add_handler 'get /v1/invoices/(.*)', :get_invoice
klass.add_handler 'get /v1/invoices/((?!search).*)', :get_invoice
klass.add_handler 'get /v1/invoices/search', :search_invoices
klass.add_handler 'get /v1/invoices', :list_invoices
klass.add_handler 'post /v1/invoices/(.*)/pay', :pay_invoice
klass.add_handler 'post /v1/invoices/(.*)', :update_invoice
Expand All @@ -25,6 +26,14 @@ def update_invoice(route, method_url, params, headers)
invoices[$1].merge!(params)
end

SEARCH_FIELDS = ["currency", "customer", "number", "receipt_number", "subscription", "total"].freeze
def search_invoices(route, method_url, params, headers)
require_param(:query) unless params[:query]

results = search_results(invoices.values, params[:query], fields: SEARCH_FIELDS, resource_name: "invoices")
Data.mock_list_object(results, params)
end

def list_invoices(route, method_url, params, headers)
params[:offset] ||= 0
params[:limit] ||= 10
Expand Down
11 changes: 10 additions & 1 deletion lib/stripe_mock/request_handlers/payment_intents.rb
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,8 @@ module PaymentIntents
def PaymentIntents.included(klass)
klass.add_handler 'post /v1/payment_intents', :new_payment_intent
klass.add_handler 'get /v1/payment_intents', :get_payment_intents
klass.add_handler 'get /v1/payment_intents/(.*)', :get_payment_intent
klass.add_handler 'get /v1/payment_intents/((?!search).*)', :get_payment_intent
klass.add_handler 'get /v1/payment_intents/search', :search_payment_intents
klass.add_handler 'post /v1/payment_intents/(.*)/confirm', :confirm_payment_intent
klass.add_handler 'post /v1/payment_intents/(.*)/capture', :capture_payment_intent
klass.add_handler 'post /v1/payment_intents/(.*)/cancel', :cancel_payment_intent
Expand Down Expand Up @@ -70,6 +71,14 @@ def get_payment_intent(route, method_url, params, headers)
payment_intent
end

SEARCH_FIELDS = ["amount", "currency", "customer", "status"].freeze
def search_payment_intents(route, method_url, params, headers)
require_param(:query) unless params[:query]

results = search_results(payment_intents.values, params[:query], fields: SEARCH_FIELDS, resource_name: "payment_intents")
Data.mock_list_object(results, params)
end

def capture_payment_intent(route, method_url, params, headers)
route =~ method_url
payment_intent = assert_existence :payment_intent, $1, payment_intents[$1]
Expand Down
17 changes: 13 additions & 4 deletions lib/stripe_mock/request_handlers/prices.rb
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,11 @@ module RequestHandlers
module Prices

def Prices.included(klass)
klass.add_handler 'post /v1/prices', :new_price
klass.add_handler 'post /v1/prices/(.*)', :update_price
klass.add_handler 'get /v1/prices/(.*)', :get_price
klass.add_handler 'get /v1/prices', :list_prices
klass.add_handler 'post /v1/prices', :new_price
klass.add_handler 'post /v1/prices/(.*)', :update_price
klass.add_handler 'get /v1/prices/((?!search).*)', :get_price
klass.add_handler 'get /v1/prices/search', :search_prices
klass.add_handler 'get /v1/prices', :list_prices
end

def new_price(route, method_url, params, headers)
Expand Down Expand Up @@ -57,6 +58,14 @@ def list_prices(route, method_url, params, headers)

Data.mock_list_object(price_data.first(limit), params.merge!(limit: limit))
end

SEARCH_FIELDS = ["active", "currency", "lookup_key", "product", "type"].freeze
def search_prices(route, method_url, params, headers)
require_param(:query) unless params[:query]

results = search_results(prices.values, params[:query], fields: SEARCH_FIELDS, resource_name: "prices")
Data.mock_list_object(results, params)
end
end
end
end
19 changes: 14 additions & 5 deletions lib/stripe_mock/request_handlers/products.rb
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,12 @@ module StripeMock
module RequestHandlers
module Products
def self.included(base)
base.add_handler 'post /v1/products', :create_product
base.add_handler 'get /v1/products/(.*)', :retrieve_product
base.add_handler 'post /v1/products/(.*)', :update_product
base.add_handler 'get /v1/products', :list_products
base.add_handler 'delete /v1/products/(.*)', :destroy_product
base.add_handler 'post /v1/products', :create_product
base.add_handler 'get /v1/products/((?!search).*)', :retrieve_product
base.add_handler 'get /v1/products/search', :search_products
base.add_handler 'post /v1/products/(.*)', :update_product
base.add_handler 'get /v1/products', :list_products
base.add_handler 'delete /v1/products/(.*)', :destroy_product
end

def create_product(_route, _method_url, params, _headers)
Expand All @@ -32,6 +33,14 @@ def list_products(_route, _method_url, params, _headers)
Data.mock_list_object(products.values.take(limit), params)
end

SEARCH_FIELDS = ["active", "description", "name", "shippable", "url"].freeze
def search_products(route, method_url, params, headers)
require_param(:query) unless params[:query]

results = search_results(products.values, params[:query], fields: SEARCH_FIELDS, resource_name: "products")
Data.mock_list_object(results, params)
end

def destroy_product(route, method_url, _params, _headers)
id = method_url.match(route).captures.first
assert_existence :product, id, products[id]
Expand Down
11 changes: 10 additions & 1 deletion lib/stripe_mock/request_handlers/subscriptions.rb
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,9 @@ module Subscriptions
def Subscriptions.included(klass)
klass.add_handler 'get /v1/subscriptions', :retrieve_subscriptions
klass.add_handler 'post /v1/subscriptions', :create_subscription
klass.add_handler 'get /v1/subscriptions/(.*)', :retrieve_subscription
klass.add_handler 'get /v1/subscriptions/((?!search).*)', :retrieve_subscription
klass.add_handler 'post /v1/subscriptions/(.*)', :update_subscription
klass.add_handler 'get /v1/subscriptions/search', :search_subscriptions
klass.add_handler 'delete /v1/subscriptions/(.*)', :cancel_subscription

klass.add_handler 'post /v1/customers/(.*)/subscription(?:s)?', :create_customer_subscription
Expand Down Expand Up @@ -343,6 +344,14 @@ def cancel_subscription(route, method_url, params, headers)
subscription
end

SEARCH_FIELDS = ["status"].freeze
def search_subscriptions(route, method_url, params, headers)
require_param(:query) unless params[:query]

results = search_results(subscriptions.values, params[:query], fields: SEARCH_FIELDS, resource_name: "subscriptions")
Data.mock_list_object(results, params)
end

private

def get_subscription_plans_from_params(params)
Expand Down
12 changes: 5 additions & 7 deletions spec/shared_stripe_examples/bank_token_examples.rb
Original file line number Diff line number Diff line change
Expand Up @@ -28,20 +28,19 @@
expect(bank_token).to match /^test_btok/
end

it "assigns the generated bank account to a new recipient" do
it "assigns the generated bank account to a new customer" do
bank_token = StripeMock.generate_bank_token(
:bank_name => "Bank Token Mocking",
:last4 => "7777"
)

recipient = Stripe::Recipient.create({
customer = Stripe::Customer.create({
name: "Fred Flinstone",
type: "individual",
email: '[email protected]',
bank_account: bank_token
source: bank_token
})
expect(recipient.active_account.last4).to eq("7777")
expect(recipient.active_account.bank_name).to eq("Bank Token Mocking")
expect(customer.sources.first.last4).to eq("7777")
expect(customer.sources.first.bank_name).to eq("Bank Token Mocking")
end

it "retrieves a created token" do
Expand All @@ -55,5 +54,4 @@
expect(token.bank_account.last4).to eq("3939")
expect(token.bank_account.bank_name).to eq("Cha-ching Banking")
end

end
Loading
Loading