mirror of
https://github.com/gooba42/adventureland.git
synced 2026-10-14 18:39:27 -05:00
Open source
This commit is contained in:
Executable
+13
@@ -0,0 +1,13 @@
|
||||
import os
|
||||
import unittest2
|
||||
|
||||
|
||||
def all():
|
||||
path = os.path.dirname(os.path.realpath(__file__))
|
||||
return unittest2.defaultTestLoader.discover(path)
|
||||
|
||||
|
||||
def resources():
|
||||
path = os.path.dirname(os.path.realpath(__file__))
|
||||
return unittest2.defaultTestLoader.discover(
|
||||
os.path.join(path, "resources"))
|
||||
Executable
+238
@@ -0,0 +1,238 @@
|
||||
import datetime
|
||||
import os
|
||||
import random
|
||||
import re
|
||||
import string
|
||||
import sys
|
||||
import unittest2
|
||||
|
||||
from mock import patch, Mock
|
||||
|
||||
import libraries.stripe
|
||||
|
||||
NOW = datetime.datetime.now()
|
||||
|
||||
DUMMY_CARD = {
|
||||
'number': '4242424242424242',
|
||||
'exp_month': NOW.month,
|
||||
'exp_year': NOW.year + 4
|
||||
}
|
||||
DUMMY_DEBIT_CARD = {
|
||||
'number': '4000056655665556',
|
||||
'exp_month': NOW.month,
|
||||
'exp_year': NOW.year + 4
|
||||
}
|
||||
DUMMY_CHARGE = {
|
||||
'amount': 100,
|
||||
'currency': 'usd',
|
||||
'card': DUMMY_CARD
|
||||
}
|
||||
|
||||
DUMMY_DISPUTE = {
|
||||
'status': 'needs_response',
|
||||
'currency': 'usd',
|
||||
'metadata': {}
|
||||
}
|
||||
|
||||
DUMMY_PLAN = {
|
||||
'amount': 2000,
|
||||
'interval': 'month',
|
||||
'name': 'Amazing Gold Plan',
|
||||
'currency': 'usd',
|
||||
'id': ('stripe-test-gold-' +
|
||||
''.join(random.choice(string.ascii_lowercase) for x in range(10)))
|
||||
}
|
||||
|
||||
DUMMY_COUPON = {
|
||||
'percent_off': 25,
|
||||
'duration': 'repeating',
|
||||
'duration_in_months': 5,
|
||||
'metadata': {}
|
||||
}
|
||||
|
||||
DUMMY_RECIPIENT = {
|
||||
'name': 'John Doe',
|
||||
'type': 'individual'
|
||||
}
|
||||
|
||||
DUMMY_TRANSFER = {
|
||||
'amount': 400,
|
||||
'currency': 'usd',
|
||||
'recipient': 'self'
|
||||
}
|
||||
|
||||
DUMMY_INVOICE_ITEM = {
|
||||
'amount': 456,
|
||||
'currency': 'usd',
|
||||
}
|
||||
|
||||
SAMPLE_INVOICE = libraries.stripe.util.json.loads("""
|
||||
{
|
||||
"amount_due": 1305,
|
||||
"attempt_count": 0,
|
||||
"attempted": true,
|
||||
"charge": "ch_wajkQ5aDTzFs5v",
|
||||
"closed": true,
|
||||
"customer": "cus_osllUe2f1BzrRT",
|
||||
"date": 1338238728,
|
||||
"discount": null,
|
||||
"ending_balance": 0,
|
||||
"id": "in_t9mHb2hpK7mml1",
|
||||
"livemode": false,
|
||||
"next_payment_attempt": null,
|
||||
"object": "invoice",
|
||||
"paid": true,
|
||||
"period_end": 1338238728,
|
||||
"period_start": 1338238716,
|
||||
"starting_balance": -8695,
|
||||
"subtotal": 10000,
|
||||
"total": 10000,
|
||||
"lines": {
|
||||
"invoiceitems": [],
|
||||
"prorations": [],
|
||||
"subscriptions": [
|
||||
{
|
||||
"plan": {
|
||||
"interval": "month",
|
||||
"object": "plan",
|
||||
"identifier": "expensive",
|
||||
"currency": "usd",
|
||||
"livemode": false,
|
||||
"amount": 10000,
|
||||
"name": "Expensive Plan",
|
||||
"trial_period_days": null,
|
||||
"id": "expensive"
|
||||
},
|
||||
"period": {
|
||||
"end": 1340917128,
|
||||
"start": 1338238728
|
||||
},
|
||||
"amount": 10000
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
""")
|
||||
|
||||
|
||||
class StripeTestCase(unittest2.TestCase):
|
||||
RESTORE_ATTRIBUTES = ('api_version', 'api_key')
|
||||
|
||||
def setUp(self):
|
||||
super(StripeTestCase, self).setUp()
|
||||
|
||||
self._stripe_original_attributes = {}
|
||||
|
||||
for attr in self.RESTORE_ATTRIBUTES:
|
||||
self._stripe_original_attributes[attr] = getattr(stripe, attr)
|
||||
|
||||
api_base = os.environ.get('STRIPE_API_BASE')
|
||||
if api_base:
|
||||
libraries.stripe.api_base = api_base
|
||||
libraries.stripe.api_key = os.environ.get(
|
||||
'STRIPE_API_KEY', 'tGN0bIwXnHdwOa85VABjPdSn8nWY7G7I')
|
||||
|
||||
def tearDown(self):
|
||||
super(StripeTestCase, self).tearDown()
|
||||
|
||||
for attr in self.RESTORE_ATTRIBUTES:
|
||||
setattr(stripe, attr, self._stripe_original_attributes[attr])
|
||||
|
||||
# Python < 2.7 compatibility
|
||||
def assertRaisesRegexp(self, exception, regexp, callable, *args, **kwargs):
|
||||
try:
|
||||
callable(*args, **kwargs)
|
||||
except exception as err:
|
||||
if regexp is None:
|
||||
return True
|
||||
|
||||
if isinstance(regexp, basestring):
|
||||
regexp = re.compile(regexp)
|
||||
if not regexp.search(str(err)):
|
||||
raise self.failureException('"%s" does not match "%s"' %
|
||||
(regexp.pattern, str(err)))
|
||||
else:
|
||||
raise self.failureException(
|
||||
'%s was not raised' % (exception.__name__,))
|
||||
|
||||
|
||||
class StripeUnitTestCase(StripeTestCase):
|
||||
REQUEST_LIBRARIES = ['urlfetch', 'requests', 'pycurl']
|
||||
|
||||
if sys.version_info >= (3, 0):
|
||||
REQUEST_LIBRARIES.append('urllib.request')
|
||||
else:
|
||||
REQUEST_LIBRARIES.append('urllib2')
|
||||
|
||||
def setUp(self):
|
||||
super(StripeUnitTestCase, self).setUp()
|
||||
|
||||
self.request_patchers = {}
|
||||
self.request_mocks = {}
|
||||
for lib in self.REQUEST_LIBRARIES:
|
||||
patcher = patch("stripe.http_client.%s" % (lib,))
|
||||
|
||||
self.request_mocks[lib] = patcher.start()
|
||||
self.request_patchers[lib] = patcher
|
||||
|
||||
def tearDown(self):
|
||||
super(StripeUnitTestCase, self).tearDown()
|
||||
|
||||
for patcher in self.request_patchers.itervalues():
|
||||
patcher.stop()
|
||||
|
||||
|
||||
class StripeApiTestCase(StripeTestCase):
|
||||
|
||||
def setUp(self):
|
||||
super(StripeApiTestCase, self).setUp()
|
||||
|
||||
self.requestor_patcher = patch('stripe.api_requestor.APIRequestor')
|
||||
requestor_class_mock = self.requestor_patcher.start()
|
||||
self.requestor_mock = requestor_class_mock.return_value
|
||||
|
||||
def tearDown(self):
|
||||
super(StripeApiTestCase, self).tearDown()
|
||||
|
||||
self.requestor_patcher.stop()
|
||||
|
||||
def mock_response(self, res):
|
||||
self.requestor_mock.request = Mock(return_value=(res, 'reskey'))
|
||||
|
||||
|
||||
class StripeResourceTest(StripeApiTestCase):
|
||||
|
||||
def setUp(self):
|
||||
super(StripeResourceTest, self).setUp()
|
||||
self.mock_response({})
|
||||
|
||||
|
||||
class MyResource(stripe.resource.APIResource):
|
||||
pass
|
||||
|
||||
|
||||
class MySingleton(stripe.resource.SingletonAPIResource):
|
||||
pass
|
||||
|
||||
|
||||
class MyListable(stripe.resource.ListableAPIResource):
|
||||
pass
|
||||
|
||||
|
||||
class MyCreatable(stripe.resource.CreateableAPIResource):
|
||||
pass
|
||||
|
||||
|
||||
class MyUpdateable(stripe.resource.UpdateableAPIResource):
|
||||
pass
|
||||
|
||||
|
||||
class MyDeletable(stripe.resource.DeletableAPIResource):
|
||||
pass
|
||||
|
||||
|
||||
class MyComposite(stripe.resource.ListableAPIResource,
|
||||
libraries.stripe.resource.CreateableAPIResource,
|
||||
libraries.stripe.resource.UpdateableAPIResource,
|
||||
libraries.stripe.resource.DeletableAPIResource):
|
||||
pass
|
||||
+154
@@ -0,0 +1,154 @@
|
||||
import libraries.stripe
|
||||
from libraries.stripe.test.helper import StripeResourceTest
|
||||
|
||||
|
||||
class AccountTest(StripeResourceTest):
|
||||
|
||||
def test_retrieve_account_deprecated(self):
|
||||
libraries.stripe.Account.retrieve()
|
||||
|
||||
self.requestor_mock.request.assert_called_with(
|
||||
'get',
|
||||
'/v1/account',
|
||||
{},
|
||||
None
|
||||
)
|
||||
|
||||
def test_retrieve_account(self):
|
||||
libraries.stripe.Account.retrieve('acct_foo')
|
||||
self.requestor_mock.request.assert_called_with(
|
||||
'get',
|
||||
'/v1/accounts/acct_foo',
|
||||
{},
|
||||
None
|
||||
)
|
||||
|
||||
def test_list_accounts(self):
|
||||
libraries.stripe.Account.list()
|
||||
self.requestor_mock.request.assert_called_with(
|
||||
'get',
|
||||
'/v1/accounts',
|
||||
{}
|
||||
)
|
||||
|
||||
def test_create_account(self):
|
||||
pii = {
|
||||
'type': 'individual',
|
||||
'first_name': 'Joe',
|
||||
'last_name': 'Smith',
|
||||
}
|
||||
libraries.stripe.Account.create(legal_entity=pii)
|
||||
self.requestor_mock.request.assert_called_with(
|
||||
'post',
|
||||
'/v1/accounts',
|
||||
{
|
||||
'legal_entity': pii,
|
||||
},
|
||||
None,
|
||||
)
|
||||
|
||||
def test_update_account(self):
|
||||
acct = libraries.stripe.Account.construct_from({
|
||||
'id': 'acct_update',
|
||||
'legal_entity': {'first_name': 'Joe'},
|
||||
}, 'api_key')
|
||||
acct.legal_entity['first_name'] = 'Bob'
|
||||
acct.save()
|
||||
|
||||
self.requestor_mock.request.assert_called_with(
|
||||
'post',
|
||||
'/v1/accounts/acct_update',
|
||||
{
|
||||
'legal_entity': {
|
||||
'first_name': 'Bob',
|
||||
},
|
||||
},
|
||||
None,
|
||||
)
|
||||
|
||||
def test_account_delete_bank_account(self):
|
||||
source = libraries.stripe.BankAccount.construct_from({
|
||||
'account': 'acc_delete_ba',
|
||||
'id': 'ba_delete_ba',
|
||||
}, 'api_key')
|
||||
source.delete()
|
||||
|
||||
self.requestor_mock.request.assert_called_with(
|
||||
'delete',
|
||||
'/v1/accounts/acc_delete_ba/external_accounts/ba_delete_ba',
|
||||
{},
|
||||
None
|
||||
)
|
||||
|
||||
def test_reject_account(self):
|
||||
self.mock_response({
|
||||
'id': 'acct_reject',
|
||||
'verification': {
|
||||
'disabled_reason': 'rejected.fraud'
|
||||
},
|
||||
})
|
||||
|
||||
obj = libraries.stripe.Account.construct_from({
|
||||
'id': 'acct_reject'
|
||||
}, 'mykey')
|
||||
|
||||
self.assertTrue(obj is obj.reject(reason='fraud'))
|
||||
self.assertEqual('rejected.fraud', obj.verification['disabled_reason'])
|
||||
self.assertEqual('acct_reject', obj.id)
|
||||
|
||||
self.requestor_mock.request.assert_called_with(
|
||||
'post',
|
||||
'/v1/accounts/acct_reject/reject',
|
||||
{'reason': 'fraud'},
|
||||
None
|
||||
)
|
||||
|
||||
def test_reject_account_without_reason(self):
|
||||
self.mock_response({
|
||||
'id': 'acct_reject',
|
||||
'verification': {
|
||||
'disabled_reason': 'rejected.fraud'
|
||||
},
|
||||
})
|
||||
|
||||
obj = libraries.stripe.Account.construct_from({
|
||||
'id': 'acct_reject'
|
||||
}, 'mykey')
|
||||
|
||||
self.assertTrue(obj is obj.reject())
|
||||
self.assertEqual('rejected.fraud', obj.verification['disabled_reason'])
|
||||
self.assertEqual('acct_reject', obj.id)
|
||||
|
||||
self.requestor_mock.request.assert_called_with(
|
||||
'post',
|
||||
'/v1/accounts/acct_reject/reject',
|
||||
{},
|
||||
None
|
||||
)
|
||||
|
||||
def test_verify_additional_owner(self):
|
||||
acct = libraries.stripe.Account.construct_from({
|
||||
'id': 'acct_update',
|
||||
'additional_owners': [{
|
||||
'first_name': 'Alice',
|
||||
'verification': {},
|
||||
}]
|
||||
}, 'api_key')
|
||||
owner = acct.additional_owners[0]
|
||||
owner.verification.document = 'file_foo'
|
||||
acct.save()
|
||||
|
||||
self.requestor_mock.request.assert_called_with(
|
||||
'post',
|
||||
'/v1/accounts/acct_update',
|
||||
{
|
||||
'additional_owners': {
|
||||
'0': {
|
||||
'verification': {
|
||||
'document': 'file_foo',
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
None,
|
||||
)
|
||||
+86
@@ -0,0 +1,86 @@
|
||||
import libraries.stripe
|
||||
from libraries.stripe.test.helper import (
|
||||
StripeApiTestCase, MyResource, MySingleton
|
||||
)
|
||||
|
||||
|
||||
class APIResourceTests(StripeApiTestCase):
|
||||
|
||||
def test_retrieve_and_refresh(self):
|
||||
self.mock_response({
|
||||
'id': 'foo2',
|
||||
'bobble': 'scrobble',
|
||||
})
|
||||
|
||||
res = MyResource.retrieve('foo*', myparam=5)
|
||||
|
||||
url = '/v1/myresources/foo%2A'
|
||||
self.requestor_mock.request.assert_called_with(
|
||||
'get', url, {'myparam': 5}, None
|
||||
)
|
||||
|
||||
self.assertEqual('scrobble', res.bobble)
|
||||
self.assertEqual('foo2', res.id)
|
||||
self.assertEqual('reskey', res.api_key)
|
||||
|
||||
self.mock_response({
|
||||
'frobble': 5,
|
||||
})
|
||||
|
||||
res = res.refresh()
|
||||
|
||||
url = '/v1/myresources/foo2'
|
||||
self.requestor_mock.request.assert_called_with(
|
||||
'get', url, {'myparam': 5}, None
|
||||
)
|
||||
|
||||
self.assertEqual(5, res.frobble)
|
||||
self.assertRaises(KeyError, res.__getitem__, 'bobble')
|
||||
|
||||
def test_convert_to_stripe_object(self):
|
||||
sample = {
|
||||
'foo': 'bar',
|
||||
'adict': {
|
||||
'object': 'charge',
|
||||
'id': 42,
|
||||
'amount': 7,
|
||||
},
|
||||
'alist': [
|
||||
{
|
||||
'object': 'customer',
|
||||
'name': 'chilango'
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
converted = libraries.stripe.resource.convert_to_stripe_object(
|
||||
sample, 'akey', None)
|
||||
|
||||
# Types
|
||||
self.assertTrue(isinstance(converted, libraries.stripe.resource.StripeObject))
|
||||
self.assertTrue(isinstance(converted.adict, libraries.stripe.Charge))
|
||||
self.assertEqual(1, len(converted.alist))
|
||||
self.assertTrue(isinstance(converted.alist[0], libraries.stripe.Customer))
|
||||
|
||||
# Values
|
||||
self.assertEqual('bar', converted.foo)
|
||||
self.assertEqual(42, converted.adict.id)
|
||||
self.assertEqual('chilango', converted.alist[0].name)
|
||||
|
||||
# Stripping
|
||||
# TODO: We should probably be stripping out this property
|
||||
# self.assertRaises(AttributeError, getattr, converted.adict, 'object')
|
||||
|
||||
|
||||
class SingletonAPIResourceTests(StripeApiTestCase):
|
||||
|
||||
def test_retrieve(self):
|
||||
self.mock_response({
|
||||
'single': 'ton'
|
||||
})
|
||||
res = MySingleton.retrieve()
|
||||
|
||||
self.requestor_mock.request.assert_called_with(
|
||||
'get', '/v1/mysingleton', {}, None)
|
||||
|
||||
self.assertEqual('ton', res.single)
|
||||
+113
@@ -0,0 +1,113 @@
|
||||
import libraries.stripe
|
||||
from libraries.stripe.test.helper import StripeResourceTest
|
||||
|
||||
|
||||
class ApplicationFeeTest(StripeResourceTest):
|
||||
|
||||
def test_list_application_fees(self):
|
||||
libraries.stripe.ApplicationFee.list()
|
||||
self.requestor_mock.request.assert_called_with(
|
||||
'get',
|
||||
'/v1/application_fees',
|
||||
{}
|
||||
)
|
||||
|
||||
|
||||
class ApplicationFeeRefundTest(StripeResourceTest):
|
||||
|
||||
def test_fetch_refund(self):
|
||||
fee = libraries.stripe.ApplicationFee.construct_from({
|
||||
'id': 'fee_get_refund',
|
||||
'refunds': {
|
||||
'object': 'list',
|
||||
'url': '/v1/application_fees/fee_get_refund/refunds',
|
||||
}
|
||||
}, 'api_key')
|
||||
|
||||
fee.refunds.retrieve("ref_get")
|
||||
|
||||
self.requestor_mock.request.assert_called_with(
|
||||
'get',
|
||||
'/v1/application_fees/fee_get_refund/refunds/ref_get',
|
||||
{},
|
||||
None
|
||||
)
|
||||
|
||||
def test_list_refunds(self):
|
||||
fee = libraries.stripe.ApplicationFee.construct_from({
|
||||
'id': 'fee_get_refund',
|
||||
'refunds': {
|
||||
'object': 'list',
|
||||
'url': '/v1/application_fees/fee_get_refund/refunds',
|
||||
}
|
||||
}, 'api_key')
|
||||
|
||||
fee.refunds.list()
|
||||
|
||||
self.requestor_mock.request.assert_called_with(
|
||||
'get',
|
||||
'/v1/application_fees/fee_get_refund/refunds',
|
||||
{},
|
||||
None
|
||||
)
|
||||
|
||||
def test_update_refund(self):
|
||||
def side_effect(*args):
|
||||
raise libraries.stripe.InvalidRequestError('invalid', 'foo')
|
||||
|
||||
self.requestor_mock.request.side_effect = side_effect
|
||||
|
||||
refund = libraries.stripe.resource.ApplicationFeeRefund.construct_from({
|
||||
'id': "ref_update",
|
||||
'fee': "fee_update",
|
||||
'metadata': {},
|
||||
}, 'api_key')
|
||||
|
||||
refund.metadata["key"] = "foo"
|
||||
|
||||
try:
|
||||
refund.save()
|
||||
except libraries.stripe.InvalidRequestError:
|
||||
pass
|
||||
|
||||
self.requestor_mock.request.assert_called_with(
|
||||
'post',
|
||||
'/v1/application_fees/fee_update/refunds/ref_update',
|
||||
{
|
||||
'metadata': {
|
||||
'key': 'foo',
|
||||
}
|
||||
},
|
||||
None
|
||||
)
|
||||
|
||||
self.requestor_mock.request.side_effect = None
|
||||
|
||||
refund.metadata["key"] = "bar"
|
||||
refund.save()
|
||||
|
||||
self.requestor_mock.request.assert_called_with(
|
||||
'post',
|
||||
'/v1/application_fees/fee_update/refunds/ref_update',
|
||||
{
|
||||
'metadata': {
|
||||
'key': 'bar',
|
||||
}
|
||||
},
|
||||
None
|
||||
)
|
||||
|
||||
def test_modify_refund(self):
|
||||
libraries.stripe.resource.ApplicationFeeRefund.modify("fee_update", "ref_update",
|
||||
metadata={'key': 'foo'},
|
||||
api_key='api_key')
|
||||
self.requestor_mock.request.assert_called_with(
|
||||
'post',
|
||||
'/v1/application_fees/fee_update/refunds/ref_update',
|
||||
{
|
||||
'metadata': {
|
||||
'key': 'foo',
|
||||
}
|
||||
},
|
||||
None
|
||||
)
|
||||
+26
@@ -0,0 +1,26 @@
|
||||
import libraries.stripe
|
||||
from libraries.stripe.test.helper import StripeResourceTest
|
||||
|
||||
|
||||
class BalanceTest(StripeResourceTest):
|
||||
|
||||
def test_retrieve_balance(self):
|
||||
libraries.stripe.Balance.retrieve()
|
||||
|
||||
self.requestor_mock.request.assert_called_with(
|
||||
'get',
|
||||
'/v1/balance',
|
||||
{},
|
||||
None
|
||||
)
|
||||
|
||||
|
||||
class BalanceTransactionTest(StripeResourceTest):
|
||||
|
||||
def test_list_balance_transactions(self):
|
||||
libraries.stripe.BalanceTransaction.list()
|
||||
self.requestor_mock.request.assert_called_with(
|
||||
'get',
|
||||
'/v1/balance/history',
|
||||
{}
|
||||
)
|
||||
+111
@@ -0,0 +1,111 @@
|
||||
import libraries.stripe
|
||||
from libraries.stripe.test.helper import StripeResourceTest
|
||||
|
||||
|
||||
class BitcoinReceiverTest(StripeResourceTest):
|
||||
|
||||
def test_retrieve_resource(self):
|
||||
libraries.stripe.BitcoinReceiver.retrieve("btcrcv_test_receiver")
|
||||
self.requestor_mock.request.assert_called_with(
|
||||
'get',
|
||||
'/v1/bitcoin/receivers/btcrcv_test_receiver',
|
||||
{},
|
||||
None
|
||||
)
|
||||
|
||||
def test_list_receivers(self):
|
||||
libraries.stripe.BitcoinReceiver.list()
|
||||
self.requestor_mock.request.assert_called_with(
|
||||
'get',
|
||||
'/v1/bitcoin/receivers',
|
||||
{},
|
||||
)
|
||||
|
||||
def test_create_receiver(self):
|
||||
libraries.stripe.BitcoinReceiver.create(amount=100, description="some details",
|
||||
currency="usd",
|
||||
email="do+fill_now@stripe.com")
|
||||
self.requestor_mock.request.assert_called_with(
|
||||
'post',
|
||||
'/v1/bitcoin/receivers',
|
||||
{
|
||||
'amount': 100,
|
||||
'description': 'some details',
|
||||
'currency': 'usd',
|
||||
'email': 'do+fill_now@stripe.com'
|
||||
},
|
||||
None
|
||||
)
|
||||
|
||||
def test_update_receiver_without_customer(self):
|
||||
params = {'id': 'receiver', 'amount': 100,
|
||||
'description': "some details", 'currency': "usd"}
|
||||
r = libraries.stripe.BitcoinReceiver.construct_from(params, 'api_key')
|
||||
r.description = "some other details"
|
||||
r.save()
|
||||
self.requestor_mock.request.assert_called_with(
|
||||
'post',
|
||||
'/v1/bitcoin/receivers/receiver',
|
||||
{
|
||||
'description': 'some other details',
|
||||
},
|
||||
None
|
||||
)
|
||||
|
||||
def test_update_receiver_with_customer(self):
|
||||
params = {'id': 'receiver', 'amount': 100,
|
||||
'description': "some details", 'currency': "usd",
|
||||
'customer': "cust"}
|
||||
r = libraries.stripe.BitcoinReceiver.construct_from(params, 'api_key')
|
||||
r.description = "some other details"
|
||||
r.save()
|
||||
self.requestor_mock.request.assert_called_with(
|
||||
'post',
|
||||
'/v1/customers/cust/sources/receiver',
|
||||
{
|
||||
'description': 'some other details',
|
||||
},
|
||||
None
|
||||
)
|
||||
|
||||
def test_delete_receiver_without_customer(self):
|
||||
params = {'id': 'receiver', 'amount': 100,
|
||||
'description': "some details", 'currency': "usd"}
|
||||
r = libraries.stripe.BitcoinReceiver.construct_from(params, 'api_key')
|
||||
r.delete()
|
||||
self.requestor_mock.request.assert_called_with(
|
||||
'delete',
|
||||
'/v1/bitcoin/receivers/receiver',
|
||||
{},
|
||||
None
|
||||
)
|
||||
|
||||
def test_delete_receiver_with_customer(self):
|
||||
params = {'id': 'receiver', 'amount': 100,
|
||||
'description': "some details", 'currency': "usd",
|
||||
'customer': "cust"}
|
||||
r = libraries.stripe.BitcoinReceiver.construct_from(params, 'api_key')
|
||||
r.delete()
|
||||
self.requestor_mock.request.assert_called_with(
|
||||
'delete',
|
||||
'/v1/customers/cust/sources/receiver',
|
||||
{},
|
||||
None
|
||||
)
|
||||
|
||||
def test_list_transactions(self):
|
||||
receiver = libraries.stripe.BitcoinReceiver.construct_from({
|
||||
'id': 'btcrcv_foo',
|
||||
'transactions': {
|
||||
'object': 'list',
|
||||
'url': '/v1/bitcoin/receivers/btcrcv_foo/transactions',
|
||||
}
|
||||
}, 'api_key')
|
||||
|
||||
receiver.transactions.list()
|
||||
self.requestor_mock.request.assert_called_with(
|
||||
'get',
|
||||
'/v1/bitcoin/receivers/btcrcv_foo/transactions',
|
||||
{},
|
||||
None
|
||||
)
|
||||
+113
@@ -0,0 +1,113 @@
|
||||
import libraries.stripe
|
||||
from libraries.stripe.test.helper import (
|
||||
StripeResourceTest, NOW, DUMMY_CHARGE
|
||||
)
|
||||
|
||||
|
||||
class ChargeTest(StripeResourceTest):
|
||||
|
||||
def test_charge_list(self):
|
||||
libraries.stripe.Charge.list(created={'lt': NOW})
|
||||
|
||||
self.requestor_mock.request.assert_called_with(
|
||||
'get',
|
||||
'/v1/charges',
|
||||
{
|
||||
'created': {'lt': NOW},
|
||||
}
|
||||
)
|
||||
|
||||
def test_charge_create(self):
|
||||
libraries.stripe.Charge.create(idempotency_key='foo', **DUMMY_CHARGE)
|
||||
|
||||
self.requestor_mock.request.assert_called_with(
|
||||
'post',
|
||||
'/v1/charges',
|
||||
DUMMY_CHARGE,
|
||||
{'Idempotency-Key': 'foo'},
|
||||
)
|
||||
|
||||
def test_charge_retrieve(self):
|
||||
libraries.stripe.Charge.retrieve('ch_test_id')
|
||||
|
||||
self.requestor_mock.request.assert_called_with(
|
||||
'get',
|
||||
'/v1/charges/ch_test_id',
|
||||
{},
|
||||
None
|
||||
)
|
||||
|
||||
def test_charge_modify(self):
|
||||
libraries.stripe.Charge.modify('ch_test_id', refund=True)
|
||||
|
||||
self.requestor_mock.request.assert_called_with(
|
||||
'post',
|
||||
'/v1/charges/ch_test_id',
|
||||
{
|
||||
'refund': True,
|
||||
},
|
||||
None
|
||||
)
|
||||
|
||||
def test_charge_update_dispute(self):
|
||||
charge = libraries.stripe.Charge(id='ch_update_id')
|
||||
charge.update_dispute(idempotency_key='foo')
|
||||
|
||||
self.requestor_mock.request.assert_called_with(
|
||||
'post',
|
||||
'/v1/charges/ch_update_id/dispute',
|
||||
{},
|
||||
{'Idempotency-Key': 'foo'},
|
||||
)
|
||||
|
||||
def test_charge_close_dispute(self):
|
||||
charge = libraries.stripe.Charge(id='ch_update_id')
|
||||
charge.close_dispute(idempotency_key='foo')
|
||||
|
||||
self.requestor_mock.request.assert_called_with(
|
||||
'post',
|
||||
'/v1/charges/ch_update_id/dispute/close',
|
||||
{},
|
||||
{'Idempotency-Key': 'foo'},
|
||||
)
|
||||
|
||||
def test_mark_as_fraudulent(self):
|
||||
charge = libraries.stripe.Charge(id='ch_update_id')
|
||||
charge.mark_as_fraudulent(idempotency_key='foo')
|
||||
|
||||
self.requestor_mock.request.assert_called_with(
|
||||
'post',
|
||||
'/v1/charges/ch_update_id',
|
||||
{
|
||||
'fraud_details': {'user_report': 'fraudulent'}
|
||||
},
|
||||
{'Idempotency-Key': 'foo'},
|
||||
)
|
||||
|
||||
def test_mark_as_safe(self):
|
||||
charge = libraries.stripe.Charge(id='ch_update_id')
|
||||
charge.mark_as_safe(idempotency_key='foo')
|
||||
|
||||
self.requestor_mock.request.assert_called_with(
|
||||
'post',
|
||||
'/v1/charges/ch_update_id',
|
||||
{
|
||||
'fraud_details': {'user_report': 'safe'}
|
||||
},
|
||||
{'Idempotency-Key': 'foo'},
|
||||
)
|
||||
|
||||
def test_create_with_source_param(self):
|
||||
libraries.stripe.Charge.create(amount=100, currency='usd',
|
||||
source='btcrcv_test_receiver')
|
||||
|
||||
self.requestor_mock.request.assert_called_with(
|
||||
'post',
|
||||
'/v1/charges',
|
||||
{
|
||||
'amount': 100,
|
||||
'currency': 'usd',
|
||||
'source': 'btcrcv_test_receiver'
|
||||
},
|
||||
None,
|
||||
)
|
||||
+23
@@ -0,0 +1,23 @@
|
||||
import libraries.stripe
|
||||
from libraries.stripe.test.helper import StripeResourceTest
|
||||
|
||||
|
||||
class CountrySpecTest(StripeResourceTest):
|
||||
|
||||
def test_country_spec_list(self):
|
||||
libraries.stripe.CountrySpec.list()
|
||||
self.requestor_mock.request.assert_called_with(
|
||||
'get',
|
||||
'/v1/country_specs',
|
||||
{}
|
||||
)
|
||||
|
||||
def test_country_spec_retrieve(self):
|
||||
libraries.stripe.CountrySpec.retrieve('US')
|
||||
|
||||
self.requestor_mock.request.assert_called_with(
|
||||
'get',
|
||||
'/v1/country_specs/US',
|
||||
{},
|
||||
None
|
||||
)
|
||||
+55
@@ -0,0 +1,55 @@
|
||||
import libraries.stripe
|
||||
from libraries.stripe.test.helper import (
|
||||
StripeResourceTest, DUMMY_COUPON
|
||||
)
|
||||
|
||||
|
||||
class CouponTest(StripeResourceTest):
|
||||
|
||||
def test_create_coupon(self):
|
||||
libraries.stripe.Coupon.create(**DUMMY_COUPON)
|
||||
self.requestor_mock.request.assert_called_with(
|
||||
'post',
|
||||
'/v1/coupons',
|
||||
DUMMY_COUPON,
|
||||
None
|
||||
)
|
||||
|
||||
def test_update_coupon(self):
|
||||
coup = libraries.stripe.Coupon.construct_from({
|
||||
'id': 'cu_update',
|
||||
'metadata': {},
|
||||
}, 'api_key')
|
||||
coup.metadata["key"] = "value"
|
||||
coup.save()
|
||||
|
||||
self.requestor_mock.request.assert_called_with(
|
||||
'post',
|
||||
"/v1/coupons/cu_update",
|
||||
{
|
||||
'metadata': {
|
||||
'key': 'value',
|
||||
}
|
||||
},
|
||||
None
|
||||
)
|
||||
|
||||
def test_delete_coupon(self):
|
||||
c = libraries.stripe.Coupon(id='cu_delete')
|
||||
c.delete()
|
||||
|
||||
self.requestor_mock.request.assert_called_with(
|
||||
'delete',
|
||||
'/v1/coupons/cu_delete',
|
||||
{},
|
||||
None
|
||||
)
|
||||
|
||||
def test_detach_coupon(self):
|
||||
customer = libraries.stripe.Customer(id="cus_delete_discount")
|
||||
customer.delete_discount()
|
||||
|
||||
self.requestor_mock.request.assert_called_with(
|
||||
'delete',
|
||||
'/v1/customers/cus_delete_discount/discount',
|
||||
)
|
||||
+35
@@ -0,0 +1,35 @@
|
||||
import libraries.stripe
|
||||
from libraries.stripe.test.helper import (
|
||||
StripeApiTestCase, MyCreatable
|
||||
)
|
||||
|
||||
|
||||
class CreateableAPIResourceTests(StripeApiTestCase):
|
||||
|
||||
def test_create(self):
|
||||
self.mock_response({
|
||||
'object': 'charge',
|
||||
'foo': 'bar',
|
||||
})
|
||||
|
||||
res = MyCreatable.create()
|
||||
|
||||
self.requestor_mock.request.assert_called_with(
|
||||
'post', '/v1/mycreatables', {}, None)
|
||||
|
||||
self.assertTrue(isinstance(res, libraries.stripe.Charge))
|
||||
self.assertEqual('bar', res.foo)
|
||||
|
||||
def test_idempotent_create(self):
|
||||
self.mock_response({
|
||||
'object': 'charge',
|
||||
'foo': 'bar',
|
||||
})
|
||||
|
||||
res = MyCreatable.create(idempotency_key='foo')
|
||||
|
||||
self.requestor_mock.request.assert_called_with(
|
||||
'post', '/v1/mycreatables', {}, {'Idempotency-Key': 'foo'})
|
||||
|
||||
self.assertTrue(isinstance(res, libraries.stripe.Charge))
|
||||
self.assertEqual('bar', res.foo)
|
||||
+370
@@ -0,0 +1,370 @@
|
||||
import datetime
|
||||
import time
|
||||
import warnings
|
||||
|
||||
import libraries.stripe
|
||||
from libraries.stripe.test.helper import (
|
||||
StripeResourceTest, DUMMY_CARD, DUMMY_PLAN
|
||||
)
|
||||
|
||||
|
||||
class CustomerTest(StripeResourceTest):
|
||||
|
||||
def test_list_customers(self):
|
||||
libraries.stripe.Customer.list()
|
||||
self.requestor_mock.request.assert_called_with(
|
||||
'get',
|
||||
'/v1/customers',
|
||||
{},
|
||||
)
|
||||
|
||||
def test_create_customer(self):
|
||||
libraries.stripe.Customer.create(description="foo bar", card=DUMMY_CARD,
|
||||
coupon='cu_discount', idempotency_key='foo')
|
||||
self.requestor_mock.request.assert_called_with(
|
||||
'post',
|
||||
'/v1/customers',
|
||||
{
|
||||
'coupon': 'cu_discount',
|
||||
'description': 'foo bar',
|
||||
'card': DUMMY_CARD
|
||||
},
|
||||
{'Idempotency-Key': 'foo'}
|
||||
)
|
||||
|
||||
def test_unset_description(self):
|
||||
customer = libraries.stripe.Customer(id="cus_unset_desc")
|
||||
customer.description = "Hey"
|
||||
customer.save(idempotency_key='foo')
|
||||
|
||||
self.requestor_mock.request.assert_called_with(
|
||||
'post',
|
||||
'/v1/customers/cus_unset_desc',
|
||||
{
|
||||
'description': 'Hey',
|
||||
},
|
||||
{'Idempotency-Key': 'foo'}
|
||||
)
|
||||
|
||||
def test_del_coupon(self):
|
||||
customer = libraries.stripe.Customer(id="cus_unset_desc")
|
||||
customer.description = "bar"
|
||||
customer.coupon = "foo"
|
||||
del customer.coupon
|
||||
customer.save()
|
||||
|
||||
self.requestor_mock.request.assert_called_with(
|
||||
'post',
|
||||
'/v1/customers/cus_unset_desc',
|
||||
{
|
||||
'description': 'bar'
|
||||
},
|
||||
None
|
||||
)
|
||||
|
||||
def test_cannot_set_empty_string(self):
|
||||
customer = libraries.stripe.Customer()
|
||||
self.assertRaises(ValueError, setattr, customer, "description", "")
|
||||
|
||||
def test_customer_add_card(self):
|
||||
customer = libraries.stripe.Customer.construct_from({
|
||||
'id': 'cus_add_card',
|
||||
'sources': {
|
||||
'object': 'list',
|
||||
'url': '/v1/customers/cus_add_card/sources',
|
||||
},
|
||||
}, 'api_key')
|
||||
customer.sources.create(card=DUMMY_CARD, idempotency_key='foo')
|
||||
|
||||
self.requestor_mock.request.assert_called_with(
|
||||
'post',
|
||||
'/v1/customers/cus_add_card/sources',
|
||||
{
|
||||
'card': DUMMY_CARD,
|
||||
},
|
||||
{'Idempotency-Key': 'foo'}
|
||||
)
|
||||
|
||||
def test_customer_add_source(self):
|
||||
customer = libraries.stripe.Customer.construct_from({
|
||||
'id': 'cus_add_source',
|
||||
'sources': {
|
||||
'object': 'list',
|
||||
'url': '/v1/customers/cus_add_source/sources',
|
||||
},
|
||||
}, 'api_key')
|
||||
customer.sources.create(source=DUMMY_CARD, idempotency_key='foo')
|
||||
|
||||
self.requestor_mock.request.assert_called_with(
|
||||
'post',
|
||||
'/v1/customers/cus_add_source/sources',
|
||||
{
|
||||
'source': DUMMY_CARD,
|
||||
},
|
||||
{'Idempotency-Key': 'foo'}
|
||||
)
|
||||
|
||||
def test_customer_update_card(self):
|
||||
card = libraries.stripe.Card.construct_from({
|
||||
'customer': 'cus_update_card',
|
||||
'id': 'ca_update_card',
|
||||
}, 'api_key')
|
||||
card.name = 'The Best'
|
||||
card.save(idempotency_key='foo')
|
||||
|
||||
self.requestor_mock.request.assert_called_with(
|
||||
'post',
|
||||
'/v1/customers/cus_update_card/sources/ca_update_card',
|
||||
{
|
||||
'name': 'The Best',
|
||||
},
|
||||
{'Idempotency-Key': 'foo'}
|
||||
)
|
||||
|
||||
def test_customer_update_source(self):
|
||||
source = libraries.stripe.BitcoinReceiver.construct_from({
|
||||
'customer': 'cus_update_source',
|
||||
'id': 'btcrcv_update_source',
|
||||
}, 'api_key')
|
||||
source.name = 'The Best'
|
||||
source.save(idempotency_key='foo')
|
||||
|
||||
self.requestor_mock.request.assert_called_with(
|
||||
'post',
|
||||
'/v1/customers/cus_update_source/sources/btcrcv_update_source',
|
||||
{
|
||||
'name': 'The Best',
|
||||
},
|
||||
{'Idempotency-Key': 'foo'}
|
||||
)
|
||||
|
||||
def test_customer_update_alipay_account(self):
|
||||
aa = libraries.stripe.AlipayAccount.construct_from({
|
||||
'customer': 'cus_update_alipay',
|
||||
'id': 'ali_update',
|
||||
}, 'api_key')
|
||||
aa.metadata = {'name': 'The Best'}
|
||||
aa.save(idempotency_key='foo')
|
||||
|
||||
self.requestor_mock.request.assert_called_with(
|
||||
'post',
|
||||
'/v1/customers/cus_update_alipay/sources/ali_update',
|
||||
{
|
||||
'metadata': {'name': 'The Best'},
|
||||
},
|
||||
{'Idempotency-Key': 'foo'}
|
||||
)
|
||||
|
||||
def test_customer_delete_card(self):
|
||||
card = libraries.stripe.Card.construct_from({
|
||||
'customer': 'cus_delete_card',
|
||||
'id': 'ca_delete_card',
|
||||
}, 'api_key')
|
||||
card.delete()
|
||||
|
||||
self.requestor_mock.request.assert_called_with(
|
||||
'delete',
|
||||
'/v1/customers/cus_delete_card/sources/ca_delete_card',
|
||||
{},
|
||||
None
|
||||
)
|
||||
|
||||
def test_customer_delete_source(self):
|
||||
source = libraries.stripe.BitcoinReceiver.construct_from({
|
||||
'customer': 'cus_delete_source',
|
||||
'id': 'btcrcv_delete_source',
|
||||
}, 'api_key')
|
||||
source.delete()
|
||||
|
||||
self.requestor_mock.request.assert_called_with(
|
||||
'delete',
|
||||
'/v1/customers/cus_delete_source/sources/btcrcv_delete_source',
|
||||
{},
|
||||
None
|
||||
)
|
||||
|
||||
def test_customer_delete_alipay_account(self):
|
||||
aa = libraries.stripe.AlipayAccount.construct_from({
|
||||
'customer': 'cus_delete_alipay',
|
||||
'id': 'ali_delete',
|
||||
}, 'api_key')
|
||||
aa.delete()
|
||||
|
||||
self.requestor_mock.request.assert_called_with(
|
||||
'delete',
|
||||
'/v1/customers/cus_delete_alipay/sources/ali_delete',
|
||||
{},
|
||||
None
|
||||
)
|
||||
|
||||
def test_customer_delete_bank_account(self):
|
||||
source = libraries.stripe.BankAccount.construct_from({
|
||||
'customer': 'cus_delete_source',
|
||||
'id': 'ba_delete_source',
|
||||
}, 'api_key')
|
||||
source.delete()
|
||||
|
||||
self.requestor_mock.request.assert_called_with(
|
||||
'delete',
|
||||
'/v1/customers/cus_delete_source/sources/ba_delete_source',
|
||||
{},
|
||||
None
|
||||
)
|
||||
|
||||
def test_customer_verify_bank_account(self):
|
||||
source = libraries.stripe.BankAccount.construct_from({
|
||||
'customer': 'cus_verify_source',
|
||||
'id': 'ba_verify_source',
|
||||
}, 'api_key')
|
||||
source.verify()
|
||||
|
||||
self.requestor_mock.request.assert_called_with(
|
||||
'post',
|
||||
'/v1/customers/cus_verify_source/sources/ba_verify_source/verify',
|
||||
{},
|
||||
None
|
||||
)
|
||||
|
||||
|
||||
class CustomerPlanTest(StripeResourceTest):
|
||||
|
||||
def test_create_customer(self):
|
||||
libraries.stripe.Customer.create(plan=DUMMY_PLAN['id'], card=DUMMY_CARD)
|
||||
|
||||
self.requestor_mock.request.assert_called_with(
|
||||
'post',
|
||||
'/v1/customers',
|
||||
{
|
||||
'card': DUMMY_CARD,
|
||||
'plan': DUMMY_PLAN['id'],
|
||||
},
|
||||
None
|
||||
)
|
||||
|
||||
def test_legacy_update_subscription(self):
|
||||
with warnings.catch_warnings(record=True) as w:
|
||||
customer = libraries.stripe.Customer(id="cus_legacy_sub_update")
|
||||
customer.update_subscription(idempotency_key='foo',
|
||||
plan=DUMMY_PLAN['id'])
|
||||
|
||||
self.requestor_mock.request.assert_called_with(
|
||||
'post',
|
||||
'/v1/customers/cus_legacy_sub_update/subscription',
|
||||
{
|
||||
'plan': DUMMY_PLAN['id'],
|
||||
},
|
||||
{'Idempotency-Key': 'foo'}
|
||||
)
|
||||
|
||||
self.assertEqual(len(w), 1)
|
||||
self.assertTrue(issubclass(w[-1].category, DeprecationWarning))
|
||||
|
||||
def test_legacy_delete_subscription(self):
|
||||
with warnings.catch_warnings(record=True) as w:
|
||||
customer = libraries.stripe.Customer(id="cus_legacy_sub_delete")
|
||||
customer.cancel_subscription()
|
||||
|
||||
self.requestor_mock.request.assert_called_with(
|
||||
'delete',
|
||||
'/v1/customers/cus_legacy_sub_delete/subscription',
|
||||
{},
|
||||
None
|
||||
)
|
||||
|
||||
self.assertEqual(len(w), 1)
|
||||
self.assertTrue(issubclass(w[-1].category, DeprecationWarning))
|
||||
|
||||
def test_list_customer_subscriptions(self):
|
||||
customer = libraries.stripe.Customer.construct_from({
|
||||
'id': 'cus_foo',
|
||||
'subscriptions': {
|
||||
'object': 'list',
|
||||
'url': 'v1/customers/cus_foo/subscriptions',
|
||||
}
|
||||
}, 'api_key')
|
||||
|
||||
customer.subscriptions.all()
|
||||
|
||||
self.requestor_mock.request.assert_called_with(
|
||||
'get',
|
||||
'v1/customers/cus_foo/subscriptions',
|
||||
{},
|
||||
None
|
||||
)
|
||||
|
||||
def test_create_customer_subscription(self):
|
||||
customer = libraries.stripe.Customer.construct_from({
|
||||
'id': 'cus_sub_create',
|
||||
'subscriptions': {
|
||||
'object': 'list',
|
||||
'url': '/v1/customers/cus_sub_create/subscriptions',
|
||||
}
|
||||
}, 'api_key')
|
||||
|
||||
customer.subscriptions.create(plan=DUMMY_PLAN['id'], coupon='foo')
|
||||
|
||||
self.requestor_mock.request.assert_called_with(
|
||||
'post',
|
||||
'/v1/customers/cus_sub_create/subscriptions',
|
||||
{
|
||||
'plan': DUMMY_PLAN['id'],
|
||||
'coupon': 'foo',
|
||||
},
|
||||
None
|
||||
)
|
||||
|
||||
def test_retrieve_customer_subscription(self):
|
||||
customer = libraries.stripe.Customer.construct_from({
|
||||
'id': 'cus_foo',
|
||||
'subscriptions': {
|
||||
'object': 'list',
|
||||
'url': '/v1/customers/cus_foo/subscriptions',
|
||||
}
|
||||
}, 'api_key')
|
||||
|
||||
customer.subscriptions.retrieve('sub_cus')
|
||||
|
||||
self.requestor_mock.request.assert_called_with(
|
||||
'get',
|
||||
'/v1/customers/cus_foo/subscriptions/sub_cus',
|
||||
{},
|
||||
None
|
||||
)
|
||||
|
||||
def test_update_customer_subscription(self):
|
||||
subscription = libraries.stripe.Subscription.construct_from({
|
||||
'id': "sub_update",
|
||||
'customer': "cus_foo",
|
||||
}, 'api_key')
|
||||
|
||||
trial_end_dttm = datetime.datetime.now() + datetime.timedelta(days=15)
|
||||
trial_end_int = int(time.mktime(trial_end_dttm.timetuple()))
|
||||
|
||||
subscription.trial_end = trial_end_int
|
||||
subscription.plan = DUMMY_PLAN['id']
|
||||
subscription.save()
|
||||
|
||||
self.requestor_mock.request.assert_called_with(
|
||||
'post',
|
||||
'/v1/subscriptions/sub_update',
|
||||
{
|
||||
'plan': DUMMY_PLAN['id'],
|
||||
'trial_end': trial_end_int,
|
||||
},
|
||||
None
|
||||
)
|
||||
|
||||
def test_delete_customer_subscription(self):
|
||||
subscription = libraries.stripe.Subscription.construct_from({
|
||||
'id': "sub_delete",
|
||||
'customer': "cus_foo",
|
||||
}, 'api_key')
|
||||
|
||||
subscription.delete()
|
||||
|
||||
self.requestor_mock.request.assert_called_with(
|
||||
'delete',
|
||||
'/v1/subscriptions/sub_delete',
|
||||
{},
|
||||
None
|
||||
)
|
||||
+21
@@ -0,0 +1,21 @@
|
||||
from libraries.stripe.test.helper import (
|
||||
StripeApiTestCase, MyDeletable
|
||||
)
|
||||
|
||||
|
||||
class DeletableAPIResourceTests(StripeApiTestCase):
|
||||
|
||||
def test_delete(self):
|
||||
self.mock_response({
|
||||
'id': 'mid',
|
||||
'deleted': True,
|
||||
})
|
||||
|
||||
obj = MyDeletable.construct_from({
|
||||
'id': 'mid'
|
||||
}, 'mykey')
|
||||
|
||||
self.assertTrue(obj is obj.delete())
|
||||
|
||||
self.assertEqual(True, obj.deleted)
|
||||
self.assertEqual('mid', obj.id)
|
||||
+70
@@ -0,0 +1,70 @@
|
||||
import libraries.stripe
|
||||
from libraries.stripe.test.helper import (
|
||||
StripeResourceTest, DUMMY_DISPUTE, NOW
|
||||
)
|
||||
|
||||
|
||||
class DisputeTest(StripeResourceTest):
|
||||
|
||||
def test_list_all_disputes(self):
|
||||
libraries.stripe.Dispute.list(created={'lt': NOW})
|
||||
|
||||
self.requestor_mock.request.assert_called_with(
|
||||
'get',
|
||||
'/v1/disputes',
|
||||
{
|
||||
'created': {'lt': NOW},
|
||||
}
|
||||
)
|
||||
|
||||
def test_create_dispute(self):
|
||||
libraries.stripe.Dispute.create(idempotency_key='foo', **DUMMY_DISPUTE)
|
||||
|
||||
self.requestor_mock.request.assert_called_with(
|
||||
'post',
|
||||
'/v1/disputes',
|
||||
DUMMY_DISPUTE,
|
||||
{'Idempotency-Key': 'foo'},
|
||||
)
|
||||
|
||||
def test_retrieve_dispute(self):
|
||||
libraries.stripe.Dispute.retrieve('dp_test_id')
|
||||
|
||||
self.requestor_mock.request.assert_called_with(
|
||||
'get',
|
||||
'/v1/disputes/dp_test_id',
|
||||
{},
|
||||
None
|
||||
)
|
||||
|
||||
def test_update_dispute(self):
|
||||
dispute = libraries.stripe.Dispute.construct_from({
|
||||
'id': 'dp_update_id',
|
||||
'evidence': {
|
||||
'product_description': 'description',
|
||||
},
|
||||
}, 'api_key')
|
||||
dispute.evidence['customer_name'] = 'customer'
|
||||
dispute.evidence['uncategorized_text'] = 'text'
|
||||
dispute.save()
|
||||
|
||||
self.requestor_mock.request.assert_called_with(
|
||||
'post',
|
||||
'/v1/disputes/dp_update_id',
|
||||
{'evidence': {
|
||||
'customer_name': 'customer',
|
||||
'uncategorized_text': 'text',
|
||||
}},
|
||||
None
|
||||
)
|
||||
|
||||
def test_close_dispute(self):
|
||||
dispute = libraries.stripe.Dispute(id='dp_close_id')
|
||||
dispute.close(idempotency_key='foo')
|
||||
|
||||
self.requestor_mock.request.assert_called_with(
|
||||
'post',
|
||||
'/v1/disputes/dp_close_id/close',
|
||||
{},
|
||||
{'Idempotency-Key': 'foo'},
|
||||
)
|
||||
+40
@@ -0,0 +1,40 @@
|
||||
import tempfile
|
||||
|
||||
import libraries.stripe
|
||||
from libraries.stripe.test.helper import StripeResourceTest
|
||||
|
||||
|
||||
class FileUploadTest(StripeResourceTest):
|
||||
|
||||
def test_create_file_upload(self):
|
||||
test_file = tempfile.TemporaryFile()
|
||||
libraries.stripe.FileUpload.create(
|
||||
purpose='dispute_evidence',
|
||||
file=test_file
|
||||
)
|
||||
self.requestor_mock.request.assert_called_with(
|
||||
'post',
|
||||
'/v1/files',
|
||||
params={
|
||||
'purpose': 'dispute_evidence',
|
||||
'file': test_file
|
||||
},
|
||||
headers={'Content-Type': 'multipart/form-data'}
|
||||
)
|
||||
|
||||
def test_fetch_file_upload(self):
|
||||
libraries.stripe.FileUpload.retrieve("fil_foo")
|
||||
self.requestor_mock.request.assert_called_with(
|
||||
'get',
|
||||
'/v1/files/fil_foo',
|
||||
{},
|
||||
None
|
||||
)
|
||||
|
||||
def test_list_file_uploads(self):
|
||||
libraries.stripe.FileUpload.list()
|
||||
self.requestor_mock.request.assert_called_with(
|
||||
'get',
|
||||
'/v1/files',
|
||||
{}
|
||||
)
|
||||
+76
@@ -0,0 +1,76 @@
|
||||
import libraries.stripe
|
||||
from libraries.stripe.test.helper import (
|
||||
StripeResourceTest, DUMMY_INVOICE_ITEM
|
||||
)
|
||||
|
||||
|
||||
class InvoiceTest(StripeResourceTest):
|
||||
|
||||
def test_add_invoice_item(self):
|
||||
customer = libraries.stripe.Customer(id="cus_invoice_items")
|
||||
customer.add_invoice_item(**DUMMY_INVOICE_ITEM)
|
||||
|
||||
expected = DUMMY_INVOICE_ITEM.copy()
|
||||
expected['customer'] = 'cus_invoice_items'
|
||||
|
||||
self.requestor_mock.request.assert_called_with(
|
||||
'post',
|
||||
'/v1/invoiceitems',
|
||||
expected,
|
||||
None,
|
||||
)
|
||||
|
||||
def test_retrieve_invoice_items(self):
|
||||
customer = libraries.stripe.Customer(id="cus_get_invoice_items")
|
||||
customer.invoice_items()
|
||||
|
||||
self.requestor_mock.request.assert_called_with(
|
||||
'get',
|
||||
'/v1/invoiceitems',
|
||||
{'customer': 'cus_get_invoice_items'},
|
||||
)
|
||||
|
||||
def test_invoice_create(self):
|
||||
customer = libraries.stripe.Customer(id="cus_invoice")
|
||||
libraries.stripe.Invoice.create(customer=customer.id)
|
||||
|
||||
self.requestor_mock.request.assert_called_with(
|
||||
'post',
|
||||
'/v1/invoices',
|
||||
{
|
||||
'customer': 'cus_invoice',
|
||||
},
|
||||
None
|
||||
)
|
||||
|
||||
def test_retrieve_customer_invoices(self):
|
||||
customer = libraries.stripe.Customer(id="cus_invoice_items")
|
||||
customer.invoices()
|
||||
|
||||
self.requestor_mock.request.assert_called_with(
|
||||
'get',
|
||||
'/v1/invoices',
|
||||
{
|
||||
'customer': 'cus_invoice_items',
|
||||
},
|
||||
)
|
||||
|
||||
def test_pay_invoice(self):
|
||||
invoice = libraries.stripe.Invoice(id="ii_pay")
|
||||
invoice.pay()
|
||||
|
||||
self.requestor_mock.request.assert_called_with(
|
||||
'post',
|
||||
'/v1/invoices/ii_pay/pay',
|
||||
{},
|
||||
None
|
||||
)
|
||||
|
||||
def test_upcoming_invoice(self):
|
||||
libraries.stripe.Invoice.upcoming()
|
||||
|
||||
self.requestor_mock.request.assert_called_with(
|
||||
'get',
|
||||
'/v1/invoices/upcoming',
|
||||
{},
|
||||
)
|
||||
+123
@@ -0,0 +1,123 @@
|
||||
import libraries.stripe
|
||||
from libraries.stripe.test.helper import StripeApiTestCase
|
||||
|
||||
|
||||
class ListObjectTests(StripeApiTestCase):
|
||||
|
||||
def setUp(self):
|
||||
super(ListObjectTests, self).setUp()
|
||||
|
||||
self.lo = libraries.stripe.resource.ListObject.construct_from({
|
||||
'id': 'me',
|
||||
'url': '/my/path',
|
||||
'data': ['foo'],
|
||||
}, 'mykey')
|
||||
|
||||
self.mock_response([{
|
||||
'object': 'charge',
|
||||
'foo': 'bar',
|
||||
}])
|
||||
|
||||
def assertResponse(self, res):
|
||||
self.assertTrue(isinstance(res[0], libraries.stripe.Charge))
|
||||
self.assertEqual('bar', res[0].foo)
|
||||
|
||||
def test_for_loop(self):
|
||||
seen = []
|
||||
|
||||
for item in self.lo:
|
||||
seen.append(item)
|
||||
|
||||
self.assertEqual(['foo'], seen)
|
||||
|
||||
def test_list(self):
|
||||
res = self.lo.list(myparam='you')
|
||||
|
||||
self.requestor_mock.request.assert_called_with(
|
||||
'get', '/my/path', {'myparam': 'you'}, None)
|
||||
|
||||
self.assertResponse(res)
|
||||
|
||||
def test_create(self):
|
||||
res = self.lo.create(myparam='eter')
|
||||
|
||||
self.requestor_mock.request.assert_called_with(
|
||||
'post', '/my/path', {'myparam': 'eter'}, None)
|
||||
|
||||
self.assertResponse(res)
|
||||
|
||||
def test_retrieve(self):
|
||||
res = self.lo.retrieve('myid', myparam='cow')
|
||||
|
||||
self.requestor_mock.request.assert_called_with(
|
||||
'get', '/my/path/myid', {'myparam': 'cow'}, None)
|
||||
|
||||
self.assertResponse(res)
|
||||
|
||||
|
||||
class AutoPagingTests(StripeApiTestCase):
|
||||
|
||||
@staticmethod
|
||||
def pageable_model_response(ids, has_more):
|
||||
return {
|
||||
'object': 'list',
|
||||
'url': '/v1/pageablemodels',
|
||||
'data': [{'id': id, 'object': 'pageablemodel'} for id in ids],
|
||||
'has_more': has_more,
|
||||
}
|
||||
|
||||
def test_iter_one_page(self):
|
||||
lo = libraries.stripe.resource.ListObject.construct_from(
|
||||
self.pageable_model_response(['pm_123', 'pm_124'], False),
|
||||
'mykey'
|
||||
)
|
||||
|
||||
self.requestor_mock.request.assert_not_called()
|
||||
|
||||
seen = [item['id'] for item in lo.auto_paging_iter()]
|
||||
|
||||
self.assertEqual(['pm_123', 'pm_124'], seen)
|
||||
|
||||
def test_iter_two_pages(self):
|
||||
lo = libraries.stripe.resource.ListObject.construct_from(
|
||||
self.pageable_model_response(['pm_123', 'pm_124'], True),
|
||||
'mykey'
|
||||
)
|
||||
lo._retrieve_params = {'foo': 'bar'}
|
||||
|
||||
self.mock_response(
|
||||
self.pageable_model_response(['pm_125', 'pm_126'], False)
|
||||
)
|
||||
|
||||
seen = [item['id'] for item in lo.auto_paging_iter()]
|
||||
|
||||
self.requestor_mock.request.assert_called_with(
|
||||
'get',
|
||||
'/v1/pageablemodels',
|
||||
{
|
||||
'starting_after': 'pm_124',
|
||||
'foo': 'bar'
|
||||
},
|
||||
None
|
||||
)
|
||||
|
||||
self.assertEqual(['pm_123', 'pm_124', 'pm_125', 'pm_126'], seen)
|
||||
|
||||
def test_class_method_two_pages(self):
|
||||
self.mock_response({
|
||||
'object': 'list',
|
||||
'data': [{'id': 'ch_001'}],
|
||||
'url': '/v1/charges',
|
||||
'has_more': False,
|
||||
})
|
||||
|
||||
seen = [item['id'] for item in libraries.stripe.Charge.auto_paging_iter(
|
||||
limit=25,
|
||||
foo='bar'
|
||||
)]
|
||||
|
||||
self.requestor_mock.request.assert_called_with(
|
||||
'get', '/v1/charges', {'limit': 25, 'foo': 'bar'}
|
||||
)
|
||||
|
||||
self.assertEqual(['ch_001'], seen)
|
||||
+35
@@ -0,0 +1,35 @@
|
||||
import libraries.stripe
|
||||
from libraries.stripe.test.helper import (
|
||||
StripeApiTestCase, MyListable
|
||||
)
|
||||
|
||||
|
||||
class ListableAPIResourceTests(StripeApiTestCase):
|
||||
|
||||
def test_all(self):
|
||||
self.mock_response({
|
||||
'object': 'list',
|
||||
'data': [
|
||||
{
|
||||
'object': 'charge',
|
||||
'name': 'jose',
|
||||
},
|
||||
{
|
||||
'object': 'charge',
|
||||
'name': 'curly',
|
||||
}
|
||||
],
|
||||
'url': '/v1/charges',
|
||||
'has_more': False,
|
||||
})
|
||||
|
||||
res = MyListable.list()
|
||||
|
||||
self.requestor_mock.request.assert_called_with(
|
||||
'get', '/v1/mylistables', {})
|
||||
|
||||
self.assertEqual(2, len(res.data))
|
||||
self.assertTrue(all(isinstance(obj, libraries.stripe.Charge)
|
||||
for obj in res.data))
|
||||
self.assertEqual('jose', res.data[0].name)
|
||||
self.assertEqual('curly', res.data[1].name)
|
||||
+61
@@ -0,0 +1,61 @@
|
||||
import libraries.stripe
|
||||
from libraries.stripe.test.helper import StripeResourceTest
|
||||
|
||||
|
||||
class MetadataTest(StripeResourceTest):
|
||||
|
||||
def test_noop_metadata(self):
|
||||
charge = libraries.stripe.Charge(id='ch_foo')
|
||||
charge.description = 'test'
|
||||
charge.save()
|
||||
|
||||
self.requestor_mock.request.assert_called_with(
|
||||
'post',
|
||||
'/v1/charges/ch_foo',
|
||||
{
|
||||
'description': 'test',
|
||||
},
|
||||
None
|
||||
)
|
||||
|
||||
def test_unset_metadata(self):
|
||||
charge = libraries.stripe.Charge(id='ch_foo')
|
||||
charge.metadata = {}
|
||||
charge.save()
|
||||
|
||||
self.requestor_mock.request.assert_called_with(
|
||||
'post',
|
||||
'/v1/charges/ch_foo',
|
||||
{
|
||||
'metadata': {},
|
||||
},
|
||||
None
|
||||
)
|
||||
|
||||
def test_whole_update(self):
|
||||
charge = libraries.stripe.Charge(id='ch_foo')
|
||||
charge.metadata = {'whole': 'update'}
|
||||
charge.save()
|
||||
|
||||
self.requestor_mock.request.assert_called_with(
|
||||
'post',
|
||||
'/v1/charges/ch_foo',
|
||||
{
|
||||
'metadata': {'whole': 'update'},
|
||||
},
|
||||
None
|
||||
)
|
||||
|
||||
def test_individual_delete(self):
|
||||
charge = libraries.stripe.Charge(id='ch_foo')
|
||||
charge.metadata = {'whole': None}
|
||||
charge.save()
|
||||
|
||||
self.requestor_mock.request.assert_called_with(
|
||||
'post',
|
||||
'/v1/charges/ch_foo',
|
||||
{
|
||||
'metadata': {'whole': None},
|
||||
},
|
||||
None
|
||||
)
|
||||
+42
@@ -0,0 +1,42 @@
|
||||
import libraries.stripe
|
||||
from libraries.stripe.test.helper import (
|
||||
StripeResourceTest, DUMMY_PLAN
|
||||
)
|
||||
|
||||
|
||||
class PlanTest(StripeResourceTest):
|
||||
|
||||
def test_create_plan(self):
|
||||
libraries.stripe.Plan.create(**DUMMY_PLAN)
|
||||
|
||||
self.requestor_mock.request.assert_called_with(
|
||||
'post',
|
||||
'/v1/plans',
|
||||
DUMMY_PLAN,
|
||||
None
|
||||
)
|
||||
|
||||
def test_delete_plan(self):
|
||||
p = libraries.stripe.Plan(id="pl_delete")
|
||||
p.delete()
|
||||
|
||||
self.requestor_mock.request.assert_called_with(
|
||||
'delete',
|
||||
'/v1/plans/pl_delete',
|
||||
{},
|
||||
None
|
||||
)
|
||||
|
||||
def test_update_plan(self):
|
||||
p = libraries.stripe.Plan(id="pl_update")
|
||||
p.name = "Plan Name"
|
||||
p.save()
|
||||
|
||||
self.requestor_mock.request.assert_called_with(
|
||||
'post',
|
||||
'/v1/plans/pl_update',
|
||||
{
|
||||
'name': 'Plan Name',
|
||||
},
|
||||
None
|
||||
)
|
||||
+75
@@ -0,0 +1,75 @@
|
||||
import libraries.stripe
|
||||
from libraries.stripe.test.helper import (
|
||||
StripeResourceTest, DUMMY_CARD
|
||||
)
|
||||
|
||||
|
||||
class RecipientTest(StripeResourceTest):
|
||||
|
||||
def test_list_recipients(self):
|
||||
libraries.stripe.Recipient.list()
|
||||
self.requestor_mock.request.assert_called_with(
|
||||
'get',
|
||||
'/v1/recipients',
|
||||
{}
|
||||
)
|
||||
|
||||
def test_recipient_transfers(self):
|
||||
recipient = libraries.stripe.Recipient(id='rp_transfer')
|
||||
recipient.transfers()
|
||||
|
||||
self.requestor_mock.request.assert_called_with(
|
||||
'get',
|
||||
'/v1/transfers',
|
||||
{'recipient': 'rp_transfer'},
|
||||
)
|
||||
|
||||
def test_recipient_add_card(self):
|
||||
recipient = libraries.stripe.Recipient.construct_from({
|
||||
'id': 'rp_add_card',
|
||||
'sources': {
|
||||
'object': 'list',
|
||||
'url': '/v1/recipients/rp_add_card/sources',
|
||||
},
|
||||
}, 'api_key')
|
||||
recipient.sources.create(card=DUMMY_CARD)
|
||||
|
||||
self.requestor_mock.request.assert_called_with(
|
||||
'post',
|
||||
'/v1/recipients/rp_add_card/sources',
|
||||
{
|
||||
'card': DUMMY_CARD,
|
||||
},
|
||||
None
|
||||
)
|
||||
|
||||
def test_recipient_update_card(self):
|
||||
card = libraries.stripe.Card.construct_from({
|
||||
'recipient': 'rp_update_card',
|
||||
'id': 'ca_update_card',
|
||||
}, 'api_key')
|
||||
card.name = 'The Best'
|
||||
card.save()
|
||||
|
||||
self.requestor_mock.request.assert_called_with(
|
||||
'post',
|
||||
'/v1/recipients/rp_update_card/cards/ca_update_card',
|
||||
{
|
||||
'name': 'The Best',
|
||||
},
|
||||
None
|
||||
)
|
||||
|
||||
def test_recipient_delete_card(self):
|
||||
card = libraries.stripe.Card.construct_from({
|
||||
'recipient': 'rp_delete_card',
|
||||
'id': 'ca_delete_card',
|
||||
}, 'api_key')
|
||||
card.delete()
|
||||
|
||||
self.requestor_mock.request.assert_called_with(
|
||||
'delete',
|
||||
'/v1/recipients/rp_delete_card/cards/ca_delete_card',
|
||||
{},
|
||||
None
|
||||
)
|
||||
+161
@@ -0,0 +1,161 @@
|
||||
import libraries.stripe
|
||||
from libraries.stripe.test.helper import StripeResourceTest
|
||||
|
||||
|
||||
class RefundTest(StripeResourceTest):
|
||||
|
||||
def test_create_refund(self):
|
||||
libraries.stripe.Refund.create(charge='ch_foo')
|
||||
|
||||
self.requestor_mock.request.assert_called_with(
|
||||
'post',
|
||||
'/v1/refunds',
|
||||
{'charge': 'ch_foo'},
|
||||
None
|
||||
)
|
||||
|
||||
def test_fetch_refund(self):
|
||||
libraries.stripe.Refund.retrieve('re_foo')
|
||||
|
||||
self.requestor_mock.request.assert_called_with(
|
||||
'get',
|
||||
'/v1/refunds/re_foo',
|
||||
{},
|
||||
None
|
||||
)
|
||||
|
||||
def test_list_refunds(self):
|
||||
libraries.stripe.Refund.list(limit=3, charge='ch_foo')
|
||||
|
||||
self.requestor_mock.request.assert_called_with(
|
||||
'get',
|
||||
'/v1/refunds',
|
||||
{'limit': 3, 'charge': 'ch_foo'}
|
||||
)
|
||||
|
||||
def test_update_refund(self):
|
||||
refund = libraries.stripe.resource.Refund.construct_from({
|
||||
'id': "ref_update",
|
||||
'charge': "ch_update",
|
||||
'metadata': {},
|
||||
}, 'api_key')
|
||||
refund.metadata["key"] = "value"
|
||||
refund.save()
|
||||
|
||||
self.requestor_mock.request.assert_called_with(
|
||||
'post',
|
||||
'/v1/refunds/ref_update',
|
||||
{
|
||||
'metadata': {
|
||||
'key': 'value',
|
||||
}
|
||||
},
|
||||
None
|
||||
)
|
||||
|
||||
|
||||
class ChargeRefundTest(StripeResourceTest):
|
||||
|
||||
def test_create_refund(self):
|
||||
charge = libraries.stripe.Charge.construct_from({
|
||||
'id': 'ch_foo',
|
||||
'refunds': {
|
||||
'object': 'list',
|
||||
'url': '/v1/charges/ch_foo/refunds',
|
||||
}
|
||||
}, 'api_key')
|
||||
|
||||
charge.refunds.create()
|
||||
|
||||
self.requestor_mock.request.assert_called_with(
|
||||
'post',
|
||||
'/v1/charges/ch_foo/refunds',
|
||||
{},
|
||||
None
|
||||
)
|
||||
|
||||
def test_non_recursive_save(self):
|
||||
charge = libraries.stripe.Charge.construct_from({
|
||||
'id': 'ch_nested_update',
|
||||
'customer': {
|
||||
'object': 'customer',
|
||||
'description': 'foo',
|
||||
},
|
||||
'refunds': {
|
||||
'object': 'list',
|
||||
'url': '/v1/charges/ch_foo/refunds',
|
||||
'data': [{
|
||||
'id': 'ref_123',
|
||||
}],
|
||||
},
|
||||
}, 'api_key')
|
||||
|
||||
charge.customer.description = 'bar'
|
||||
charge.refunds.has_more = True
|
||||
charge.refunds.data[0].description = 'bar'
|
||||
charge.save()
|
||||
|
||||
# Note: ideally, we'd want the library to NOT issue requests in this
|
||||
# case (i.e. the assert should actually be `assert_not_called()`).
|
||||
self.requestor_mock.request.assert_called_with(
|
||||
'post',
|
||||
'/v1/charges/ch_nested_update',
|
||||
{'refunds': {'has_more': True}},
|
||||
None
|
||||
)
|
||||
|
||||
def test_fetch_refund(self):
|
||||
charge = libraries.stripe.Charge.construct_from({
|
||||
'id': 'ch_get_refund',
|
||||
'refunds': {
|
||||
'object': 'list',
|
||||
'url': '/v1/charges/ch_get_refund/refunds',
|
||||
}
|
||||
}, 'api_key')
|
||||
|
||||
charge.refunds.retrieve("ref_get")
|
||||
|
||||
self.requestor_mock.request.assert_called_with(
|
||||
'get',
|
||||
'/v1/charges/ch_get_refund/refunds/ref_get',
|
||||
{},
|
||||
None
|
||||
)
|
||||
|
||||
def test_list_refunds(self):
|
||||
charge = libraries.stripe.Charge.construct_from({
|
||||
'id': 'ch_get_refund',
|
||||
'refunds': {
|
||||
'object': 'list',
|
||||
'url': '/v1/charges/ch_get_refund/refunds',
|
||||
}
|
||||
}, 'api_key')
|
||||
|
||||
charge.refunds.list()
|
||||
|
||||
self.requestor_mock.request.assert_called_with(
|
||||
'get',
|
||||
'/v1/charges/ch_get_refund/refunds',
|
||||
{},
|
||||
None
|
||||
)
|
||||
|
||||
def test_update_refund(self):
|
||||
refund = libraries.stripe.resource.Refund.construct_from({
|
||||
'id': "ref_update",
|
||||
'charge': "ch_update",
|
||||
'metadata': {},
|
||||
}, 'api_key')
|
||||
refund.metadata["key"] = "value"
|
||||
refund.save()
|
||||
|
||||
self.requestor_mock.request.assert_called_with(
|
||||
'post',
|
||||
'/v1/refunds/ref_update',
|
||||
{
|
||||
'metadata': {
|
||||
'key': 'value',
|
||||
}
|
||||
},
|
||||
None
|
||||
)
|
||||
+90
@@ -0,0 +1,90 @@
|
||||
import libraries.stripe
|
||||
from libraries.stripe.test.helper import StripeResourceTest
|
||||
|
||||
|
||||
class ProductTest(StripeResourceTest):
|
||||
|
||||
def test_list_products(self):
|
||||
libraries.stripe.Product.list()
|
||||
self.requestor_mock.request.assert_called_with(
|
||||
'get',
|
||||
'/v1/products',
|
||||
{}
|
||||
)
|
||||
|
||||
def test_delete_products(self):
|
||||
p = libraries.stripe.Product(id='product_to_delete')
|
||||
p.delete()
|
||||
|
||||
self.requestor_mock.request.assert_called_with(
|
||||
'delete',
|
||||
'/v1/products/product_to_delete',
|
||||
{},
|
||||
None
|
||||
)
|
||||
|
||||
|
||||
class SKUTest(StripeResourceTest):
|
||||
|
||||
def test_list_skus(self):
|
||||
libraries.stripe.SKU.list()
|
||||
self.requestor_mock.request.assert_called_with(
|
||||
'get',
|
||||
'/v1/skus',
|
||||
{}
|
||||
)
|
||||
|
||||
def test_delete_skus(self):
|
||||
sku = libraries.stripe.SKU(id='sku_delete')
|
||||
sku.delete()
|
||||
|
||||
self.requestor_mock.request.assert_called_with(
|
||||
'delete',
|
||||
'/v1/skus/sku_delete',
|
||||
{},
|
||||
None
|
||||
)
|
||||
|
||||
|
||||
class OrderTest(StripeResourceTest):
|
||||
|
||||
def test_list_orders(self):
|
||||
libraries.stripe.Order.list()
|
||||
self.requestor_mock.request.assert_called_with(
|
||||
'get',
|
||||
'/v1/orders',
|
||||
{}
|
||||
)
|
||||
|
||||
def test_pay_order(self):
|
||||
order = libraries.stripe.Order(id="or_pay")
|
||||
order.pay()
|
||||
|
||||
self.requestor_mock.request.assert_called_with(
|
||||
'post',
|
||||
'/v1/orders/or_pay/pay',
|
||||
{},
|
||||
None
|
||||
)
|
||||
|
||||
def test_return_order(self):
|
||||
order = libraries.stripe.Order(id="or_return")
|
||||
order.return_order()
|
||||
|
||||
self.requestor_mock.request.assert_called_with(
|
||||
'post',
|
||||
'/v1/orders/or_return/returns',
|
||||
{},
|
||||
None
|
||||
)
|
||||
|
||||
|
||||
class OrderReturnTest(StripeResourceTest):
|
||||
|
||||
def test_list_order_returns(self):
|
||||
libraries.stripe.OrderReturn.list()
|
||||
self.requestor_mock.request.assert_called_with(
|
||||
'get',
|
||||
'/v1/order_returns',
|
||||
{}
|
||||
)
|
||||
+61
@@ -0,0 +1,61 @@
|
||||
import libraries.stripe
|
||||
from libraries.stripe.test.helper import StripeResourceTest
|
||||
|
||||
|
||||
class ReversalTest(StripeResourceTest):
|
||||
|
||||
def test_fetch_reversal(self):
|
||||
transfer = libraries.stripe.Charge.construct_from({
|
||||
'id': 'tr_get',
|
||||
'reversals': {
|
||||
'object': 'list',
|
||||
'url': '/v1/transfers/tr_get/reversals',
|
||||
}
|
||||
}, 'api_key')
|
||||
|
||||
transfer.reversals.retrieve("foo")
|
||||
|
||||
self.requestor_mock.request.assert_called_with(
|
||||
'get',
|
||||
'/v1/transfers/tr_get/reversals/foo',
|
||||
{},
|
||||
None
|
||||
)
|
||||
|
||||
def test_list_reversals(self):
|
||||
transfer = libraries.stripe.Charge.construct_from({
|
||||
'id': 'tr_list',
|
||||
'reversals': {
|
||||
'object': 'list',
|
||||
'url': '/v1/transfers/tr_list/reversals',
|
||||
}
|
||||
}, 'api_key')
|
||||
|
||||
transfer.reversals.list()
|
||||
|
||||
self.requestor_mock.request.assert_called_with(
|
||||
'get',
|
||||
'/v1/transfers/tr_list/reversals',
|
||||
{},
|
||||
None
|
||||
)
|
||||
|
||||
def test_update_transfer(self):
|
||||
reversal = libraries.stripe.resource.Reversal.construct_from({
|
||||
'id': "rev_update",
|
||||
'transfer': "tr_update",
|
||||
'metadata': {},
|
||||
}, 'api_key')
|
||||
reversal.metadata["key"] = "value"
|
||||
reversal.save()
|
||||
|
||||
self.requestor_mock.request.assert_called_with(
|
||||
'post',
|
||||
'/v1/transfers/tr_update/reversals/rev_update',
|
||||
{
|
||||
'metadata': {
|
||||
'key': 'value',
|
||||
}
|
||||
},
|
||||
None
|
||||
)
|
||||
+164
@@ -0,0 +1,164 @@
|
||||
import pickle
|
||||
import sys
|
||||
|
||||
import libraries.stripe
|
||||
from libraries.stripe import util
|
||||
from libraries.stripe.test.helper import StripeUnitTestCase, SAMPLE_INVOICE
|
||||
|
||||
|
||||
class StripeObjectTests(StripeUnitTestCase):
|
||||
|
||||
def test_initializes_with_parameters(self):
|
||||
obj = libraries.stripe.resource.StripeObject(
|
||||
'foo', 'bar', myparam=5, yourparam='boo')
|
||||
|
||||
self.assertEqual('foo', obj.id)
|
||||
self.assertEqual('bar', obj.api_key)
|
||||
|
||||
def test_access(self):
|
||||
obj = libraries.stripe.resource.StripeObject('myid', 'mykey', myparam=5)
|
||||
|
||||
# Empty
|
||||
self.assertRaises(AttributeError, getattr, obj, 'myattr')
|
||||
self.assertRaises(KeyError, obj.__getitem__, 'myattr')
|
||||
self.assertEqual('def', obj.get('myattr', 'def'))
|
||||
self.assertEqual(None, obj.get('myattr'))
|
||||
|
||||
# Setters
|
||||
obj.myattr = 'myval'
|
||||
obj['myitem'] = 'itval'
|
||||
self.assertEqual('sdef', obj.setdefault('mydef', 'sdef'))
|
||||
|
||||
# Getters
|
||||
self.assertEqual('myval', obj.setdefault('myattr', 'sdef'))
|
||||
self.assertEqual('myval', obj.myattr)
|
||||
self.assertEqual('myval', obj['myattr'])
|
||||
self.assertEqual('myval', obj.get('myattr'))
|
||||
|
||||
self.assertEqual(['id', 'myattr', 'mydef', 'myitem'],
|
||||
sorted(obj.keys()))
|
||||
self.assertEqual(['itval', 'myid', 'myval', 'sdef'],
|
||||
sorted(obj.values()))
|
||||
|
||||
# Illegal operations
|
||||
self.assertRaises(ValueError, setattr, obj, 'foo', '')
|
||||
|
||||
def test_refresh_from(self):
|
||||
obj = libraries.stripe.resource.StripeObject.construct_from({
|
||||
'foo': 'bar',
|
||||
'trans': 'me',
|
||||
}, 'mykey')
|
||||
|
||||
self.assertEqual('mykey', obj.api_key)
|
||||
self.assertEqual('bar', obj.foo)
|
||||
self.assertEqual('me', obj['trans'])
|
||||
self.assertEqual(None, obj.stripe_account)
|
||||
|
||||
obj.refresh_from({
|
||||
'foo': 'baz',
|
||||
'johnny': 5,
|
||||
}, 'key2', stripe_account='acct_foo')
|
||||
|
||||
self.assertEqual(5, obj.johnny)
|
||||
self.assertEqual('baz', obj.foo)
|
||||
self.assertRaises(AttributeError, getattr, obj, 'trans')
|
||||
self.assertEqual('key2', obj.api_key)
|
||||
self.assertEqual('acct_foo', obj.stripe_account)
|
||||
|
||||
obj.refresh_from({
|
||||
'trans': 4,
|
||||
'metadata': {'amount': 42}
|
||||
}, 'key2', True)
|
||||
|
||||
self.assertEqual('baz', obj.foo)
|
||||
self.assertEqual(4, obj.trans)
|
||||
|
||||
def test_passing_nested_refresh(self):
|
||||
obj = libraries.stripe.resource.StripeObject.construct_from({
|
||||
'foos': {
|
||||
'type': 'list',
|
||||
'data': [
|
||||
{'id': 'nested'}
|
||||
],
|
||||
}
|
||||
}, 'key', stripe_account='acct_foo')
|
||||
|
||||
nested = obj.foos.data[0]
|
||||
|
||||
self.assertEqual('key', obj.api_key)
|
||||
self.assertEqual('nested', nested.id)
|
||||
self.assertEqual('key', nested.api_key)
|
||||
self.assertEqual('acct_foo', nested.stripe_account)
|
||||
|
||||
def test_refresh_from_nested_object(self):
|
||||
obj = libraries.stripe.resource.StripeObject.construct_from(
|
||||
SAMPLE_INVOICE, 'key')
|
||||
|
||||
self.assertEqual(1, len(obj.lines.subscriptions))
|
||||
self.assertTrue(
|
||||
isinstance(obj.lines.subscriptions[0],
|
||||
libraries.stripe.resource.StripeObject))
|
||||
self.assertEqual('month', obj.lines.subscriptions[0].plan.interval)
|
||||
|
||||
def test_to_json(self):
|
||||
obj = libraries.stripe.resource.StripeObject.construct_from(
|
||||
SAMPLE_INVOICE, 'key')
|
||||
|
||||
self.check_invoice_data(util.json.loads(str(obj)))
|
||||
|
||||
def check_invoice_data(self, data):
|
||||
# Check rough structure
|
||||
self.assertEqual(20, len(data.keys()))
|
||||
self.assertEqual(3, len(data['lines'].keys()))
|
||||
self.assertEqual(0, len(data['lines']['invoiceitems']))
|
||||
self.assertEqual(1, len(data['lines']['subscriptions']))
|
||||
|
||||
# Check various data types
|
||||
self.assertEqual(1338238728, data['date'])
|
||||
self.assertEqual(None, data['next_payment_attempt'])
|
||||
self.assertEqual(False, data['livemode'])
|
||||
self.assertEqual('month',
|
||||
data['lines']['subscriptions'][0]['plan']['interval'])
|
||||
|
||||
def test_repr(self):
|
||||
obj = libraries.stripe.resource.StripeObject(
|
||||
'foo', 'bar', myparam=5)
|
||||
|
||||
obj['object'] = u'\u4e00boo\u1f00'
|
||||
|
||||
res = repr(obj)
|
||||
|
||||
if sys.version_info[0] < 3:
|
||||
res = unicode(repr(obj), 'utf-8')
|
||||
|
||||
self.assertTrue(u'<StripeObject \u4e00boo\u1f00' in res)
|
||||
self.assertTrue(u'id=foo' in res)
|
||||
|
||||
def test_pickling(self):
|
||||
obj = libraries.stripe.resource.StripeObject(
|
||||
'foo', 'bar', myparam=5)
|
||||
|
||||
obj['object'] = 'boo'
|
||||
obj.refresh_from({'fala': 'lalala'}, api_key='bar', partial=True)
|
||||
|
||||
self.assertEqual('lalala', obj.fala)
|
||||
|
||||
pickled = pickle.dumps(obj)
|
||||
newobj = pickle.loads(pickled)
|
||||
|
||||
self.assertEqual('foo', newobj.id)
|
||||
self.assertEqual('bar', newobj.api_key)
|
||||
self.assertEqual('boo', newobj['object'])
|
||||
self.assertEqual('lalala', newobj.fala)
|
||||
|
||||
def test_deletion(self):
|
||||
obj = libraries.stripe.resource.StripeObject('id', 'key')
|
||||
|
||||
obj.coupon = "foo"
|
||||
self.assertEqual('foo', obj.coupon)
|
||||
|
||||
del obj.coupon
|
||||
self.assertRaises(AttributeError, getattr, obj, 'coupon')
|
||||
|
||||
obj.refresh_from({'coupon': 'foo'}, api_key='bar', partial=True)
|
||||
self.assertEqual('foo', obj.coupon)
|
||||
+116
@@ -0,0 +1,116 @@
|
||||
import datetime
|
||||
import time
|
||||
|
||||
import libraries.stripe
|
||||
from libraries.stripe.test.helper import (
|
||||
StripeResourceTest, DUMMY_PLAN
|
||||
)
|
||||
|
||||
|
||||
class SubscriptionTest(StripeResourceTest):
|
||||
|
||||
def test_list_subscriptions(self):
|
||||
libraries.stripe.Subscription.all(customer="test_cus", plan=DUMMY_PLAN['id'],
|
||||
limit=3)
|
||||
self.requestor_mock.request.assert_called_with(
|
||||
'get',
|
||||
'/v1/subscriptions',
|
||||
{
|
||||
'customer': 'test_cus',
|
||||
'plan': DUMMY_PLAN['id'],
|
||||
'limit': 3,
|
||||
},
|
||||
)
|
||||
|
||||
def test_retrieve_subscription(self):
|
||||
libraries.stripe.Subscription.retrieve('test_sub')
|
||||
|
||||
self.requestor_mock.request.assert_called_with(
|
||||
'get',
|
||||
'/v1/subscriptions/test_sub',
|
||||
{},
|
||||
None
|
||||
)
|
||||
|
||||
def test_create_subscription(self):
|
||||
libraries.stripe.Subscription.create(customer="test_cus", plan=DUMMY_PLAN['id'])
|
||||
|
||||
self.requestor_mock.request.assert_called_with(
|
||||
'post',
|
||||
'/v1/subscriptions',
|
||||
{
|
||||
'customer': 'test_cus',
|
||||
'plan': DUMMY_PLAN['id']
|
||||
},
|
||||
None
|
||||
)
|
||||
|
||||
def test_update_subscription(self):
|
||||
subscription = libraries.stripe.Subscription.construct_from({
|
||||
'id': 'test_sub',
|
||||
'customer': 'test_cus',
|
||||
}, 'api_key')
|
||||
|
||||
trial_end_dttm = datetime.datetime.now() + datetime.timedelta(days=15)
|
||||
trial_end_int = int(time.mktime(trial_end_dttm.timetuple()))
|
||||
|
||||
subscription.plan = DUMMY_PLAN['id']
|
||||
subscription.trial_end = trial_end_int
|
||||
subscription.save()
|
||||
|
||||
self.requestor_mock.request.assert_called_with(
|
||||
'post',
|
||||
'/v1/subscriptions/test_sub',
|
||||
{
|
||||
'plan': DUMMY_PLAN['id'],
|
||||
'trial_end': trial_end_int
|
||||
},
|
||||
None
|
||||
)
|
||||
|
||||
def test_modify_subscription(self):
|
||||
trial_end_dttm = datetime.datetime.now() + datetime.timedelta(days=15)
|
||||
trial_end_int = int(time.mktime(trial_end_dttm.timetuple()))
|
||||
|
||||
libraries.stripe.Subscription.modify('test_sub',
|
||||
plan=DUMMY_PLAN['id'],
|
||||
trial_end=trial_end_int)
|
||||
|
||||
self.requestor_mock.request.assert_called_with(
|
||||
'post',
|
||||
'/v1/subscriptions/test_sub',
|
||||
{
|
||||
'plan': DUMMY_PLAN['id'],
|
||||
'trial_end': trial_end_int
|
||||
},
|
||||
None
|
||||
)
|
||||
|
||||
def test_delete_subscription(self):
|
||||
subscription = libraries.stripe.Subscription.construct_from({
|
||||
'id': 'test_sub',
|
||||
'customer': 'test_cus',
|
||||
}, 'api_key')
|
||||
|
||||
subscription.delete()
|
||||
|
||||
self.requestor_mock.request.assert_called_with(
|
||||
'delete',
|
||||
'/v1/subscriptions/test_sub',
|
||||
{},
|
||||
None
|
||||
)
|
||||
|
||||
def test_delete_subscription_discount(self):
|
||||
subscription = libraries.stripe.Subscription.construct_from({
|
||||
'id': 'test_sub',
|
||||
'customer': 'test_cus',
|
||||
'coupon': 'test_discount'
|
||||
}, 'api_key')
|
||||
|
||||
subscription.delete_discount()
|
||||
|
||||
self.requestor_mock.request.assert_called_with(
|
||||
'delete',
|
||||
'/v1/subscriptions/test_sub/discount'
|
||||
)
|
||||
+25
@@ -0,0 +1,25 @@
|
||||
import libraries.stripe
|
||||
from libraries.stripe.test.helper import StripeResourceTest
|
||||
|
||||
|
||||
class ThreeDSecureTest(StripeResourceTest):
|
||||
|
||||
def test_threedsecure_create(self):
|
||||
libraries.stripe.ThreeDSecure.create(
|
||||
card="tok_test",
|
||||
amount=1500,
|
||||
currency="usd",
|
||||
return_url="https://example.org/3d-secure-result"
|
||||
)
|
||||
|
||||
self.requestor_mock.request.assert_called_with(
|
||||
'post',
|
||||
'/v1/3d_secure',
|
||||
{
|
||||
'card': 'tok_test',
|
||||
'amount': 1500,
|
||||
'currency': 'usd',
|
||||
'return_url': 'https://example.org/3d-secure-result'
|
||||
},
|
||||
None
|
||||
)
|
||||
+24
@@ -0,0 +1,24 @@
|
||||
import libraries.stripe
|
||||
from libraries.stripe.test.helper import StripeResourceTest
|
||||
|
||||
|
||||
class TransferTest(StripeResourceTest):
|
||||
|
||||
def test_list_transfers(self):
|
||||
libraries.stripe.Transfer.list()
|
||||
self.requestor_mock.request.assert_called_with(
|
||||
'get',
|
||||
'/v1/transfers',
|
||||
{}
|
||||
)
|
||||
|
||||
def test_cancel_transfer(self):
|
||||
transfer = libraries.stripe.Transfer(id='tr_cancel')
|
||||
transfer.cancel()
|
||||
|
||||
self.requestor_mock.request.assert_called_with(
|
||||
'post',
|
||||
'/v1/transfers/tr_cancel/cancel',
|
||||
{},
|
||||
None
|
||||
)
|
||||
+366
@@ -0,0 +1,366 @@
|
||||
from libraries.stripe.test.helper import (
|
||||
StripeApiTestCase, MyUpdateable
|
||||
)
|
||||
|
||||
|
||||
class UpdateableAPIResourceTests(StripeApiTestCase):
|
||||
|
||||
def setUp(self):
|
||||
super(UpdateableAPIResourceTests, self).setUp()
|
||||
|
||||
self.mock_response({
|
||||
'thats': 'it'
|
||||
})
|
||||
|
||||
self.obj = MyUpdateable.construct_from({
|
||||
'id': 'myid',
|
||||
'foo': 'bar',
|
||||
'baz': 'boz',
|
||||
'metadata': {
|
||||
'size': 'l',
|
||||
'score': 4,
|
||||
'height': 10
|
||||
}
|
||||
}, 'mykey')
|
||||
|
||||
def checkSave(self):
|
||||
self.assertTrue(self.obj is self.obj.save())
|
||||
|
||||
self.assertEqual('it', self.obj.thats)
|
||||
# TODO: Should we force id to be retained?
|
||||
# self.assertEqual('myid', obj.id)
|
||||
self.assertRaises(AttributeError, getattr, self.obj, 'baz')
|
||||
|
||||
def test_idempotent_save(self):
|
||||
self.obj.baz = 'updated'
|
||||
self.obj.save(idempotency_key='foo')
|
||||
|
||||
self.requestor_mock.request.assert_called_with(
|
||||
'post',
|
||||
'/v1/myupdateables/myid',
|
||||
{
|
||||
'metadata': {},
|
||||
'baz': 'updated',
|
||||
},
|
||||
{
|
||||
'Idempotency-Key': 'foo',
|
||||
},
|
||||
)
|
||||
|
||||
def test_save(self):
|
||||
self.obj.baz = 'updated'
|
||||
self.obj.other = 'newval'
|
||||
self.obj.metadata.size = 'm'
|
||||
self.obj.metadata.info = 'a2'
|
||||
self.obj.metadata.height = None
|
||||
|
||||
self.checkSave()
|
||||
|
||||
self.requestor_mock.request.assert_called_with(
|
||||
'post',
|
||||
'/v1/myupdateables/myid',
|
||||
{
|
||||
'baz': 'updated',
|
||||
'other': 'newval',
|
||||
'metadata': {
|
||||
'size': 'm',
|
||||
'info': 'a2',
|
||||
'height': '',
|
||||
}
|
||||
},
|
||||
None
|
||||
)
|
||||
|
||||
def test_add_key_to_nested_object(self):
|
||||
acct = MyUpdateable.construct_from({
|
||||
'id': 'myid',
|
||||
'legal_entity': {
|
||||
'size': 'l',
|
||||
'score': 4,
|
||||
'height': 10
|
||||
}
|
||||
}, 'mykey')
|
||||
|
||||
acct.legal_entity['first_name'] = 'bob'
|
||||
|
||||
self.assertTrue(acct is acct.save())
|
||||
|
||||
self.requestor_mock.request.assert_called_with(
|
||||
'post',
|
||||
'/v1/myupdateables/myid',
|
||||
{
|
||||
'legal_entity': {
|
||||
'first_name': 'bob',
|
||||
}
|
||||
},
|
||||
None
|
||||
)
|
||||
|
||||
def test_save_nothing(self):
|
||||
acct = MyUpdateable.construct_from({
|
||||
'id': 'myid',
|
||||
'metadata': {
|
||||
'key': 'value',
|
||||
}
|
||||
}, 'mykey')
|
||||
|
||||
self.assertTrue(acct is acct.save())
|
||||
|
||||
# Note: ideally, we'd want the library to NOT issue requests in this
|
||||
# case (i.e. the assert should actually be `assert_not_called()`).
|
||||
self.requestor_mock.request.assert_called_with(
|
||||
'post',
|
||||
'/v1/myupdateables/myid',
|
||||
{'metadata': {}},
|
||||
None
|
||||
)
|
||||
|
||||
def test_replace_nested_object(self):
|
||||
acct = MyUpdateable.construct_from({
|
||||
'id': 'myid',
|
||||
'legal_entity': {
|
||||
'last_name': 'smith',
|
||||
}
|
||||
}, 'mykey')
|
||||
|
||||
acct.legal_entity = {
|
||||
'first_name': 'bob',
|
||||
}
|
||||
|
||||
self.assertTrue(acct is acct.save())
|
||||
|
||||
self.requestor_mock.request.assert_called_with(
|
||||
'post',
|
||||
'/v1/myupdateables/myid',
|
||||
{
|
||||
'legal_entity': {
|
||||
'first_name': 'bob',
|
||||
'last_name': '',
|
||||
}
|
||||
},
|
||||
None
|
||||
)
|
||||
|
||||
def test_array_setting(self):
|
||||
acct = MyUpdateable.construct_from({
|
||||
'id': 'myid',
|
||||
'legal_entity': {}
|
||||
}, 'mykey')
|
||||
|
||||
acct.legal_entity.additional_owners = [{'first_name': 'Bob'}]
|
||||
|
||||
self.assertTrue(acct is acct.save())
|
||||
|
||||
self.requestor_mock.request.assert_called_with(
|
||||
'post',
|
||||
'/v1/myupdateables/myid',
|
||||
{
|
||||
'legal_entity': {
|
||||
'additional_owners': [
|
||||
{'first_name': 'Bob'}
|
||||
]
|
||||
}
|
||||
},
|
||||
None
|
||||
)
|
||||
|
||||
def test_array_none(self):
|
||||
acct = MyUpdateable.construct_from({
|
||||
'id': 'myid',
|
||||
'legal_entity': {
|
||||
'additional_owners': None,
|
||||
}
|
||||
}, 'mykey')
|
||||
|
||||
acct.foo = 'bar'
|
||||
|
||||
self.assertTrue(acct is acct.save())
|
||||
|
||||
self.requestor_mock.request.assert_called_with(
|
||||
'post',
|
||||
'/v1/myupdateables/myid',
|
||||
{
|
||||
'foo': 'bar',
|
||||
'legal_entity': {},
|
||||
},
|
||||
None
|
||||
)
|
||||
|
||||
def test_array_insertion(self):
|
||||
acct = MyUpdateable.construct_from({
|
||||
'id': 'myid',
|
||||
'legal_entity': {
|
||||
'additional_owners': []
|
||||
}
|
||||
}, 'mykey')
|
||||
|
||||
acct.legal_entity.additional_owners.append({'first_name': 'Bob'})
|
||||
|
||||
self.assertTrue(acct is acct.save())
|
||||
|
||||
self.requestor_mock.request.assert_called_with(
|
||||
'post',
|
||||
'/v1/myupdateables/myid',
|
||||
{
|
||||
'legal_entity': {
|
||||
'additional_owners': {
|
||||
'0': {'first_name': 'Bob'},
|
||||
}
|
||||
}
|
||||
},
|
||||
None
|
||||
)
|
||||
|
||||
def test_array_update(self):
|
||||
acct = MyUpdateable.construct_from({
|
||||
'id': 'myid',
|
||||
'legal_entity': {
|
||||
'additional_owners': [
|
||||
{'first_name': 'Bob'},
|
||||
{'first_name': 'Jane'}
|
||||
]
|
||||
}
|
||||
}, 'mykey')
|
||||
|
||||
acct.legal_entity.additional_owners[1].first_name = 'Janet'
|
||||
|
||||
self.assertTrue(acct is acct.save())
|
||||
|
||||
self.requestor_mock.request.assert_called_with(
|
||||
'post',
|
||||
'/v1/myupdateables/myid',
|
||||
{
|
||||
'legal_entity': {
|
||||
'additional_owners': {
|
||||
'0': {},
|
||||
'1': {'first_name': 'Janet'}
|
||||
}
|
||||
}
|
||||
},
|
||||
None
|
||||
)
|
||||
|
||||
def test_array_noop(self):
|
||||
acct = MyUpdateable.construct_from({
|
||||
'id': 'myid',
|
||||
'legal_entity': {
|
||||
'additional_owners': [{'first_name': 'Bob'}]
|
||||
},
|
||||
'currencies_supported': ['usd', 'cad']
|
||||
}, 'mykey')
|
||||
|
||||
self.assertTrue(acct is acct.save())
|
||||
|
||||
self.requestor_mock.request.assert_called_with(
|
||||
'post',
|
||||
'/v1/myupdateables/myid',
|
||||
{
|
||||
'legal_entity': {'additional_owners': {'0': {}}}
|
||||
},
|
||||
None
|
||||
)
|
||||
|
||||
def test_hash_noop(self):
|
||||
acct = MyUpdateable.construct_from({
|
||||
'id': 'myid',
|
||||
'legal_entity': {
|
||||
'address': {'line1': '1 Two Three'}
|
||||
}
|
||||
}, 'mykey')
|
||||
|
||||
self.assertTrue(acct is acct.save())
|
||||
|
||||
self.requestor_mock.request.assert_called_with(
|
||||
'post',
|
||||
'/v1/myupdateables/myid',
|
||||
{'legal_entity': {'address': {}}},
|
||||
None
|
||||
)
|
||||
|
||||
def test_save_replace_metadata_with_number(self):
|
||||
self.obj.baz = 'updated'
|
||||
self.obj.other = 'newval'
|
||||
self.obj.metadata = 3
|
||||
|
||||
self.checkSave()
|
||||
|
||||
self.requestor_mock.request.assert_called_with(
|
||||
'post',
|
||||
'/v1/myupdateables/myid',
|
||||
{
|
||||
'baz': 'updated',
|
||||
'other': 'newval',
|
||||
'metadata': 3,
|
||||
},
|
||||
None
|
||||
)
|
||||
|
||||
def test_save_overwrite_metadata(self):
|
||||
self.obj.metadata = {}
|
||||
self.checkSave()
|
||||
|
||||
self.requestor_mock.request.assert_called_with(
|
||||
'post',
|
||||
'/v1/myupdateables/myid',
|
||||
{
|
||||
'metadata': {
|
||||
'size': '',
|
||||
'score': '',
|
||||
'height': '',
|
||||
}
|
||||
},
|
||||
None
|
||||
)
|
||||
|
||||
def test_save_replace_metadata(self):
|
||||
self.obj.baz = 'updated'
|
||||
self.obj.other = 'newval'
|
||||
self.obj.metadata = {
|
||||
'size': 'm',
|
||||
'info': 'a2',
|
||||
'score': 4,
|
||||
}
|
||||
|
||||
self.checkSave()
|
||||
|
||||
self.requestor_mock.request.assert_called_with(
|
||||
'post',
|
||||
'/v1/myupdateables/myid',
|
||||
{
|
||||
'baz': 'updated',
|
||||
'other': 'newval',
|
||||
'metadata': {
|
||||
'size': 'm',
|
||||
'info': 'a2',
|
||||
'height': '',
|
||||
'score': 4,
|
||||
}
|
||||
},
|
||||
None
|
||||
)
|
||||
|
||||
def test_save_update_metadata(self):
|
||||
self.obj.baz = 'updated'
|
||||
self.obj.other = 'newval'
|
||||
self.obj.metadata.update({
|
||||
'size': 'm',
|
||||
'info': 'a2',
|
||||
'score': 4,
|
||||
})
|
||||
|
||||
self.checkSave()
|
||||
|
||||
self.requestor_mock.request.assert_called_with(
|
||||
'post',
|
||||
'/v1/myupdateables/myid',
|
||||
{
|
||||
'baz': 'updated',
|
||||
'other': 'newval',
|
||||
'metadata': {
|
||||
'size': 'm',
|
||||
'info': 'a2',
|
||||
'score': 4,
|
||||
}
|
||||
},
|
||||
None
|
||||
)
|
||||
Executable
+37
@@ -0,0 +1,37 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
import sys
|
||||
|
||||
import unittest2
|
||||
|
||||
from libraries.stripe import StripeError
|
||||
from libraries.stripe.test.helper import StripeUnitTestCase
|
||||
|
||||
|
||||
class StripeErrorTests(StripeUnitTestCase):
|
||||
|
||||
def test_formatting(self):
|
||||
err = StripeError(u'öre')
|
||||
if sys.version_info > (3, 0):
|
||||
assert str(err) == u'öre'
|
||||
else:
|
||||
assert str(err) == '\xc3\xb6re'
|
||||
assert unicode(err) == u'öre'
|
||||
|
||||
def test_formatting_with_request_id(self):
|
||||
err = StripeError(u'öre', headers={'request-id': '123'})
|
||||
if sys.version_info > (3, 0):
|
||||
assert str(err) == u'Request 123: öre'
|
||||
else:
|
||||
assert str(err) == 'Request 123: \xc3\xb6re'
|
||||
assert unicode(err) == u'Request 123: öre'
|
||||
|
||||
def test_formatting_with_none(self):
|
||||
err = StripeError(None, headers={'request-id': '123'})
|
||||
if sys.version_info > (3, 0):
|
||||
assert str(err) == u'Request 123: <empty message>'
|
||||
else:
|
||||
assert str(err) == 'Request 123: <empty message>'
|
||||
assert unicode(err) == u'Request 123: <empty message>'
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest2.main()
|
||||
Executable
+264
@@ -0,0 +1,264 @@
|
||||
import sys
|
||||
import unittest2
|
||||
|
||||
from mock import Mock, patch
|
||||
|
||||
import libraries.stripe
|
||||
|
||||
from libraries.stripe.test.helper import StripeUnitTestCase
|
||||
|
||||
VALID_API_METHODS = ('get', 'post', 'delete')
|
||||
|
||||
|
||||
class HttpClientTests(StripeUnitTestCase):
|
||||
|
||||
def setUp(self):
|
||||
super(HttpClientTests, self).setUp()
|
||||
|
||||
self.original_filters = libraries.stripe.http_client.warnings.filters[:]
|
||||
libraries.stripe.http_client.warnings.simplefilter('ignore')
|
||||
|
||||
def tearDown(self):
|
||||
libraries.stripe.http_client.warnings.filters = self.original_filters
|
||||
|
||||
super(HttpClientTests, self).tearDown()
|
||||
|
||||
def check_default(self, none_libs, expected):
|
||||
for lib in none_libs:
|
||||
setattr(stripe.http_client, lib, None)
|
||||
|
||||
inst = libraries.stripe.http_client.new_default_http_client()
|
||||
|
||||
self.assertTrue(isinstance(inst, expected))
|
||||
|
||||
def test_new_default_http_client_urlfetch(self):
|
||||
self.check_default((),
|
||||
libraries.stripe.http_client.UrlFetchClient)
|
||||
|
||||
def test_new_default_http_client_requests(self):
|
||||
self.check_default(('urlfetch',),
|
||||
libraries.stripe.http_client.RequestsClient)
|
||||
|
||||
def test_new_default_http_client_pycurl(self):
|
||||
self.check_default(('urlfetch', 'requests',),
|
||||
libraries.stripe.http_client.PycurlClient)
|
||||
|
||||
def test_new_default_http_client_urllib2(self):
|
||||
self.check_default(('urlfetch', 'requests', 'pycurl'),
|
||||
libraries.stripe.http_client.Urllib2Client)
|
||||
|
||||
|
||||
class ClientTestBase():
|
||||
|
||||
@property
|
||||
def request_mock(self):
|
||||
return self.request_mocks[self.request_client.name]
|
||||
|
||||
@property
|
||||
def valid_url(self, path='/foo'):
|
||||
return 'https://api.stripe.com%s' % (path,)
|
||||
|
||||
def make_request(self, method, url, headers, post_data):
|
||||
client = self.request_client(verify_ssl_certs=True)
|
||||
return client.request(method, url, headers, post_data)
|
||||
|
||||
def mock_response(self, body, code):
|
||||
raise NotImplementedError(
|
||||
'You must implement this in your test subclass')
|
||||
|
||||
def mock_error(self, error):
|
||||
raise NotImplementedError(
|
||||
'You must implement this in your test subclass')
|
||||
|
||||
def check_call(self, meth, abs_url, headers, params):
|
||||
raise NotImplementedError(
|
||||
'You must implement this in your test subclass')
|
||||
|
||||
def test_request(self):
|
||||
self.mock_response(self.request_mock, '{"foo": "baz"}', 200)
|
||||
|
||||
for meth in VALID_API_METHODS:
|
||||
abs_url = self.valid_url
|
||||
data = ''
|
||||
|
||||
if meth != 'post':
|
||||
abs_url = '%s?%s' % (abs_url, data)
|
||||
data = None
|
||||
|
||||
headers = {'my-header': 'header val'}
|
||||
|
||||
body, code, _ = self.make_request(
|
||||
meth, abs_url, headers, data)
|
||||
|
||||
self.assertEqual(200, code)
|
||||
self.assertEqual('{"foo": "baz"}', body)
|
||||
|
||||
self.check_call(self.request_mock, meth, abs_url,
|
||||
data, headers)
|
||||
|
||||
def test_exception(self):
|
||||
self.mock_error(self.request_mock)
|
||||
self.assertRaises(stripe.error.APIConnectionError,
|
||||
self.make_request,
|
||||
'get', self.valid_url, {}, None)
|
||||
|
||||
|
||||
class RequestsVerify(object):
|
||||
|
||||
def __eq__(self, other):
|
||||
return other and other.endswith('stripe/data/ca-certificates.crt')
|
||||
|
||||
|
||||
class RequestsClientTests(StripeUnitTestCase, ClientTestBase):
|
||||
request_client = libraries.stripe.http_client.RequestsClient
|
||||
|
||||
def mock_response(self, mock, body, code):
|
||||
result = Mock()
|
||||
result.content = body
|
||||
result.status_code = code
|
||||
|
||||
mock.request = Mock(return_value=result)
|
||||
|
||||
def mock_error(self, mock):
|
||||
mock.exceptions.RequestException = Exception
|
||||
mock.request.side_effect = mock.exceptions.RequestException()
|
||||
|
||||
def check_call(self, mock, meth, url, post_data, headers):
|
||||
mock.request.assert_called_with(meth, url,
|
||||
headers=headers,
|
||||
data=post_data,
|
||||
verify=RequestsVerify(),
|
||||
timeout=80)
|
||||
|
||||
|
||||
class UrlFetchClientTests(StripeUnitTestCase, ClientTestBase):
|
||||
request_client = libraries.stripe.http_client.UrlFetchClient
|
||||
|
||||
def mock_response(self, mock, body, code):
|
||||
result = Mock()
|
||||
result.content = body
|
||||
result.status_code = code
|
||||
|
||||
mock.fetch = Mock(return_value=result)
|
||||
|
||||
def mock_error(self, mock):
|
||||
mock.Error = mock.InvalidURLError = Exception
|
||||
mock.fetch.side_effect = mock.InvalidURLError()
|
||||
|
||||
def check_call(self, mock, meth, url, post_data, headers):
|
||||
mock.fetch.assert_called_with(
|
||||
url=url,
|
||||
method=meth,
|
||||
headers=headers,
|
||||
validate_certificate=True,
|
||||
deadline=55,
|
||||
payload=post_data
|
||||
)
|
||||
|
||||
|
||||
class Urllib2ClientTests(StripeUnitTestCase, ClientTestBase):
|
||||
request_client = libraries.stripe.http_client.Urllib2Client
|
||||
|
||||
def mock_response(self, mock, body, code):
|
||||
response = Mock
|
||||
response.read = Mock(return_value=body)
|
||||
response.code = code
|
||||
response.info = Mock(return_value={})
|
||||
|
||||
self.request_object = Mock()
|
||||
mock.Request = Mock(return_value=self.request_object)
|
||||
|
||||
mock.urlopen = Mock(return_value=response)
|
||||
|
||||
def mock_error(self, mock):
|
||||
mock.urlopen.side_effect = ValueError
|
||||
|
||||
def check_call(self, mock, meth, url, post_data, headers):
|
||||
if sys.version_info >= (3, 0) and isinstance(post_data, basestring):
|
||||
post_data = post_data.encode('utf-8')
|
||||
|
||||
mock.Request.assert_called_with(url, post_data, headers)
|
||||
mock.urlopen.assert_called_with(self.request_object)
|
||||
|
||||
|
||||
class PycurlClientTests(StripeUnitTestCase, ClientTestBase):
|
||||
request_client = libraries.stripe.http_client.PycurlClient
|
||||
|
||||
@property
|
||||
def request_mock(self):
|
||||
if not hasattr(self, 'curl_mock'):
|
||||
lib_mock = self.request_mocks[self.request_client.name]
|
||||
|
||||
self.curl_mock = Mock()
|
||||
|
||||
lib_mock.Curl = Mock(return_value=self.curl_mock)
|
||||
|
||||
return self.curl_mock
|
||||
|
||||
def setUp(self):
|
||||
super(PycurlClientTests, self).setUp()
|
||||
|
||||
self.sio_patcher = patch('stripe.util.StringIO.StringIO')
|
||||
|
||||
sio_mock = Mock()
|
||||
self.sio_patcher.start().return_value = sio_mock
|
||||
self.sio_getvalue = sio_mock.getvalue
|
||||
|
||||
def tearDown(self):
|
||||
super(PycurlClientTests, self).tearDown()
|
||||
|
||||
self.sio_patcher.stop()
|
||||
|
||||
def mock_response(self, mock, body, code):
|
||||
self.sio_getvalue.return_value = body
|
||||
|
||||
mock.getinfo.return_value = code
|
||||
|
||||
def mock_error(self, mock):
|
||||
class FakeException(BaseException):
|
||||
|
||||
def __getitem__(self, i):
|
||||
return 'foo'
|
||||
|
||||
libraries.stripe.http_client.pycurl.error = FakeException
|
||||
mock.perform.side_effect = libraries.stripe.http_client.pycurl.error
|
||||
|
||||
def check_call(self, mock, meth, url, post_data, headers):
|
||||
# TODO: Check the setopt calls
|
||||
pass
|
||||
|
||||
|
||||
class APIEncodeTest(StripeUnitTestCase):
|
||||
|
||||
def test_encode_dict(self):
|
||||
body = {
|
||||
'foo': {
|
||||
'dob': {
|
||||
'month': 1,
|
||||
},
|
||||
'name': 'bat'
|
||||
},
|
||||
}
|
||||
|
||||
values = [t for t in libraries.stripe.api_requestor._api_encode(body)]
|
||||
|
||||
self.assertTrue(('foo[dob][month]', 1) in values)
|
||||
self.assertTrue(('foo[name]', 'bat') in values)
|
||||
|
||||
def test_encode_array(self):
|
||||
body = {
|
||||
'foo': [{
|
||||
'dob': {
|
||||
'month': 1,
|
||||
},
|
||||
'name': 'bat'
|
||||
}],
|
||||
}
|
||||
|
||||
values = [t for t in libraries.stripe.api_requestor._api_encode(body)]
|
||||
|
||||
self.assertTrue(('foo[][dob][month]', 1) in values)
|
||||
self.assertTrue(('foo[][name]', 'bat') in values)
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest2.main()
|
||||
Executable
+176
@@ -0,0 +1,176 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
import os
|
||||
import sys
|
||||
import unittest2
|
||||
import libraries.stripe
|
||||
|
||||
from mock import patch
|
||||
from libraries.stripe.test.helper import (StripeTestCase, NOW, DUMMY_CHARGE, DUMMY_CARD)
|
||||
|
||||
|
||||
class FunctionalTests(StripeTestCase):
|
||||
request_client = libraries.stripe.http_client.Urllib2Client
|
||||
|
||||
def setUp(self):
|
||||
super(FunctionalTests, self).setUp()
|
||||
|
||||
def get_http_client(*args, **kwargs):
|
||||
return self.request_client(*args, **kwargs)
|
||||
|
||||
self.client_patcher = patch(
|
||||
'stripe.http_client.new_default_http_client')
|
||||
|
||||
client_mock = self.client_patcher.start()
|
||||
client_mock.side_effect = get_http_client
|
||||
|
||||
def tearDown(self):
|
||||
super(FunctionalTests, self).tearDown()
|
||||
|
||||
self.client_patcher.stop()
|
||||
|
||||
def test_dns_failure(self):
|
||||
api_base = libraries.stripe.api_base
|
||||
try:
|
||||
libraries.stripe.api_base = 'https://my-invalid-domain.ireallywontresolve/v1'
|
||||
self.assertRaises(stripe.error.APIConnectionError,
|
||||
libraries.stripe.Customer.create)
|
||||
finally:
|
||||
libraries.stripe.api_base = api_base
|
||||
|
||||
def test_run(self):
|
||||
charge = libraries.stripe.Charge.create(**DUMMY_CHARGE)
|
||||
self.assertFalse(charge.refunded)
|
||||
charge.refund()
|
||||
self.assertTrue(charge.refunded)
|
||||
|
||||
def test_refresh(self):
|
||||
charge = libraries.stripe.Charge.create(**DUMMY_CHARGE)
|
||||
charge2 = libraries.stripe.Charge.retrieve(charge.id)
|
||||
self.assertEqual(charge2.created, charge.created)
|
||||
|
||||
charge2.junk = 'junk'
|
||||
charge2.refresh()
|
||||
self.assertRaises(AttributeError, lambda: charge2.junk)
|
||||
|
||||
def test_list_accessors(self):
|
||||
customer = libraries.stripe.Customer.create(card=DUMMY_CARD)
|
||||
self.assertEqual(customer['created'], customer.created)
|
||||
customer['foo'] = 'bar'
|
||||
self.assertEqual(customer.foo, 'bar')
|
||||
|
||||
def test_raise(self):
|
||||
EXPIRED_CARD = DUMMY_CARD.copy()
|
||||
EXPIRED_CARD['exp_month'] = NOW.month - 2
|
||||
EXPIRED_CARD['exp_year'] = NOW.year - 2
|
||||
self.assertRaises(stripe.error.CardError, libraries.stripe.Charge.create,
|
||||
amount=100, currency='usd', card=EXPIRED_CARD)
|
||||
|
||||
def test_response_headers(self):
|
||||
EXPIRED_CARD = DUMMY_CARD.copy()
|
||||
EXPIRED_CARD['exp_month'] = NOW.month - 2
|
||||
EXPIRED_CARD['exp_year'] = NOW.year - 2
|
||||
try:
|
||||
libraries.stripe.Charge.create(amount=100, currency='usd', card=EXPIRED_CARD)
|
||||
self.fail('charge creation with expired card did not fail')
|
||||
except libraries.stripe.error.CardError as e:
|
||||
self.assertTrue(e.request_id.startswith('req_'))
|
||||
|
||||
def test_unicode(self):
|
||||
# Make sure unicode requests can be sent
|
||||
self.assertRaises(stripe.error.InvalidRequestError,
|
||||
libraries.stripe.Charge.retrieve,
|
||||
id=u'☃')
|
||||
|
||||
def test_none_values(self):
|
||||
customer = libraries.stripe.Customer.create(plan=None)
|
||||
self.assertTrue(customer.id)
|
||||
|
||||
def test_missing_id(self):
|
||||
customer = libraries.stripe.Customer()
|
||||
self.assertRaises(stripe.error.InvalidRequestError, customer.refresh)
|
||||
|
||||
|
||||
class RequestsFunctionalTests(FunctionalTests):
|
||||
request_client = libraries.stripe.http_client.RequestsClient
|
||||
|
||||
|
||||
class UrlfetchFunctionalTests(FunctionalTests):
|
||||
request_client = 'urlfetch'
|
||||
|
||||
def setUp(self):
|
||||
if libraries.stripe.http_client.urlfetch is None:
|
||||
self.skipTest(
|
||||
'`urlfetch` from Google App Engine is unavailable.')
|
||||
else:
|
||||
super(UrlfetchFunctionalTests, self).setUp()
|
||||
|
||||
|
||||
class PycurlFunctionalTests(FunctionalTests):
|
||||
|
||||
def setUp(self):
|
||||
if not os.environ.get('STRIPE_TEST_PYCURL'):
|
||||
self.skipTest('Pycurl skipped as STRIPE_TEST_PYCURL is not set')
|
||||
if sys.version_info >= (3, 0):
|
||||
self.skipTest('Pycurl is not supported in Python 3')
|
||||
else:
|
||||
super(PycurlFunctionalTests, self).setUp()
|
||||
|
||||
request_client = libraries.stripe.http_client.PycurlClient
|
||||
|
||||
|
||||
class AuthenticationErrorTest(StripeTestCase):
|
||||
|
||||
def test_invalid_credentials(self):
|
||||
key = libraries.stripe.api_key
|
||||
try:
|
||||
libraries.stripe.api_key = 'invalid'
|
||||
libraries.stripe.Customer.create()
|
||||
except libraries.stripe.error.AuthenticationError as e:
|
||||
self.assertEqual(401, e.http_status)
|
||||
self.assertTrue(isinstance(e.http_body, basestring))
|
||||
self.assertTrue(isinstance(e.json_body, dict))
|
||||
# Note that an invalid API key bypasses many of the standard
|
||||
# facilities in the API server so currently no Request ID is
|
||||
# returned.
|
||||
finally:
|
||||
libraries.stripe.api_key = key
|
||||
|
||||
|
||||
class CardErrorTest(StripeTestCase):
|
||||
|
||||
def test_declined_card_props(self):
|
||||
EXPIRED_CARD = DUMMY_CARD.copy()
|
||||
EXPIRED_CARD['exp_month'] = NOW.month - 2
|
||||
EXPIRED_CARD['exp_year'] = NOW.year - 2
|
||||
try:
|
||||
libraries.stripe.Charge.create(amount=100, currency='usd', card=EXPIRED_CARD)
|
||||
except libraries.stripe.error.CardError as e:
|
||||
self.assertEqual(402, e.http_status)
|
||||
self.assertTrue(isinstance(e.http_body, basestring))
|
||||
self.assertTrue(isinstance(e.json_body, dict))
|
||||
self.assertTrue(e.request_id.startswith('req_'))
|
||||
|
||||
|
||||
class InvalidRequestErrorTest(StripeTestCase):
|
||||
|
||||
def test_nonexistent_object(self):
|
||||
try:
|
||||
libraries.stripe.Charge.retrieve('invalid')
|
||||
except libraries.stripe.error.InvalidRequestError as e:
|
||||
self.assertEqual(404, e.http_status)
|
||||
self.assertTrue(isinstance(e.http_body, basestring))
|
||||
self.assertTrue(isinstance(e.json_body, dict))
|
||||
self.assertTrue(e.request_id.startswith('req_'))
|
||||
|
||||
def test_invalid_data(self):
|
||||
try:
|
||||
libraries.stripe.Charge.create()
|
||||
except libraries.stripe.error.InvalidRequestError as e:
|
||||
self.assertEqual(400, e.http_status)
|
||||
self.assertTrue(isinstance(e.http_body, basestring))
|
||||
self.assertTrue(isinstance(e.json_body, dict))
|
||||
self.assertTrue(e.request_id.startswith('req_'))
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest2.main()
|
||||
+52
@@ -0,0 +1,52 @@
|
||||
# -*- encoding: utf-8 -*-
|
||||
|
||||
import re
|
||||
import sys
|
||||
|
||||
from libraries.stripe.multipart_data_generator import MultipartDataGenerator
|
||||
from libraries.stripe.test.helper import StripeTestCase
|
||||
|
||||
|
||||
class MultipartDataGeneratorTests(StripeTestCase):
|
||||
|
||||
def run_test_multipart_data_with_file(self, test_file):
|
||||
params = {
|
||||
"key1": b"ASCII value",
|
||||
"key2": u"Üñìçôdé value",
|
||||
"key3": test_file
|
||||
}
|
||||
generator = MultipartDataGenerator()
|
||||
generator.add_params(params)
|
||||
http_body = generator.get_post_data()
|
||||
|
||||
if sys.version_info >= (3,):
|
||||
http_body = http_body.decode('utf-8')
|
||||
|
||||
self.assertTrue(re.search(
|
||||
r"Content-Disposition: form-data; name=\"key1\"", http_body))
|
||||
self.assertTrue(re.search(r"ASCII value", http_body))
|
||||
self.assertTrue(re.search(
|
||||
r"Content-Disposition: form-data; name=\"key2\"", http_body))
|
||||
self.assertTrue(re.search(r"Üñìçôdé value", http_body))
|
||||
self.assertTrue(re.search(
|
||||
r"Content-Disposition: form-data; name=\"key3\"; "
|
||||
r"filename=\".+\"",
|
||||
http_body))
|
||||
self.assertTrue(re.search(
|
||||
r"Content-Type: application/octet-stream", http_body))
|
||||
|
||||
test_file.seek(0)
|
||||
file_contents = test_file.read()
|
||||
|
||||
if sys.version_info >= (3,) and isinstance(file_contents, bytes):
|
||||
file_contents = file_contents.decode('utf-8')
|
||||
|
||||
self.assertNotEqual(-1, http_body.find(file_contents))
|
||||
|
||||
def test_multipart_data_file_text(self):
|
||||
with open(__file__, mode='r') as test_file:
|
||||
self.run_test_multipart_data_with_file(test_file)
|
||||
|
||||
def test_multipart_data_file_binary(self):
|
||||
with open(__file__, mode='rb') as test_file:
|
||||
self.run_test_multipart_data_with_file(test_file)
|
||||
Executable
+417
@@ -0,0 +1,417 @@
|
||||
import datetime
|
||||
import unittest2
|
||||
import urlparse
|
||||
|
||||
from mock import Mock, ANY
|
||||
|
||||
import libraries.stripe
|
||||
|
||||
from libraries.stripe.test.helper import StripeUnitTestCase
|
||||
|
||||
VALID_API_METHODS = ('get', 'post', 'delete')
|
||||
|
||||
|
||||
class GMT1(datetime.tzinfo):
|
||||
|
||||
def utcoffset(self, dt):
|
||||
return datetime.timedelta(hours=1)
|
||||
|
||||
def dst(self, dt):
|
||||
return datetime.timedelta(0)
|
||||
|
||||
def tzname(self, dt):
|
||||
return "Europe/Prague"
|
||||
|
||||
|
||||
class APIHeaderMatcher(object):
|
||||
EXP_KEYS = ['X-Stripe-Client-User-Agent', 'User-Agent', 'Authorization']
|
||||
METHOD_EXTRA_KEYS = {"post": ["Content-Type"]}
|
||||
|
||||
def __init__(self, api_key=None, extra={}, request_method=None):
|
||||
self.request_method = request_method
|
||||
self.api_key = api_key or libraries.stripe.api_key
|
||||
self.extra = extra
|
||||
|
||||
def __eq__(self, other):
|
||||
return (self._keys_match(other) and
|
||||
self._auth_match(other) and
|
||||
self._extra_match(other))
|
||||
|
||||
def _keys_match(self, other):
|
||||
expected_keys = self.EXP_KEYS + self.extra.keys()
|
||||
if self.request_method is not None and self.request_method in \
|
||||
self.METHOD_EXTRA_KEYS:
|
||||
expected_keys.extend(self.METHOD_EXTRA_KEYS[self.request_method])
|
||||
|
||||
return (sorted(other.keys()) == sorted(expected_keys))
|
||||
|
||||
def _auth_match(self, other):
|
||||
return other['Authorization'] == "Bearer %s" % (self.api_key,)
|
||||
|
||||
def _extra_match(self, other):
|
||||
for k, v in self.extra.iteritems():
|
||||
if other[k] != v:
|
||||
return False
|
||||
|
||||
return True
|
||||
|
||||
|
||||
class QueryMatcher(object):
|
||||
|
||||
def __init__(self, expected):
|
||||
self.expected = sorted(expected)
|
||||
|
||||
def __eq__(self, other):
|
||||
query = urlparse.urlsplit(other).query or other
|
||||
|
||||
parsed = libraries.stripe.util.parse_qsl(query)
|
||||
return self.expected == sorted(parsed)
|
||||
|
||||
|
||||
class UrlMatcher(object):
|
||||
|
||||
def __init__(self, expected):
|
||||
self.exp_parts = urlparse.urlsplit(expected)
|
||||
|
||||
def __eq__(self, other):
|
||||
other_parts = urlparse.urlsplit(other)
|
||||
|
||||
for part in ('scheme', 'netloc', 'path', 'fragment'):
|
||||
expected = getattr(self.exp_parts, part)
|
||||
actual = getattr(other_parts, part)
|
||||
if expected != actual:
|
||||
print 'Expected %s "%s" but got "%s"' % (
|
||||
part, expected, actual)
|
||||
return False
|
||||
|
||||
q_matcher = QueryMatcher(stripe.util.parse_qsl(self.exp_parts.query))
|
||||
return q_matcher == other
|
||||
|
||||
|
||||
class APIRequestorRequestTests(StripeUnitTestCase):
|
||||
ENCODE_INPUTS = {
|
||||
'dict': {
|
||||
'astring': 'bar',
|
||||
'anint': 5,
|
||||
'anull': None,
|
||||
'adatetime': datetime.datetime(2013, 1, 1, tzinfo=GMT1()),
|
||||
'atuple': (1, 2),
|
||||
'adict': {'foo': 'bar', 'boz': 5},
|
||||
'alist': ['foo', 'bar'],
|
||||
},
|
||||
'list': [1, 'foo', 'baz'],
|
||||
'string': 'boo',
|
||||
'unicode': u'\u1234',
|
||||
'datetime': datetime.datetime(2013, 1, 1, second=1, tzinfo=GMT1()),
|
||||
'none': None,
|
||||
}
|
||||
|
||||
ENCODE_EXPECTATIONS = {
|
||||
'dict': [
|
||||
('%s[astring]', 'bar'),
|
||||
('%s[anint]', 5),
|
||||
('%s[adatetime]', 1356994800),
|
||||
('%s[adict][foo]', 'bar'),
|
||||
('%s[adict][boz]', 5),
|
||||
('%s[alist][]', 'foo'),
|
||||
('%s[alist][]', 'bar'),
|
||||
('%s[atuple][]', 1),
|
||||
('%s[atuple][]', 2),
|
||||
],
|
||||
'list': [
|
||||
('%s[]', 1),
|
||||
('%s[]', 'foo'),
|
||||
('%s[]', 'baz'),
|
||||
],
|
||||
'string': [('%s', 'boo')],
|
||||
'unicode': [('%s', libraries.stripe.util.utf8(u'\u1234'))],
|
||||
'datetime': [('%s', 1356994801)],
|
||||
'none': [],
|
||||
}
|
||||
|
||||
def setUp(self):
|
||||
super(APIRequestorRequestTests, self).setUp()
|
||||
|
||||
self.http_client = Mock(stripe.http_client.HTTPClient)
|
||||
self.http_client._verify_ssl_certs = True
|
||||
self.http_client.name = 'mockclient'
|
||||
|
||||
self.requestor = libraries.stripe.api_requestor.APIRequestor(
|
||||
client=self.http_client)
|
||||
|
||||
def mock_response(self, return_body, return_code, requestor=None,
|
||||
headers=None):
|
||||
if not requestor:
|
||||
requestor = self.requestor
|
||||
|
||||
self.http_client.request = Mock(
|
||||
return_value=(return_body, return_code, headers or {}))
|
||||
|
||||
def check_call(self, meth, abs_url=None, headers=None,
|
||||
post_data=None, requestor=None):
|
||||
if not abs_url:
|
||||
abs_url = 'https://api.stripe.com%s' % (self.valid_path,)
|
||||
if not requestor:
|
||||
requestor = self.requestor
|
||||
if not headers:
|
||||
headers = APIHeaderMatcher(request_method=meth)
|
||||
|
||||
self.http_client.request.assert_called_with(
|
||||
meth, abs_url, headers, post_data)
|
||||
|
||||
@property
|
||||
def valid_path(self):
|
||||
return '/foo'
|
||||
|
||||
def encoder_check(self, key):
|
||||
stk_key = "my%s" % (key,)
|
||||
|
||||
value = self.ENCODE_INPUTS[key]
|
||||
expectation = [(k % (stk_key,), v) for k, v in
|
||||
self.ENCODE_EXPECTATIONS[key]]
|
||||
|
||||
stk = []
|
||||
fn = getattr(stripe.api_requestor.APIRequestor, "encode_%s" % (key,))
|
||||
fn(stk, stk_key, value)
|
||||
|
||||
if isinstance(value, dict):
|
||||
expectation.sort()
|
||||
stk.sort()
|
||||
|
||||
self.assertEqual(expectation, stk)
|
||||
|
||||
def _test_encode_naive_datetime(self):
|
||||
stk = []
|
||||
|
||||
libraries.stripe.api_requestor.APIRequestor.encode_datetime(
|
||||
stk, 'test', datetime.datetime(2013, 1, 1))
|
||||
|
||||
# Naive datetimes will encode differently depending on your system
|
||||
# local time. Since we don't know the local time of your system,
|
||||
# we just check that naive encodings are within 24 hours of correct.
|
||||
self.assertTrue(60 * 60 * 24 > abs(stk[0][1] - 1356994800))
|
||||
|
||||
def test_param_encoding(self):
|
||||
self.mock_response('{}', 200)
|
||||
|
||||
self.requestor.request('get', '', self.ENCODE_INPUTS)
|
||||
|
||||
expectation = []
|
||||
for type_, values in self.ENCODE_EXPECTATIONS.iteritems():
|
||||
expectation.extend([(k % (type_,), str(v)) for k, v in values])
|
||||
|
||||
self.check_call('get', QueryMatcher(expectation))
|
||||
|
||||
def test_dictionary_list_encoding(self):
|
||||
params = {
|
||||
'foo': {
|
||||
'0': {
|
||||
'bar': 'bat',
|
||||
}
|
||||
}
|
||||
}
|
||||
encoded = list(stripe.api_requestor._api_encode(params))
|
||||
key, value = encoded[0]
|
||||
|
||||
self.assertEqual('foo[0][bar]', key)
|
||||
self.assertEqual('bat', value)
|
||||
|
||||
def test_url_construction(self):
|
||||
CASES = (
|
||||
('https://api.stripe.com?foo=bar', '', {'foo': 'bar'}),
|
||||
('https://api.stripe.com?foo=bar', '?', {'foo': 'bar'}),
|
||||
('https://api.stripe.com', '', {}),
|
||||
(
|
||||
'https://api.stripe.com/%20spaced?foo=bar%24&baz=5',
|
||||
'/%20spaced?foo=bar%24',
|
||||
{'baz': '5'}
|
||||
),
|
||||
(
|
||||
'https://api.stripe.com?foo=bar&foo=bar',
|
||||
'?foo=bar',
|
||||
{'foo': 'bar'}
|
||||
),
|
||||
)
|
||||
|
||||
for expected, url, params in CASES:
|
||||
self.mock_response('{}', 200)
|
||||
|
||||
self.requestor.request('get', url, params)
|
||||
|
||||
self.check_call('get', expected)
|
||||
|
||||
def test_empty_methods(self):
|
||||
for meth in VALID_API_METHODS:
|
||||
self.mock_response('{}', 200)
|
||||
|
||||
body, key = self.requestor.request(meth, self.valid_path, {})
|
||||
|
||||
if meth == 'post':
|
||||
post_data = ''
|
||||
else:
|
||||
post_data = None
|
||||
|
||||
self.check_call(meth, post_data=post_data)
|
||||
self.assertEqual({}, body)
|
||||
|
||||
def test_methods_with_params_and_response(self):
|
||||
for meth in VALID_API_METHODS:
|
||||
self.mock_response('{"foo": "bar", "baz": 6}', 200)
|
||||
|
||||
params = {
|
||||
'alist': [1, 2, 3],
|
||||
'adict': {'frobble': 'bits'},
|
||||
'adatetime': datetime.datetime(2013, 1, 1, tzinfo=GMT1())
|
||||
}
|
||||
encoded = ('adict%5Bfrobble%5D=bits&adatetime=1356994800&'
|
||||
'alist%5B%5D=1&alist%5B%5D=2&alist%5B%5D=3')
|
||||
|
||||
body, key = self.requestor.request(meth, self.valid_path,
|
||||
params)
|
||||
self.assertEqual({'foo': 'bar', 'baz': 6}, body)
|
||||
|
||||
if meth == 'post':
|
||||
self.check_call(
|
||||
meth,
|
||||
post_data=QueryMatcher(stripe.util.parse_qsl(encoded)))
|
||||
else:
|
||||
abs_url = "https://api.stripe.com%s?%s" % (
|
||||
self.valid_path, encoded)
|
||||
self.check_call(meth, abs_url=UrlMatcher(abs_url))
|
||||
|
||||
def test_uses_headers(self):
|
||||
self.mock_response('{}', 200)
|
||||
self.requestor.request('get', self.valid_path, {}, {'foo': 'bar'})
|
||||
self.check_call('get', headers=APIHeaderMatcher(extra={'foo': 'bar'}))
|
||||
|
||||
def test_uses_instance_key(self):
|
||||
key = 'fookey'
|
||||
requestor = libraries.stripe.api_requestor.APIRequestor(key,
|
||||
client=self.http_client)
|
||||
|
||||
self.mock_response('{}', 200, requestor=requestor)
|
||||
|
||||
body, used_key = requestor.request('get', self.valid_path, {})
|
||||
|
||||
self.check_call('get', headers=APIHeaderMatcher(
|
||||
key, request_method='get'), requestor=requestor)
|
||||
self.assertEqual(key, used_key)
|
||||
|
||||
def test_passes_api_version(self):
|
||||
libraries.stripe.api_version = 'fooversion'
|
||||
|
||||
self.mock_response('{}', 200)
|
||||
|
||||
body, key = self.requestor.request('get', self.valid_path, {})
|
||||
|
||||
self.check_call('get', headers=APIHeaderMatcher(
|
||||
extra={'Stripe-Version': 'fooversion'}, request_method='get'))
|
||||
|
||||
def test_uses_instance_account(self):
|
||||
account = 'acct_foo'
|
||||
requestor = libraries.stripe.api_requestor.APIRequestor(account=account,
|
||||
client=self.http_client)
|
||||
|
||||
self.mock_response('{}', 200, requestor=requestor)
|
||||
|
||||
requestor.request('get', self.valid_path, {})
|
||||
|
||||
self.check_call(
|
||||
'get',
|
||||
requestor=requestor,
|
||||
headers=APIHeaderMatcher(
|
||||
extra={'Stripe-Account': account},
|
||||
request_method='get'
|
||||
),
|
||||
)
|
||||
|
||||
def test_fails_without_api_key(self):
|
||||
libraries.stripe.api_key = None
|
||||
|
||||
self.assertRaises(stripe.error.AuthenticationError,
|
||||
self.requestor.request,
|
||||
'get', self.valid_path, {})
|
||||
|
||||
def test_not_found(self):
|
||||
self.mock_response('{"error": {}}', 404)
|
||||
|
||||
self.assertRaises(stripe.error.InvalidRequestError,
|
||||
self.requestor.request,
|
||||
'get', self.valid_path, {})
|
||||
|
||||
def test_authentication_error(self):
|
||||
self.mock_response('{"error": {}}', 401)
|
||||
|
||||
self.assertRaises(stripe.error.AuthenticationError,
|
||||
self.requestor.request,
|
||||
'get', self.valid_path, {})
|
||||
|
||||
def test_card_error(self):
|
||||
self.mock_response('{"error": {}}', 402)
|
||||
|
||||
self.assertRaises(stripe.error.CardError,
|
||||
self.requestor.request,
|
||||
'get', self.valid_path, {})
|
||||
|
||||
def test_rate_limit_error(self):
|
||||
self.mock_response('{"error": {}}', 429)
|
||||
|
||||
self.assertRaises(stripe.error.RateLimitError,
|
||||
self.requestor.request,
|
||||
'get', self.valid_path, {})
|
||||
|
||||
def test_old_rate_limit_error(self):
|
||||
"""
|
||||
Tests legacy rate limit error pre-2015-09-18
|
||||
"""
|
||||
self.mock_response('{"error": {"code":"rate_limit"}}', 400)
|
||||
|
||||
self.assertRaises(stripe.error.RateLimitError,
|
||||
self.requestor.request,
|
||||
'get', self.valid_path, {})
|
||||
|
||||
def test_server_error(self):
|
||||
self.mock_response('{"error": {}}', 500)
|
||||
|
||||
self.assertRaises(stripe.error.APIError,
|
||||
self.requestor.request,
|
||||
'get', self.valid_path, {})
|
||||
|
||||
def test_invalid_json(self):
|
||||
self.mock_response('{', 200)
|
||||
|
||||
self.assertRaises(stripe.error.APIError,
|
||||
self.requestor.request,
|
||||
'get', self.valid_path, {})
|
||||
|
||||
def test_invalid_method(self):
|
||||
self.assertRaises(stripe.error.APIConnectionError,
|
||||
self.requestor.request,
|
||||
'foo', 'bar')
|
||||
|
||||
|
||||
class DefaultClientTests(unittest2.TestCase):
|
||||
|
||||
def setUp(self):
|
||||
libraries.stripe.default_http_client = None
|
||||
libraries.stripe.api_key = 'foo'
|
||||
|
||||
def test_default_http_client_called(self):
|
||||
hc = Mock(stripe.http_client.HTTPClient)
|
||||
hc._verify_ssl_certs = True
|
||||
hc.name = 'mockclient'
|
||||
hc.request = Mock(return_value=("{}", 200, {}))
|
||||
|
||||
libraries.stripe.default_http_client = hc
|
||||
libraries.stripe.Charge.list(limit=3)
|
||||
|
||||
hc.request.assert_called_with(
|
||||
'get', 'https://api.stripe.com/v1/charges?limit=3', ANY, None)
|
||||
|
||||
def tearDown(self):
|
||||
libraries.stripe.api_key = None
|
||||
libraries.stripe.default_http_client = None
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest2.main()
|
||||
Reference in New Issue
Block a user