1
1
# -*- coding: utf-8 -*-
2
2
from __future__ import unicode_literals
3
+ import inspect
4
+ import time
3
5
4
6
import unittest
5
7
@@ -18,7 +20,282 @@ def setUpClass(cls):
18
20
cls .merchant = api_key .merchant
19
21
balanced .Marketplace ().save ()
20
22
21
-
22
23
def test_00_merchant_expectations (self ):
23
24
mps = balanced .Marketplace .query .all ()
24
25
self .assertEqual (len (mps ), 1 )
26
+
27
+
28
+ CARD = {
29
+ 'street_address' : '801 High Street' ,
30
+ 'city' : 'Palo Alto' ,
31
+ 'region' : 'CA' ,
32
+ 'postal_code' : '94301' ,
33
+ 'name' : 'Johnny Fresh' ,
34
+ 'card_number' : '4' + '1' * 15 ,
35
+ 'expiration_month' : 12 ,
36
+ 'expiration_year' : 2013 ,
37
+ }
38
+
39
+ CARD_NO_ADDRESS = {
40
+ 'name' : 'Johnny Fresh' ,
41
+ 'card_number' : '4' + '1' * 15 ,
42
+ 'expiration_month' : 12 ,
43
+ 'expiration_year' : 2013 ,
44
+ }
45
+
46
+ BANK_ACCOUNT = {
47
+ 'name' : 'Homer Jay' ,
48
+ 'account_number' : '112233a' ,
49
+ 'bank_code' : '121042882' ,
50
+ }
51
+
52
+ PERSON_MERCHANT = {
53
+ 'type' : 'person' ,
54
+ 'name' : 'William James' ,
55
+ 'tax_id' : '393-48-3992' , # Should work w/ and w/o dashes
56
+ 'street_address' : '167 West 74th Street' ,
57
+ 'postal_code' : '10023' ,
58
+ 'dob' : '1842-01-01' ,
59
+ 'phone_number' : '+16505551234' ,
60
+ 'country_code' : 'USA' ,
61
+ }
62
+
63
+ BUSINESS_PRINCIPAL = {
64
+ 'name' : 'William James' ,
65
+ 'tax_id' : '393483992' ,
66
+ 'street_address' : '167 West 74th Street' ,
67
+ 'postal_code' : '10023' ,
68
+ 'dob' : '1842-01-01' ,
69
+ 'phone_number' : '+16505551234' ,
70
+ 'country_code' : 'USA' ,
71
+ }
72
+
73
+ BUSINESS_MERCHANT = {
74
+ 'type' : 'business' ,
75
+ 'name' : 'Levain Bakery' ,
76
+ 'tax_id' : '253912384' ,
77
+ 'street_address' : '167 West 74th Street' ,
78
+ 'postal_code' : '10023' ,
79
+ 'phone_number' : '+16505551234' ,
80
+ 'country_code' : 'USA' ,
81
+ 'person' : BUSINESS_PRINCIPAL ,
82
+ }
83
+
84
+
85
+ class AICases (AcceptanceUseCases ):
86
+
87
+ email_address_counter = 0
88
+
89
+ def setUp (self ):
90
+ try :
91
+ self .mp = balanced .Marketplace .my_marketplace
92
+ except :
93
+ self .mp = balanced .Marketplace ().save ()
94
+
95
+ def _email_address (self ):
96
+ self .email_address_counter += 1
97
+ return 'suite+{}+{}@example.com' .format (
98
+ time .time (), self .email_address_counter )
99
+
100
+ def _test_transaction_successes (self , cases ):
101
+ for callable , kwargs , validate_cls , validate_kwargs in cases :
102
+ if inspect .isclass (callable ):
103
+ resource = callable (** kwargs ).save ()
104
+ else :
105
+ resource = callable (** kwargs )
106
+ self .assertTrue (isinstance (resource , validate_cls ))
107
+ for k , v in validate_kwargs .iteritems ():
108
+ self .assertEqual (getattr (resource , k ), v )
109
+
110
+ def _test_transaction_failures (self , cases ):
111
+ for callable , kwargs , exc , validate_kwargs in cases :
112
+ with self .assertRaises (exc ) as ex_ctx :
113
+ if inspect .isclass (callable ):
114
+ callable (** kwargs ).save ()
115
+ else :
116
+ callable (** kwargs )
117
+ for k , v in validate_kwargs .iteritems ():
118
+ self .assertEqual (getattr (ex_ctx , k ), v )
119
+
120
+ def test_hold_successes (self ):
121
+ cases = [
122
+ ]
123
+ self ._test_transaction_successes (cases )
124
+
125
+ def test_hold_failures (self ):
126
+ cases = [
127
+ ]
128
+ self ._test_transaction_failures (cases )
129
+
130
+ def test_refund_successes (self ):
131
+ cases = [
132
+ ]
133
+ self ._test_transaction_successes (cases )
134
+
135
+ def test_refund_failures (self ):
136
+ cases = [
137
+ ]
138
+ self ._test_transaction_failures (cases )
139
+
140
+ def test_credit_successes (self ):
141
+ cases = [
142
+ ]
143
+ self ._test_transaction_successes (cases )
144
+
145
+ def test_credit_failures (self ):
146
+ cases = [
147
+ ]
148
+ self ._test_transaction_failures (cases )
149
+
150
+ def test_debits_success (self ):
151
+ cases = [
152
+ ]
153
+ self ._test_transaction_successes (cases )
154
+
155
+ def test_debits_failures (self ):
156
+ cases = [
157
+ ]
158
+ self ._test_transaction_failures (cases )
159
+
160
+ def test_hold_card_uri (self ):
161
+ cases = []
162
+ self ._test_transaction_successes (cases )
163
+
164
+ def test_debit_card_uri (self ):
165
+ cases = []
166
+ self ._test_transaction_successes (cases )
167
+
168
+ def test_upgrade_account_to_merchant_invalid_uri (self ):
169
+ card = self .mp .create_card (** CARD )
170
+ buyer = self .mp .create_buyer ('a@b.com' , card .uri )
171
+ buyer .merchant_uri = '/no/a/merchant'
172
+ with self .assertRaises (balanced .exc .HTTPError ) as ex_ctx :
173
+ buyer .save ()
174
+ ex = ex_ctx .exception
175
+ self .assertEqual (ex .status_code , 400 )
176
+ self .assertIn (
177
+ 'Invalid field "merchant_uri" - v1/no/a/merchant not found' ,
178
+ str (ex ))
179
+
180
+ def test_upgrade_account_to_merchant_success (self ):
181
+ card = self .mp .create_card (** CARD )
182
+ with balanced .key_switcher (None ):
183
+ api_key = balanced .APIKey ().save ()
184
+ merchant = api_key .merchant
185
+ buyer = self .mp .create_buyer (self ._email_address (), card .uri )
186
+ self .assertItemsEqual (buyer .roles , ['buyer' ])
187
+ buyer .merchant_uri = merchant .uri
188
+ buyer .save ()
189
+ self .assertItemsEqual (buyer .roles , ['buyer' , 'merchant' ])
190
+
191
+ def test_debit_uses_newly_added_funding_src (self ):
192
+ bank_account = balanced .BankAccount (** BANK_ACCOUNT ).save ()
193
+ merchant_account = self .mp .create_merchant (
194
+ self ._email_address (),
195
+ merchant = BUSINESS_MERCHANT ,
196
+ bank_account_uri = bank_account .uri ,
197
+ )
198
+
199
+ # debit bank account
200
+ debit = merchant_account .debit (amount = 100 )
201
+ self .assertEqual (debit .source .id , bank_account .id )
202
+
203
+ # debit card
204
+ card = balanced .Card (** CARD ).save ()
205
+ merchant_account .add_card (card .uri )
206
+ debit = merchant_account .debit (amount = 100 )
207
+ self .assertEqual (debit .source .id , card .id )
208
+
209
+ # debit bank account
210
+ card .is_valid = False
211
+ card .save ()
212
+ debit = merchant_account .debit (amount = 100 )
213
+ self .assertEqual (debit .source .id , bank_account .id )
214
+
215
+ def test_maximum_credit_amount (self ):
216
+ bank_account = balanced .BankAccount (** BANK_ACCOUNT ).save ()
217
+ merchant_account = self .mp .create_merchant (
218
+ self ._email_address (),
219
+ merchant = BUSINESS_MERCHANT ,
220
+ bank_account_uri = bank_account .uri ,
221
+ )
222
+ balanced .bust_cache ()
223
+ self .mp = balanced .Marketplace .my_marketplace
224
+ if self .mp .in_escrow :
225
+ merchant_account .credit (self .mp .in_escrow )
226
+ with self .assertRaises (balanced .exc .HTTPError ) as ex_ctx :
227
+ merchant_account .credit (100 )
228
+ ex = ex_ctx .exception
229
+ self .assertIn ('has insufficient funds to cover a transfer of' , str (ex ))
230
+ card = self .mp .create_card (** CARD )
231
+ buyer = self .mp .create_buyer (self ._email_address (), card .uri )
232
+ buyer .debit (200 )
233
+ merchant_account .credit (100 )
234
+
235
+ def test_maximum_debit_amount (self ):
236
+ card = self .mp .create_card (** CARD )
237
+ buyer = self .mp .create_buyer (self ._email_address (), card .uri )
238
+ with self .assertRaises (balanced .exc .HTTPError ) as ex_ctx :
239
+ buyer .debit (10 ** 9 + 1 )
240
+ ex = ex_ctx .exception
241
+ self .assertIn ('must be <= 1000000000' , str (ex ))
242
+
243
+ def test_maximum_refund_amount (self ):
244
+ bank_account = balanced .BankAccount (** BANK_ACCOUNT ).save ()
245
+ merchant = self .mp .create_merchant (
246
+ self ._email_address (),
247
+ merchant = BUSINESS_MERCHANT ,
248
+ bank_account_uri = bank_account .uri ,
249
+ )
250
+ balanced .bust_cache ()
251
+ self .mp = balanced .Marketplace .my_marketplace
252
+ if self .mp .in_escrow :
253
+ merchant .credit (self .mp .in_escrow )
254
+ card = self .mp .create_card (** CARD )
255
+ buyer = self .mp .create_buyer (self ._email_address (), card .uri )
256
+ debit = buyer .debit (200 )
257
+ bank_account = balanced .BankAccount (** BANK_ACCOUNT ).save ()
258
+ merchant .credit (100 )
259
+ with self .assertRaises (balanced .exc .HTTPError ) as ex_ctx :
260
+ debit .refund ()
261
+ ex = ex_ctx .exception
262
+ self .assertIn ('balance insufficient to issue refund' , str (ex ))
263
+ ex = ex_ctx .exception
264
+ buyer .debit (100 )
265
+ debit .refund ()
266
+
267
+ def test_view_credits_once_bank_account_has_been_invalidated (self ):
268
+ bank_account = balanced .BankAccount (** BANK_ACCOUNT ).save ()
269
+ merchant = self .mp .create_merchant (
270
+ self ._email_address (),
271
+ merchant = BUSINESS_MERCHANT ,
272
+ bank_account_uri = bank_account .uri ,
273
+ )
274
+ card = self .mp .create_card (** CARD )
275
+ buyer = self .mp .create_buyer (self ._email_address (), card .uri )
276
+ buyer .debit (100 + 200 + 300 )
277
+ credit1 = merchant .credit (100 )
278
+ credit2 = merchant .credit (200 )
279
+ credit3 = merchant .credit (300 )
280
+ merchant .bank_accounts [0 ].invalid = True
281
+ merchant .bank_accounts [0 ].save ()
282
+ self .assertItemsEqual (
283
+ [credit1 .id , credit2 .id , credit3 .id ],
284
+ [c .id for c in merchant .credits ]
285
+ )
286
+
287
+ def test_create_merchants_with_same_identity_on_same_marketplace (self ):
288
+ with balanced .key_switcher (None ):
289
+ api_key = balanced .APIKey ().save ()
290
+ merchant = api_key .merchant
291
+ merch_account_1 = self .mp .create_merchant (
292
+ self ._email_address (),
293
+ merchant_uri = merchant .uri )
294
+ merch_account_2 = self .mp .create_merchant (
295
+ self ._email_address (),
296
+ merchant_uri = merchant .uri )
297
+ self .assertEqual (merch_account_1 .roles , ['merchant' ])
298
+ self .assertEqual (merch_account_2 .roles , ['merchant' ])
299
+
300
+ def test_tokenize_card_without_address (self ):
301
+ card = balanced .Card (** CARD_NO_ADDRESS ).save ()
0 commit comments