source: main/waeup.ikoba/branches/uli-payments/src/waeup/ikoba/payments/tests/test_paypal.py @ 12305

Last change on this file since 12305 was 12305, checked in by uli, 10 years ago

Put all local changes into repos. Sorry for the mess!

  • Property svn:keywords set to Id
File size: 36.1 KB
Line 
1## $Id: test_paypal.py 12305 2014-12-23 13:06:04Z uli $
2##
3## Copyright (C) 2014 Uli Fouquet & Henrik Bettermann
4## This program is free software; you can redistribute it and/or modify
5## it under the terms of the GNU General Public License as published by
6## the Free Software Foundation; either version 2 of the License, or
7## (at your option) any later version.
8##
9## This program is distributed in the hope that it will be useful,
10## but WITHOUT ANY WARRANTY; without even the implied warranty of
11## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12## GNU General Public License for more details.
13##
14## You should have received a copy of the GNU General Public License
15## along with this program; if not, write to the Free Software
16## Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17##
18import decimal
19import os
20import re
21import shutil
22import tempfile
23import unittest
24import paypalrestsdk
25from zope.component import (
26    getGlobalSiteManager, queryUtility, getUtilitiesFor,
27    )
28from zope.i18nmessageid.message import Message as i18nMessage
29from zope.interface import implements
30from zope.interface.verify import verifyObject, verifyClass
31from zope.schema.interfaces import IVocabularyTokenized, ITerm
32from waeup.ikoba.interfaces import IPayPalConfig
33from waeup.ikoba.payments.interfaces import (
34    IPaymentGatewayService, IPayer, IPayee, IPaymentItem, IPayment,
35    )
36from waeup.ikoba.payments.paypal import (
37    get_paypal_config_file_path, parse_paypal_config, get_access_token,
38    configure_sdk, get_payment, Payer, PayerInfo, ShippingAddress,
39    ADDRESS_TYPES_VOCAB, IShippingAddress, Address, IAddress, to_dict,
40    CreditCard, CREDIT_CARD_TYPES_VOCAB, CREDIT_CARD_STATUS_VOCAB,
41    ICreditCard, ICreditCardToken, CreditCardToken, FundingInstrument,
42    AmountDetails, IAmount, Amount, IItem, Item, STOCK_KEEPING_UNITS_VOCAB,
43    IItemList, ItemList, IPaymentOptions, PaymentOptions, ITransaction,
44    Transaction, PAYMENT_OPTION_METHODS_VOCAB, PayPalCreditCardService,
45    PayPalRegularPaymentService,
46    )
47from waeup.ikoba.testing import (
48    FunctionalLayer, FunctionalTestCase,
49    )
50
51
52#
53# PayPal test config
54#
55
56EXTERNAL_PAYPAL_TESTS = False
57
58#
59# End of PayPal test config
60#
61
62
63def external_paypal_test(func):
64    """A decorator that can block test functions.
65    """
66    if not EXTERNAL_PAYPAL_TESTS:
67        myself = __file__
68        if myself.endswith('.pyc'):
69            myself = myself[:-2]
70        print "WARNING: external paypal tests are skipped!"
71        print "WARNING: edit %s to enable them." % myself
72        return
73    return func
74
75
76class HelperTests(unittest.TestCase):
77
78    def setUp(self):
79        self.workdir = tempfile.mkdtemp()
80
81    def tearDown(self):
82        shutil.rmtree(self.workdir)
83        # unregister any remaining utils registered during tests
84        util = queryUtility(IPayPalConfig)
85        if util is not None:
86            getGlobalSiteManager().unregisterUtility(util, IPayPalConfig)
87
88    def test_get_paypal_config_file_path(self):
89        # we can get a config file path (if registered)
90        path = os.path.join(self.workdir, 'sample.cfg')
91        getGlobalSiteManager().registerUtility(
92            {'path': path, }, IPayPalConfig, '')
93        result = get_paypal_config_file_path()
94        assert result == path
95
96    def test_get_paypal_config_file_path_no_file(self):
97        # without IPayPalConfig util set, we get `None`
98        result = get_paypal_config_file_path()
99        assert result is None
100
101    def test_parse_paypal_config(self):
102        # we can parse paypal configs
103        path = os.path.join(self.workdir, 'sample.cfg')
104        open(path, 'w').write(
105            "[rest-client]\n"
106            "id = myid\n"
107            "secret = mysecret\n"
108            "mode = live\n")
109        result = parse_paypal_config(path)
110        assert result['client_id'] == u'myid'
111        assert result['client_secret'] == u'mysecret'
112        assert result['mode'] == 'live'
113
114    def test_parse_paypal_config_defaults(self):
115        # we have fallback values (defaults) in place
116        path = os.path.join(self.workdir, 'sample.cfg')
117        open(path, 'w').write(
118            "[rest-client]\n"
119            )
120        result = parse_paypal_config(path)
121        assert result['client_id'] is None
122        assert result['client_secret'] is None
123        assert result['mode'] == "sandbox"
124
125    def test_configure_sdk(self):
126        # we can configure the paypal sdk
127        path = os.path.join(self.workdir, 'sample.cfg')
128        open(path, 'w').write(
129            "[rest-client]\n"
130            "id = my-special-id\n"
131            )
132        result = configure_sdk(path)
133        assert result['client_id'] == 'my-special-id'
134        assert result['client_secret'] is None
135        assert result['mode'] == "sandbox"
136        assert paypalrestsdk.api.__api__.mode == 'sandbox'
137        assert paypalrestsdk.api.__api__.client_id == 'my-special-id'
138
139    def test_get_payment_invalid_intent(self):
140        # only 'sale' is currently allowed
141        self.assertRaises(
142            ValueError, get_payment, intent='invalid')
143        self.assertRaises(
144            ValueError, get_payment, intent='order')
145
146    def test_to_dict(self):
147        # we can turn objects into dicts
148        class C1(object):
149            a = 1
150            b = "somestring"
151            c = u"unicodestring"
152            d = None
153        obj = C1()
154        self.assertEqual(
155            to_dict(obj),
156            {'a': u"1",
157             'b': u"somestring",
158             'c': u"unicodestring",
159             }
160            )
161
162    def test_to_dict_map(self):
163        # we can map attribute names
164        class C1(object):
165            a = 1
166            b = "somestring"
167        obj = C1()
168        self.assertEqual(
169            to_dict(obj, name_map={'a': 'replaced_a'}),
170            {'replaced_a': u"1",
171             'b': u"somestring",
172             })
173
174    def test_to_dict_lists(self):
175        # to_dict can handle lists
176        class C1(object):
177            a = 1
178
179            def to_dict(self):
180                return to_dict(self)
181
182        obj1 = C1()
183        obj2 = C1()
184        obj2.a = 2
185        obj3 = C1()
186        obj3.a = 3
187        obj1.foo = [obj2, obj3]
188        self.assertEqual(
189            to_dict(obj1),
190            {
191                'a': u'1',
192                'foo': [
193                    {'a': u'2'},
194                    {'a': u'3'},
195                    ]
196                }
197            )
198
199    def test_to_dict_decimals(self):
200        # decimals are converted to numbers with 2 decimals
201        class C1(object):
202            a = decimal.Decimal("0.1")
203        self.assertEqual(
204            to_dict(C1()),
205            {
206                'a': u"0.10",
207                }
208            )
209
210
211class PayerTests(unittest.TestCase):
212
213    def test_create(self):
214        # we can create payer objects
215        payer = Payer(payment_method='paypal')
216        assert payer.payment_method == 'paypal'
217        assert payer.funding_instruments == []
218        assert payer.payer_info is None
219        assert payer.status is None
220
221    def test_init_invalid_payment_meth(self):
222        # we must provide a valid payment method
223        payer = Payer(payment_method='paypal')
224        assert payer is not None
225        payer = Payer(payment_method='credit_card')
226        assert payer is not None
227        self.assertRaises(
228            ValueError, Payer, payment_method='invalid')
229
230    def test_init_invalid_payer_state(self):
231        # only certain values are allowed as payer states
232        payer = Payer(payment_method='paypal', status='VERIFIED')
233        assert payer is not None
234        payer = Payer(payment_method='paypal', status='UNVERIFIED')
235        assert payer is not None
236        self.assertRaises(
237            ValueError, Payer, payment_method='paypal', status='InVaLiD')
238
239
240class PayerInfoTests(unittest.TestCase):
241
242    def test_create(self):
243        # we can create payer infos
244        info = PayerInfo()
245        assert info.email == ''
246        assert info.first_name == ''
247        assert info.last_name == ''
248        assert info.payer_id == ''
249        assert info.phone == ''
250        assert info.shipping_address is None
251        assert info.tax_id_type == ''
252        assert info.tax_id == ''
253
254    def test_init_invalid_tax_id_type(self):
255        # onyl certain tax id types are allowed
256        info = PayerInfo(tax_id_type='BR_CPF')
257        assert info is not None
258        info = PayerInfo(tax_id_type='BR_CNPJ')
259        assert info is not None
260        self.assertRaises(
261            ValueError, PayerInfo, tax_id_type='INVALID_TYPE')
262
263
264class CreditCardTests(unittest.TestCase):
265
266    def test_iface(self):
267        # we fullfill any interface contracts
268        credit_card = CreditCard(
269            number=u"12345678",
270            credit_card_type="visa",
271            expire_month=4,
272            expire_year=2012,
273            )
274        verifyClass(ICreditCard, CreditCard)
275        verifyObject(ICreditCard, credit_card)
276
277    def test_create(self):
278        # we can create CreditCard objects
279        credit_card = CreditCard(
280            number=u"12345678",
281            credit_card_type="visa",
282            expire_month=4,
283            expire_year=2012,
284            )
285        assert credit_card.paypal_id is None
286        assert credit_card.payer_id is not None
287        assert credit_card.number == u"12345678"
288        assert credit_card.credit_card_type == "visa"
289        assert credit_card.expire_month == 4
290        assert credit_card.expire_year == 2012
291        assert credit_card.cvv2 is None
292        assert credit_card.first_name is None
293        assert credit_card.last_name is None
294        assert credit_card.billing_address is None
295        assert credit_card.state is None
296        assert credit_card.paypal_valid_until is None
297
298    def test_payer_id_given(self):
299        # we do not override given payer ids
300        credit_card = CreditCard(
301            number=u"12345678",
302            credit_card_type="visa",
303            expire_month=4,
304            expire_year=2012,
305            payer_id=u'MySpecialPayerId',
306            )
307        assert credit_card.payer_id == u'MySpecialPayerId'
308
309    def test_payer_id_not_given(self):
310        # in case no payer id is given, we generate one
311        credit_card = CreditCard(
312            number=u"12345678",
313            credit_card_type="visa",
314            expire_month=4,
315            expire_year=2012,
316            )
317        # our payer ids contain a leading 'PAYER_' and 32 hex digits
318        assert re.match('PAYER_[0-9a-f]{32}$', credit_card.payer_id)
319
320    def test_number_is_checked(self):
321        # we do not accept invalid numbers
322        self.assertRaises(
323            ValueError, CreditCard,
324            number=u"not-a-number",
325            credit_card_type="visa",
326            expire_month=4,
327            expire_year=2012,
328            )
329
330    def test_to_str(self):
331        # we can turn CreditCard objects into dicts.
332        addr = Address(
333            line1=u"52 N Main ST",
334            city=u"Johnstown",
335            state=u"OH",
336            postal_code=u"43210",
337            country_code=u"US")
338        credit_card = CreditCard(
339            credit_card_type=u"visa",
340            payer_id=u"PAYER_0123456789012345678901",
341            number=u"4417119669820331",
342            expire_month=11,
343            expire_year=2018,
344            cvv2=u"874",
345            first_name=u"Joe",
346            last_name=u"Shopper",
347            billing_address=addr)
348        self.assertEqual(
349            credit_card.to_dict(),
350            {
351                "type": u"visa",
352                "number": u"4417119669820331",
353                "payer_id": u"PAYER_0123456789012345678901",
354                "expire_month": u"11",
355                "expire_year": u"2018",
356                "cvv2": u"874",
357                "first_name": u"Joe",
358                "last_name": u"Shopper",
359                "billing_address": {
360                    "line1": u"52 N Main ST",
361                    "city": u"Johnstown",
362                    "state": u"OH",
363                    "postal_code": u"43210",
364                    "country_code": u"US"}
365                }
366            )
367
368
369class CreditCardTokenTests(unittest.TestCase):
370
371    def test_iface(self):
372        # we fullfill any interface contracts
373        token = CreditCardToken(
374            credit_card_id=u"12345678",
375            )
376        verifyClass(ICreditCardToken, CreditCardToken)
377        verifyObject(ICreditCardToken, token)
378
379    def test_create(self):
380        # we can create CreditCardToken objects
381        token = CreditCardToken(
382            credit_card_id=u"12345678",
383            )
384        assert token.credit_card_id == u"12345678"
385        assert token.payer_id is None
386        assert token.credit_card_type is None
387        assert token.expire_month is None
388        assert token.expire_year is None
389        assert token.last4 is None
390
391    def test_payer_id_given(self):
392        # we do not override given payer ids
393        token = CreditCardToken(
394            credit_card_id=u"12345678",
395            payer_id=u'MySpecialPayerId',
396            )
397        assert token.payer_id == u'MySpecialPayerId'
398
399    def test_to_str(self):
400        # we can turn CreditCardToken objects into dicts.
401        token = CreditCardToken(
402            credit_card_type=u"visa",
403            payer_id=u"PAYER_0123456789012345678901",
404            credit_card_id=u"12345678",
405            last4="8901",
406            expire_month=11,
407            expire_year=2018,
408            )
409        self.assertEqual(
410            token.to_dict(),
411            {
412                "credit_card_id": u"12345678",
413                "payer_id": u"PAYER_0123456789012345678901",
414                "last4": u"8901",
415                "type": u"visa",
416                "expire_month": u"11",
417                "expire_year": u"2018",
418                }
419            )
420
421
422class FundingInstrumentTests(unittest.TestCase):
423
424    def test_create(self):
425        # we can create FundingInstrument objects
426        token = CreditCardToken(
427            credit_card_id=u"12345678",
428            )
429        instr = FundingInstrument(credit_card_token=token)
430        assert instr.credit_card_token is token
431
432    def test_require_credit_card_or_token(self):
433        # we require a credit card object or a token.
434        credit_card = CreditCard(
435            number=u"12345678",
436            credit_card_type="visa",
437            expire_month=4,
438            expire_year=2012,
439            )
440        token = CreditCardToken(
441            credit_card_id=u"12345678",
442            )
443        self.assertRaises(
444            ValueError, FundingInstrument,
445            credit_card=credit_card,
446            credit_card_token=token
447            )
448        self.assertRaises(
449            ValueError, FundingInstrument
450            )
451
452    def test_to_dict(self):
453        # we can turn Funding instruments into dicts
454        token = CreditCardToken(
455            credit_card_type=u"visa",
456            payer_id=u"PAYER_0123456789012345678901",
457            credit_card_id=u"12345678",
458            last4="8901",
459            expire_month=11,
460            expire_year=2018,
461            )
462        instr = FundingInstrument(credit_card_token=token)
463        result = instr.to_dict()
464        self.assertEqual(
465            result,
466            {
467                "credit_card_token": {
468                    "credit_card_id": u"12345678",
469                    "payer_id": u"PAYER_0123456789012345678901",
470                    "last4": u"8901",
471                    "type": u"visa",
472                    "expire_month": u"11",
473                    "expire_year": u"2018",
474                    }
475                }
476            )
477
478
479class AddressTests(unittest.TestCase):
480
481    def test_iface(self):
482        # we fullfill any interface contracts
483        addr = Address(
484            line1=u'Address Line 1',
485            city=u'Somecity',
486            country_code=u'AT',
487            )
488        verifyClass(IAddress, Address)
489        verifyObject(IAddress, addr)
490
491    def test_create(self):
492        # we can create addresses
493        addr = Address(
494            line1=u'Honey Street 1',
495            city=u'Beartown',
496            country_code=u'GB',
497            )
498        assert addr.line1 == u'Honey Street 1'
499        assert addr.line2 is None
500        assert addr.city == u'Beartown'
501        assert addr.country_code == u'GB'
502        assert addr.postal_code is None
503        assert addr.state is None
504        assert addr.phone is None
505
506    def test_to_dict(self):
507        # we can turn addresses into dicts
508        addr = Address(
509            line1=u'Honey Street 1',
510            city=u'Beartown',
511            country_code=u'GB',
512            )
513        self.assertEqual(
514            addr.to_dict(),
515            {
516                'line1': u'Honey Street 1',
517                'city': u'Beartown',
518                'country_code': u'GB',
519                }
520            )
521        addr.line2 = u"Behind little tree"
522        self.assertEqual(
523            addr.to_dict(),
524            {
525                'line1': u'Honey Street 1',
526                'line2': u'Behind little tree',
527                'city': u'Beartown',
528                'country_code': u'GB',
529                }
530            )
531
532
533class ShippingAddressTests(unittest.TestCase):
534
535    def test_iface(self):
536        # we fullfill any interface contracts
537        addr = ShippingAddress(
538            recipient_name=u'Foo Bar',
539            line1=u'Address Line 1',
540            city=u'Somecity',
541            country_code=u'AT',
542            )
543        verifyClass(IShippingAddress, ShippingAddress)
544        verifyObject(IShippingAddress, addr)
545
546    def test_create(self):
547        # we can create shipping addresses
548        addr = ShippingAddress(
549            recipient_name=u'Rob Receiver',
550            line1=u'Honey Street 1',
551            city=u'Beartown',
552            country_code=u'GB',
553            )
554        assert addr.recipient_name == u'Rob Receiver'
555        assert addr.type == u'residential'
556        assert addr.line1 == u'Honey Street 1'
557        assert addr.line2 is None
558        assert addr.city == u'Beartown'
559        assert addr.country_code == u'GB'
560        assert addr.postal_code is None
561        assert addr.state is None
562        assert addr.phone is None
563
564    def test_to_dict(self):
565        # we can turn shipping addresses into dicts
566        addr = ShippingAddress(
567            recipient_name=u'Rob Receiver',
568            line1=u'Honey Street 1',
569            city=u'Beartown',
570            country_code=u'GB',
571            )
572        self.assertEqual(
573            addr.to_dict(),
574            {
575                'recipient_name': u'Rob Receiver',
576                'type': u'residential',
577                'line1': u'Honey Street 1',
578                'city': u'Beartown',
579                'country_code': u'GB',
580                }
581            )
582        addr.line2 = u"Behind little tree"
583        self.assertEqual(
584            addr.to_dict(),
585            {
586                'recipient_name': u'Rob Receiver',
587                'type': u'residential',
588                'line1': u'Honey Street 1',
589                'line2': u'Behind little tree',
590                'city': u'Beartown',
591                'country_code': u'GB',
592                }
593            )
594
595
596class AmountDetailsTests(unittest.TestCase):
597
598    def test_create(self):
599        # we can create AmountDetail objects
600        details = AmountDetails()
601        assert details.shipping is None
602        assert details.subtotal is None
603        assert details.tax is None
604        assert details.fee is None
605        assert details.handling_fee is None
606        assert details.insurance is None
607        assert details.shipping_discount is None
608
609    def test_to_dict(self):
610        # we can turn AmountDetails into a dict
611        details = AmountDetails(
612            shipping=decimal.Decimal("0.10"),
613            tax=decimal.Decimal("0.30"),
614            fee=decimal.Decimal("0.40"),
615            handling_fee=decimal.Decimal("0.50"),
616            insurance=decimal.Decimal("0.60"),
617            shipping_discount=decimal.Decimal("0.70")
618            )
619        self.assertEqual(
620            details.to_dict(),
621            {
622                'shipping': u"0.10",
623                'subtotal': u"1.20",
624                'tax': u"0.30",
625                'fee': u"0.40",
626                'handling_fee': u"0.50",
627                'insurance': u"0.60",
628                'shipping_discount': u"0.70"
629                }
630            )
631
632    def test_subtotal_all_none(self):
633        # if all items are none, also subtotal is none
634        details = AmountDetails(
635            shipping=None, tax=None, fee=None, handling_fee=None,
636            insurance=None, shipping_discount=None,
637            )
638        assert details.subtotal is None
639        details.shipping_discount = decimal.Decimal("1.00")
640        assert details.subtotal == decimal.Decimal("-1.00")
641
642    def test_subtotal_sum(self):
643        # subtotal sums up correctly
644        details = AmountDetails(
645            shipping=decimal.Decimal("0.05"),
646            tax=decimal.Decimal("0.40"),
647            fee=decimal.Decimal("3.00"),
648            handling_fee=decimal.Decimal("20.00"),
649            insurance=decimal.Decimal("100.00"),
650            shipping_discount=None
651            )
652        self.assertEqual(details.subtotal, decimal.Decimal("123.45"))
653        details.shipping_discount = decimal.Decimal("0.00")
654        self.assertEqual(details.subtotal, decimal.Decimal("123.45"))
655        details.shipping_discount = decimal.Decimal("23.45")
656        self.assertEqual(details.subtotal, decimal.Decimal("100.00"))
657
658
659class AmountTests(unittest.TestCase):
660
661    def test_iface(self):
662        # we fullfill any interface contracts.
663        amount = Amount()
664        verifyClass(IAmount, Amount)
665        verifyObject(IAmount, amount)
666
667    def test_create(self):
668        # we can create amount objects
669        details = AmountDetails(
670            shipping=decimal.Decimal("0.05"),
671            tax=decimal.Decimal("0.40"),
672            fee=decimal.Decimal("3.00"),
673            handling_fee=decimal.Decimal("20.00"),
674            insurance=decimal.Decimal("100.00"),
675            shipping_discount=None
676            )
677        amount = Amount(
678            total=decimal.Decimal("12.12"),
679            currency="USD",
680            details=details
681            )
682        assert amount.total == decimal.Decimal("12.12")
683        assert amount.currency == "USD"
684        assert amount.details is details
685
686    def test_to_dict(self):
687        # we can turn Amount objects into dicts
688        self.maxDiff = None
689        details = AmountDetails(
690            shipping=decimal.Decimal("0.05"),
691            tax=decimal.Decimal("0.40"),
692            fee=decimal.Decimal("3.00"),
693            handling_fee=decimal.Decimal("20.00"),
694            insurance=decimal.Decimal("100.00"),
695            shipping_discount=None
696            )
697        amount = Amount(
698            total=decimal.Decimal("12.12"),
699            currency="USD",
700            details=details
701            )
702        self.assertEqual(
703            amount.to_dict(),
704            {
705                'total': u'12.12',
706                'currency': u'USD',
707                'details': {
708                    'shipping': u'0.05',
709                    'subtotal': u'123.45',
710                    'tax': u'0.40',
711                    'fee': u'3.00',
712                    'handling_fee': u'20.00',
713                    'insurance': u'100.00',
714                    }
715                }
716            )
717
718
719class ItemTests(unittest.TestCase):
720
721    def test_iface(self):
722        # we fullfill all interface contracts
723        item = Item(name=u"Splendid Item")
724        verifyClass(IItem, Item)
725        verifyObject(IItem, item)
726
727    def test_create(self):
728        # we can create Item objects
729        item = Item(
730            quantity=3,
731            name=u"Splendid Thing",
732            price=decimal.Decimal("1.1"),
733            currency="USD",
734            sku="pcs",
735            description=u"Soo splendid!",
736            tax=decimal.Decimal("0.1"),
737            )
738        assert item.quantity == 3
739        assert item.name == u"Splendid Thing"
740        assert item.price == decimal.Decimal("1.1")
741        assert item.currency == "USD"
742        assert item.sku == "pcs"
743        assert item.description == u"Soo splendid!"
744        assert item.tax == decimal.Decimal("0.1")
745
746    def test_to_dict(self):
747        # we can turn Item objects into dicts
748        item = Item(
749            quantity=3,
750            name=u"Splendid Thing",
751            price=decimal.Decimal("1.1"),
752            currency="USD",
753            sku="pcs",
754            description=u"Soo splendid!",
755            tax=decimal.Decimal("0.1"),
756            )
757        self.assertEqual(
758            item.to_dict(),
759            {
760                "quantity": u"3",
761                "name": u"Splendid Thing",
762                "price": u"1.10",
763                "currency": u"USD",
764                "sku": u"pcs",
765                "description": u"Soo splendid!",
766                "tax": u"0.10"
767                }
768            )
769
770
771class ItemListTests(unittest.TestCase):
772
773    def test_iface(self):
774        # we fullfill all interface contracts
775        item_list = ItemList()
776        verifyClass(IItemList, ItemList)
777        verifyObject(IItemList, item_list)
778
779    def test_create_minimal(self):
780        # we can create ItemLists with a minimum of params
781        item_list = ItemList()
782        assert item_list.shipping_address is None
783        assert item_list.items == []
784
785    def test_create(self):
786        # we can create ItemLists
787        item1 = Item(
788            name=u"Splendid Thing",
789            )
790        item2 = Item(
791            name=u"Other Splendid Thing",
792            )
793        addr = ShippingAddress(
794            recipient_name=u'Rob Receiver',
795            line1=u'Honey Street 1',
796            city=u'Beartown',
797            country_code=u'GB',
798            )
799        item_list = ItemList(
800            shipping_address=addr,
801            items=[item1, item2])
802        assert item_list.shipping_address is addr
803        assert item_list.items == [item1, item2]
804
805    def test_to_dict(self):
806        # we can turn ITemLists into dicts
807        item = Item(
808            quantity=3,
809            name=u"Splendid Thing",
810            price=decimal.Decimal("1.1"),
811            currency="USD",
812            sku="pcs",
813            description=u"Soo splendid!",
814            tax=decimal.Decimal("0.1"),
815            )
816        addr = ShippingAddress(
817            recipient_name=u'Rob Receiver',
818            line1=u'Honey Street 1',
819            city=u'Beartown',
820            country_code=u'GB',
821            )
822        item_list = ItemList(items=[item, ], shipping_address=addr)
823        self.assertEqual(
824            item_list.to_dict(),
825            {
826                "items": [
827                    {
828                        "quantity": u"3",
829                        "name": u"Splendid Thing",
830                        "price": u"1.10",
831                        "currency": u"USD",
832                        "sku": u"pcs",
833                        "description": u"Soo splendid!",
834                        "tax": u"0.10"
835                        }
836                    ],
837                "shipping_address":
838                {
839                    'recipient_name': u'Rob Receiver',
840                    'type': u'residential',
841                    'line1': u'Honey Street 1',
842                    'city': u'Beartown',
843                    'country_code': u'GB',
844                    }
845                }
846            )
847
848
849class PaymentOptionsTests(unittest.TestCase):
850
851    def test_iface(self):
852        # we fullfill all interface contracts
853        opts = PaymentOptions()
854        verifyClass(IPaymentOptions, PaymentOptions)
855        verifyObject(IPaymentOptions, opts)
856
857    def test_create(self):
858        # we can create PaymentOptions objects
859        opts = PaymentOptions()
860        assert opts.allowed_payment_method is None
861
862    def test_allowed_payment_method_checked_in_init(self):
863        # any value apart from None, INSTANT... is rejected in __init__
864        self.assertRaises(
865            ValueError,
866            PaymentOptions, allowed_payment_method='NoTvAlID')
867
868    def test_to_dict(self):
869        # we can turn PaymentOptions into dicts
870        opts = PaymentOptions(
871            allowed_payment_method="INSTANT_FUNDING_SOURCE")
872        self.assertEqual(
873            opts.to_dict(),
874            {
875                'allowed_payment_method': "INSTANT_FUNDING_SOURCE",
876                }
877            )
878
879
880class TransactionTests(unittest.TestCase):
881
882    def test_iface(self):
883        # we fullfill all interface contracts
884        amount = Amount()
885        transaction = Transaction(amount=amount)
886        verifyClass(ITransaction, Transaction)
887        verifyObject(ITransaction, transaction)
888
889    def test_create(self):
890        # we can create transacions
891        amount = Amount()
892        transaction = Transaction(amount=amount)
893        assert transaction.amount is amount
894        assert transaction.description is None
895        assert transaction.item_list is None
896        assert transaction.related_resources == []
897        assert transaction.invoice_number is None
898        assert transaction.custom is None
899        assert transaction.soft_descriptor is None
900        assert transaction.payment_options is None
901
902    def test_to_dict(self):
903        # we can turn Transaction objects into dicts
904        transaction = Transaction(
905            amount=Amount(),
906            description=u"My description",
907            item_list=ItemList(),
908            related_resources=[],
909            invoice_number=u"12345",
910            custom=u"Some custom remark",
911            soft_descriptor=u"softdescriptor?",
912            payment_options=PaymentOptions(
913                allowed_payment_method="INSTANT_FUNDING_SOURCE"),
914            )
915        self.assertEqual(
916            transaction.to_dict(), {
917                'amount': {'currency': u'USD', 'total': u'0.00'},
918                'custom': u'Some custom remark',
919                'description': u'My description',
920                'invoice_number': u'12345',
921                'item_list': {
922                    'items': []
923                    },
924                'payment_options': {
925                    'allowed_payment_method': u'INSTANT_FUNDING_SOURCE'
926                    },
927                'related_resources': [],
928                'soft_descriptor': u'softdescriptor?'
929                }
930            )
931
932
933class AddressTypesVocabTests(unittest.TestCase):
934
935    def test_address_types_vocab_tokenized(self):
936        # we can get a countries source suitable for forms etc.
937        verifyObject(IVocabularyTokenized, ADDRESS_TYPES_VOCAB)
938
939    def test_address_types_vocab_i18nized(self):
940        # vocab titles are i18nized
941        result = ADDRESS_TYPES_VOCAB.getTerm('residential')
942        assert ITerm.providedBy(result)
943        self.assertEqual(result.title, u'residential')
944        assert isinstance(result.title, i18nMessage)
945
946    def test_address_types_vocab_tokens_are_string(self):
947        # vocab tokens are simple strings
948        result = ADDRESS_TYPES_VOCAB.getTerm('residential')
949        assert ITerm.providedBy(result)
950        assert result.token == result.value
951        assert result.value == 'residential'
952        assert isinstance(result.token, str)
953        assert isinstance(result.value, str)
954
955
956class CreditCardTypesVocabTests(unittest.TestCase):
957
958    def test_credit_card_types_vocab_tokenized(self):
959        # we can get a countries source suitable for forms etc.
960        verifyObject(IVocabularyTokenized, CREDIT_CARD_TYPES_VOCAB)
961
962    def test_credit_cards_types_vocab_i18nized(self):
963        # vocab titles are i18nized
964        result = CREDIT_CARD_TYPES_VOCAB.getTerm('visa')
965        assert ITerm.providedBy(result)
966        self.assertEqual(result.title, u'visa')
967        assert isinstance(result.title, i18nMessage)
968
969    def test_credit_cards_types_vocab_tokens_are_string(self):
970        # vocab tokens are simple strings
971        result = CREDIT_CARD_TYPES_VOCAB.getTerm('visa')
972        assert ITerm.providedBy(result)
973        assert result.token == result.value
974        assert result.value == 'visa'
975        assert isinstance(result.token, str)
976        assert isinstance(result.value, str)
977
978
979class CreditcardstatusVocabTests(unittest.TestCase):
980
981    def test_credit_card_status_vocab_tokenized(self):
982        # we can get a countries source suitable for forms etc.
983        verifyObject(IVocabularyTokenized, CREDIT_CARD_STATUS_VOCAB)
984
985    def test_credit_cards_status_vocab_i18nized(self):
986        # vocab titles are i18nized
987        result = CREDIT_CARD_STATUS_VOCAB.getTerm('ok')
988        assert ITerm.providedBy(result)
989        self.assertEqual(result.title, u'ok')
990        assert isinstance(result.title, i18nMessage)
991
992    def test_credit_cards_status_vocab_tokens_are_string(self):
993        # vocab tokens are simple strings
994        result = CREDIT_CARD_STATUS_VOCAB.getTerm('expired')
995        assert ITerm.providedBy(result)
996        assert result.token == result.value
997        assert result.value == 'expired'
998        assert isinstance(result.token, str)
999        assert isinstance(result.value, str)
1000
1001
1002class StockKeepingUnitsVocabTests(unittest.TestCase):
1003
1004    def test_sku_vocab_tokenized(self):
1005        # we can get a tokenzed vocab for stock keeping units
1006        verifyObject(IVocabularyTokenized, STOCK_KEEPING_UNITS_VOCAB)
1007
1008    def test_sku_vocab_i18nized(self):
1009        # vocab titles are i18nized
1010        result = STOCK_KEEPING_UNITS_VOCAB.getTerm('pcs')
1011        assert ITerm.providedBy(result)
1012        self.assertEqual(result.title, u'pieces')
1013        assert isinstance(result.title, i18nMessage)
1014
1015    def test_sku_vocab_tokens_are_string(self):
1016        # vocab tokens are simple strings
1017        result = STOCK_KEEPING_UNITS_VOCAB.getTerm('pcs')
1018        assert ITerm.providedBy(result)
1019        assert result.token == result.value
1020        assert result.value == 'pcs'
1021        assert isinstance(result.token, str)
1022        assert isinstance(result.value, str)
1023
1024
1025class PaymentOptionMethodsVocabTests(unittest.TestCase):
1026
1027    def test_payment_option_methods_vocab_tokenized(self):
1028        # we can get a countries source suitable for forms etc.
1029        verifyObject(IVocabularyTokenized, PAYMENT_OPTION_METHODS_VOCAB)
1030
1031    def test_payment_option_methods_vocab_i18nized(self):
1032        # vocab titles are i18nized
1033        result = PAYMENT_OPTION_METHODS_VOCAB.getTerm('INSTANT_FUNDING_SOURCE')
1034        assert ITerm.providedBy(result)
1035        self.assertEqual(result.title, u'INSTANT_FUNDING_SOURCE')
1036        assert isinstance(result.title, i18nMessage)
1037
1038    def test_payment_option_methods_vocab_tokens_are_string(self):
1039        # vocab tokens are simple strings
1040        result = PAYMENT_OPTION_METHODS_VOCAB.getTerm('INSTANT_FUNDING_SOURCE')
1041        assert ITerm.providedBy(result)
1042        assert result.token == result.value
1043        assert result.value == 'INSTANT_FUNDING_SOURCE'
1044        assert isinstance(result.token, str)
1045        assert isinstance(result.value, str)
1046
1047
1048class FakePayer(object):
1049
1050    implements(IPayer)
1051
1052    payer_id = 'PAYER-123'
1053
1054
1055class FakePayee(object):
1056
1057     implements(IPayee)
1058
1059     payee_id = 'PAYEE-456'
1060
1061
1062class FakePaymentItem(object):
1063
1064    implements(IPaymentItem)
1065
1066    item_id = 'BILL-123456'
1067    amount = decimal.Decimal("12.10")
1068    currency = 'EUR'
1069
1070
1071class PayPalCreditCardServiceTests(unittest.TestCase):
1072
1073    def test_iface(self):
1074        # we fullfill all interface contracts
1075        service = PayPalCreditCardService()
1076        verifyClass(IPaymentGatewayService, PayPalCreditCardService)
1077        verifyObject(IPaymentGatewayService, service)
1078
1079    def DIStest_creditcard_service_can_create_payment(self):
1080        # we can create IPayment objects with creditcard service
1081        service = PayPalCreditCardService()
1082        payment = service.create_payment(
1083            payer=FakePayer(),
1084            payment_item=FakePaymentItem(),
1085            payee=FakePayee()
1086            )
1087        assert IPayment.providedBy(payment)
1088
1089
1090class FunctionalPaypalTests(FunctionalTestCase):
1091
1092    layer = FunctionalLayer
1093
1094    @external_paypal_test
1095    def test_get_access_token(self):
1096        # we can get an access token
1097        result = get_access_token()
1098        assert isinstance(result, unicode)
1099
1100    @external_paypal_test
1101    def test_get_payment(self):
1102        # we can construct (paypal-)payment objects
1103        payment = get_payment()
1104        assert isinstance(payment, paypalrestsdk.Payment)
1105        result = payment.create()
1106        assert result is True
1107
1108    def test_paypal_services_registered(self):
1109        # the PayPal gateway services are all registered
1110        creditcard_service = queryUtility(
1111            IPaymentGatewayService, name=u'paypal_creditcard')
1112        assert creditcard_service is not None
1113        assert isinstance(creditcard_service, PayPalCreditCardService)
1114        paypal_regular_service = queryUtility(
1115            IPaymentGatewayService, name=u'paypal_regular')
1116        assert paypal_regular_service is not None
1117        assert isinstance(paypal_regular_service, PayPalRegularPaymentService)
Note: See TracBrowser for help on using the repository browser.