From 0d92719bd8fd951031f26c7819a9eab233cbca73 Mon Sep 17 00:00:00 2001 From: Ryan Johnston Date: Fri, 21 Aug 2015 16:02:25 -0400 Subject: [PATCH 01/24] Version Bump --- sharpy/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sharpy/__init__.py b/sharpy/__init__.py index 1bc90e9..c07c373 100644 --- a/sharpy/__init__.py +++ b/sharpy/__init__.py @@ -1 +1 @@ -VERSION = (0, 8) +VERSION = (0, 9) From 92d66203e33ed20e5c675ef1574f29f39802025e Mon Sep 17 00:00:00 2001 From: Ryan Johnston Date: Fri, 21 Aug 2015 16:03:46 -0400 Subject: [PATCH 02/24] Add promotion parsers --- sharpy/parsers.py | 75 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 75 insertions(+) diff --git a/sharpy/parsers.py b/sharpy/parsers.py index 6d4b417..8235e93 100644 --- a/sharpy/parsers.py +++ b/sharpy/parsers.py @@ -328,4 +328,79 @@ def parse_subscription_item(self, item_element): item['modified_datetime'] = self.parse_datetime(item_element.findtext('modifiedDatetime')) return item + + +class PromotionsParser(CheddarOutputParser): + ''' + A utility class for parsing cheddar's xml output for promotions. + ''' + def parse_xml(self, xml_str): + promotions = [] + promotions_xml = XML(xml_str) + for promotion_xml in promotions_xml: + promotion = self.parse_promotion(promotion_xml) + promotions.append(promotion) + + return promotions + + def parse_promotions(self, promotions_element): + promotions = [] + if promotions_element is not None: + for promotion_element in promotions_element: + promotions.append(self.parse_promotion(promotion_element)) + + return promotions + + def parse_promotion(self, promotion_element): + promotion = {} + import pdb; pdb.set_trace() + promotion['id'] = promotion_element.attrib['id'] + promotion['name'] = promotion_element.findtext('name') + promotion['description'] = promotion_element.findtext('description') + promotion['created_datetime'] = self.parse_datetime(promotion_element.findtext('createdDatetime')) + + promotion['incentives'] = self.parse_incentives(promotion_element.find('incentives')) + promotion['coupons'] = self.parse_coupons(promotion_element.find('coupons')) + + return promotion + + def parse_incentives(self, incentives_element): + incentives = [] + + if incentives_element is not None: + for incentive_element in incentives_element: + incentives.append(self.parse_incentive(incentive_element)) + + return incentives + + def parse_incentive(self, incentive_element): + incentive = {} + + incentive['id'] = incentive_element.attrib['id'] + incentive['type'] = incentive_element.findtext('type') + incentive['percentage'] = incentive_element.findtext('percentage') + incentive['months'] = incentive_element.findtext('months') + incentive['created_datetime'] = self.parse_datetime(incentive_element.findtext('createdDatetime')) + + return incentive + + def parse_coupons(self, coupons_element): + coupons = [] + + if coupons_element is not None: + for coupon_element in coupons_element: + coupons.append(self.parse_coupon(coupon_element)) + + return coupons + + def parse_coupon(self, coupon_element): + coupon = {} + + coupon['id'] = coupon_element.attrib['id'] + coupon['code'] = coupon_element.attrib['code'] + coupon['max_redemptions'] = coupon_element.findtext('maxRedemptions') + coupon['expiration_datetime'] = self.parse_datetime(coupon_element.findtext('expirationDatetime')) + coupon['created_datetime'] = self.parse_datetime(coupon_element.findtext('createdDatetime')) + + return coupon From 7f627b2cd905cb44938e9aaf7327daf5f60b3f18 Mon Sep 17 00:00:00 2001 From: Ryan Johnston Date: Fri, 21 Aug 2015 16:04:01 -0400 Subject: [PATCH 03/24] Add promotion object to product. --- sharpy/product.py | 77 ++++++++++++++++++++++++++++++++++++++++------- 1 file changed, 66 insertions(+), 11 deletions(-) diff --git a/sharpy/product.py b/sharpy/product.py index cd6c0bc..17992b9 100644 --- a/sharpy/product.py +++ b/sharpy/product.py @@ -7,7 +7,7 @@ from sharpy.client import Client from sharpy.exceptions import NotFound -from sharpy.parsers import PlansParser, CustomersParser +from sharpy.parsers import PlansParser, CustomersParser, PromotionsParser class CheddarProduct(object): @@ -263,8 +263,42 @@ def delete_all_customers(self): path='customers/delete-all/confirm/%d' % int(time()), method='POST' ) - - + + def get_all_promotions(self): + ''' + Returns all promotions. + https://cheddargetter.com/developers#promotions + ''' + promotions = [] + + try: + response = self.client.make_request(path='promotions/get') + except NotFound: + response = None + + response = self.client.make_request(path='promotions/get') + promotions_parser = PromotionsParser() + promotions_data = promotions_parser.parse_xml(response.content) + promotions = [Promotion(**promotion_data) for promotion_data in promotions_data] + + return promotions + + def get_promotion(self, code): + ''' + Get the promotion with the specified coupon code. + https://cheddargetter.com/developers#single-promotion + ''' + + response = self.client.make_request( + path='promotions/get', + params={'code': code}, + ) + promotion_parser = PromotionsParser() + promotion_data = promotion_parser.parse_xml(response.content) + + return Promotion(**promotion_data[0]) + + class PricingPlan(object): def __init__(self, name, code, id, description, is_active, is_free, @@ -576,12 +610,12 @@ def __init__(self, id, gateway_token, cc_first_name, cc_last_name, super(Subscription, self).__init__() - def load_data(self, id, gateway_token, cc_first_name, cc_last_name, \ - cc_company, cc_country, cc_address, cc_city, cc_state, \ - cc_zip, cc_type, cc_last_four, cc_expiration_date, customer,\ - cc_email=None, canceled_datetime=None ,created_datetime=None, \ - plans=None, invoices=None, items=None, gateway_account=None, \ - cancel_reason=None, cancel_type=None, redirect_url=None): + def load_data(self, id, gateway_token, cc_first_name, cc_last_name, + cc_company, cc_country, cc_address, cc_city, cc_state, + cc_zip, cc_type, cc_last_four, cc_expiration_date, customer, + cc_email=None, canceled_datetime=None ,created_datetime=None, + plans=None, invoices=None, items=None, gateway_account=None, + cancel_reason=None, cancel_type=None, redirect_url=None): self.id = id self.gateway_token = gateway_token @@ -764,5 +798,26 @@ def set(self, quantity): ) return self.subscription.customer.load_data_from_xml(response.content) - - + + +class Promotion(object): + def __init__(self, id=None, code=None, name=None, description=None, + created_datetime=None, incentives=None, coupons=None): + + self.load_data(code=code, id=id, name=name, description=description, + created_datetime=created_datetime, + incentives=incentives, coupons=coupons) + + super(Promotion, self).__init__() + + def load_data(self, id=None, code=None, name=None, description=None, + created_datetime=None, incentives=None, coupons=None): + + self.code = code + self.id = id + self.name = name + self.description = description + self.created = created_datetime + + self.incentives = incentives + self.coupons = coupons \ No newline at end of file From 8b589acf3348a94af9d56bc4e837b518fa8d3243 Mon Sep 17 00:00:00 2001 From: Ryan Johnston Date: Fri, 21 Aug 2015 16:10:41 -0400 Subject: [PATCH 04/24] Update readme with elementtree information --- README.rst | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/README.rst b/README.rst index 630b8bb..25f40b2 100644 --- a/README.rst +++ b/README.rst @@ -50,8 +50,17 @@ Code You can checkout and download Sharpy's latest code at `Github `_. +Installing elementtree for Development and Unit Testing +======================================================= +When trying to install elementtree, pip may report that there is no such package. If this happens to you, you can work around by downloading and installing it manually. + + wget http://effbot.org/media/downloads/elementtree-1.2.6-20050316.zip + unzip elementtree-1.2.6-20050316.zip + cd elementtree-1.2.6-20050316/ + pip install . + TODOs ===== * Flesh out the documentation to cover the full API. -* Add support for the various filtering options in the `get_customers` call. \ No newline at end of file +* Add support for the various filtering options in the `get_customers` call. From 72f6aa8d6bf050cd0b661c382de4114c9593691e Mon Sep 17 00:00:00 2001 From: Ryan Johnston Date: Fri, 21 Aug 2015 16:13:06 -0400 Subject: [PATCH 05/24] Formatting updates for code in readme --- README.rst | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/README.rst b/README.rst index 25f40b2..c5dcb99 100644 --- a/README.rst +++ b/README.rst @@ -30,6 +30,8 @@ Getting Started To get started with Sharpy, simply install it like you would any other python package +.. code:: + pip install sharpy Optionally, you can also install `lxml `_ on your @@ -54,6 +56,8 @@ Installing elementtree for Development and Unit Testing ======================================================= When trying to install elementtree, pip may report that there is no such package. If this happens to you, you can work around by downloading and installing it manually. +.. code:: + wget http://effbot.org/media/downloads/elementtree-1.2.6-20050316.zip unzip elementtree-1.2.6-20050316.zip cd elementtree-1.2.6-20050316/ From 02b729539b2375998d411adfc9753401d455de71 Mon Sep 17 00:00:00 2001 From: Ryan Johnston Date: Fri, 21 Aug 2015 17:28:38 -0400 Subject: [PATCH 06/24] Add readme for testing --- tests/readme.rst | 31 +++++++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) create mode 100644 tests/readme.rst diff --git a/tests/readme.rst b/tests/readme.rst new file mode 100644 index 0000000..6b41c7e --- /dev/null +++ b/tests/readme.rst @@ -0,0 +1,31 @@ +Requirements +============ + +Inside a virtualenv, run: + +pip install -r dev-requirements.txt + +Installing elementtree for Unit Testing +======================================================= +When trying to install elementtree, pip may report that there is no such package. If this happens to you, you can work around by downloading and installing it manually. + +.. code:: + + wget http://effbot.org/media/downloads/elementtree-1.2.6-20050316.zip + unzip elementtree-1.2.6-20050316.zip + cd elementtree-1.2.6-20050316/ + pip install . + +Config +====== + +In the tests folder, copy the config.ini.template to config.ini. Fill in your email, password, and product code. + +You will also need to setup the correct plans in cheddar. You may want to set up a product intended just for testing. + +Running Tests +============= +Run the test with nosetests. + +.. code:: + nosetests From ded5aed84cd42c9728bc7ac0c281ab34714208b0 Mon Sep 17 00:00:00 2001 From: Ryan Johnston Date: Fri, 21 Aug 2015 17:29:37 -0400 Subject: [PATCH 07/24] Needs line break for code to show --- tests/readme.rst | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/readme.rst b/tests/readme.rst index 6b41c7e..48e1dfc 100644 --- a/tests/readme.rst +++ b/tests/readme.rst @@ -28,4 +28,5 @@ Running Tests Run the test with nosetests. .. code:: + nosetests From acfc60cda7601530fed205e7fcb11b496b7de357 Mon Sep 17 00:00:00 2001 From: Ryan Johnston Date: Fri, 21 Aug 2015 17:30:10 -0400 Subject: [PATCH 08/24] Add code formatting to install line. --- tests/readme.rst | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/tests/readme.rst b/tests/readme.rst index 48e1dfc..241072c 100644 --- a/tests/readme.rst +++ b/tests/readme.rst @@ -3,7 +3,9 @@ Requirements Inside a virtualenv, run: -pip install -r dev-requirements.txt +.. code:: + + pip install -r dev-requirements.txt Installing elementtree for Unit Testing ======================================================= From 7ffa8a2be17463a4b810c1bf3c799082d02d73a5 Mon Sep 17 00:00:00 2001 From: Ryan Johnston Date: Mon, 24 Aug 2015 11:11:47 -0400 Subject: [PATCH 09/24] Update readme with cheddargetter unittest setup. --- tests/readme.rst | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/tests/readme.rst b/tests/readme.rst index 241072c..6947dc4 100644 --- a/tests/readme.rst +++ b/tests/readme.rst @@ -23,8 +23,18 @@ Config In the tests folder, copy the config.ini.template to config.ini. Fill in your email, password, and product code. + +Cheddar Setup +============= You will also need to setup the correct plans in cheddar. You may want to set up a product intended just for testing. +The following plan codes are required for unit tests: + +* FREE_MONTHLY +* PAID_MONTHLY + +Be sure you turn on the native gateway credit card option. + Running Tests ============= Run the test with nosetests. From 018c6daa6e19eb902c0e5affbe06bf104c03e6a1 Mon Sep 17 00:00:00 2001 From: Ryan Johnston Date: Mon, 24 Aug 2015 11:12:39 -0400 Subject: [PATCH 10/24] CheddarGetter setup will probably happen before config. --- tests/readme.rst | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/tests/readme.rst b/tests/readme.rst index 6947dc4..4accffd 100644 --- a/tests/readme.rst +++ b/tests/readme.rst @@ -18,13 +18,7 @@ When trying to install elementtree, pip may report that there is no such package cd elementtree-1.2.6-20050316/ pip install . -Config -====== - -In the tests folder, copy the config.ini.template to config.ini. Fill in your email, password, and product code. - - -Cheddar Setup +CheddarGetter Setup ============= You will also need to setup the correct plans in cheddar. You may want to set up a product intended just for testing. @@ -35,6 +29,11 @@ The following plan codes are required for unit tests: Be sure you turn on the native gateway credit card option. +Config +====== + +In the tests folder, copy the config.ini.template to config.ini. Fill in your email, password, and product code. + Running Tests ============= Run the test with nosetests. From 35fa3cc21be40a712b491a15ea9a291f07d5bb35 Mon Sep 17 00:00:00 2001 From: Ryan Johnston Date: Mon, 24 Aug 2015 13:15:12 -0400 Subject: [PATCH 11/24] Update readme.rst --- tests/readme.rst | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/readme.rst b/tests/readme.rst index 4accffd..a126579 100644 --- a/tests/readme.rst +++ b/tests/readme.rst @@ -26,6 +26,7 @@ The following plan codes are required for unit tests: * FREE_MONTHLY * PAID_MONTHLY +* TRACKED_MONTHLY Be sure you turn on the native gateway credit card option. From 6926b4f9dd7ce032661e7582854e5ef0829fd8bd Mon Sep 17 00:00:00 2001 From: Ryan Johnston Date: Mon, 24 Aug 2015 13:18:27 -0400 Subject: [PATCH 12/24] Update readme.rst --- tests/readme.rst | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/tests/readme.rst b/tests/readme.rst index a126579..08e2a8a 100644 --- a/tests/readme.rst +++ b/tests/readme.rst @@ -28,6 +28,11 @@ The following plan codes are required for unit tests: * PAID_MONTHLY * TRACKED_MONTHLY +The following tracked items are required for unit tests: + +* MONTHLY_ITEM +* ONCE_ITEM + Be sure you turn on the native gateway credit card option. Config From 4d0fd823206337b98bf1d32bfeb313fcaff532e7 Mon Sep 17 00:00:00 2001 From: Ryan Johnston Date: Mon, 24 Aug 2015 13:43:45 -0400 Subject: [PATCH 13/24] Try to be more clean on plans. Update the plans to a table to include the names and number of tracked items. Some Unit tests are checking against these. --- tests/readme.rst | 27 ++++++++++++++++++++------- 1 file changed, 20 insertions(+), 7 deletions(-) diff --git a/tests/readme.rst b/tests/readme.rst index 08e2a8a..d865c99 100644 --- a/tests/readme.rst +++ b/tests/readme.rst @@ -22,18 +22,31 @@ CheddarGetter Setup ============= You will also need to setup the correct plans in cheddar. You may want to set up a product intended just for testing. -The following plan codes are required for unit tests: -* FREE_MONTHLY -* PAID_MONTHLY -* TRACKED_MONTHLY The following tracked items are required for unit tests: -* MONTHLY_ITEM -* ONCE_ITEM ++--------------+--------------+ +| Name | Code | ++==============+==============+ +| Once Item | ONCE_ITEM | ++--------------+--------------+ +| Monthly Item | MONTHLY_ITEM | ++--------------+--------------+ + +The following plan codes are required for unit tests: -Be sure you turn on the native gateway credit card option. ++-----------------+-----------------+---------+-----------+--------------+ +| Plan Name | Code | Price | ONCE_ITEM | MONTHLY_ITEM | ++=================+=================+=========+===========+==============+ +| Free Monthly | FREE_MONTHLY | $0.00 | 1 | 10 | ++-----------------+-----------------+---------+-----------+--------------+ +| Paid Monthly | PAID_MONTHLY | $10.00 | 1 | 10 | ++-----------------+-----------------+---------+-----------+--------------+ +| Tracked Monthly | TRACKED_MONTHLY | $10.00 | 1 | 10 | ++-----------------+-----------------+---------+-----------+--------------+ + +Be sure to turn on the native gateway credit card option in Configuration > Product settings > Gateway Settings. Config ====== From fbed197cc3e06d64c9bc24753389ffd608f58aaa Mon Sep 17 00:00:00 2001 From: Ryan Johnston Date: Mon, 24 Aug 2015 14:31:42 -0400 Subject: [PATCH 14/24] Update readme.rst --- tests/readme.rst | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/tests/readme.rst b/tests/readme.rst index d865c99..4d03d60 100644 --- a/tests/readme.rst +++ b/tests/readme.rst @@ -46,6 +46,17 @@ The following plan codes are required for unit tests: | Tracked Monthly | TRACKED_MONTHLY | $10.00 | 1 | 10 | +-----------------+-----------------+---------+-----------+--------------+ + +The following promotions are required for unit tests: + ++----------------+---------------+--------+ +| Promotion Name | Coupon Code | % Off | ++================+===============+========+ +| Coupon | COUPON | 10 | ++----------------+---------------+--------+ +| Coupon 2 | COUPON2 | 20 | ++----------------+---------------+--------+ + Be sure to turn on the native gateway credit card option in Configuration > Product settings > Gateway Settings. Config From ed573e111589bb398ae1b0b610fcdf06cdaf55ba Mon Sep 17 00:00:00 2001 From: Ryan Johnston Date: Mon, 24 Aug 2015 14:32:46 -0400 Subject: [PATCH 15/24] Update readme.rst --- tests/readme.rst | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/tests/readme.rst b/tests/readme.rst index 4d03d60..59bb58e 100644 --- a/tests/readme.rst +++ b/tests/readme.rst @@ -49,13 +49,13 @@ The following plan codes are required for unit tests: The following promotions are required for unit tests: -+----------------+---------------+--------+ -| Promotion Name | Coupon Code | % Off | -+================+===============+========+ -| Coupon | COUPON | 10 | -+----------------+---------------+--------+ -| Coupon 2 | COUPON2 | 20 | -+----------------+---------------+--------+ ++----------------+---------------+--------+-----------+ +| Promotion Name | Coupon Code | % Off | Duration | ++================+===============+========+===========+ +| Coupon | COUPON | 10 | Forever | ++----------------+---------------+--------+-----------+ +| Coupon 2 | COUPON2 | 20 | Forever | ++----------------+---------------+--------+-----------+ Be sure to turn on the native gateway credit card option in Configuration > Product settings > Gateway Settings. From f8f0500d116d6597660988d8bb9efd8857c079e1 Mon Sep 17 00:00:00 2001 From: Ryan Johnston Date: Mon, 24 Aug 2015 15:17:34 -0400 Subject: [PATCH 16/24] Remove the debug code. --- sharpy/parsers.py | 1 - 1 file changed, 1 deletion(-) diff --git a/sharpy/parsers.py b/sharpy/parsers.py index 8235e93..7183c1f 100644 --- a/sharpy/parsers.py +++ b/sharpy/parsers.py @@ -354,7 +354,6 @@ def parse_promotions(self, promotions_element): def parse_promotion(self, promotion_element): promotion = {} - import pdb; pdb.set_trace() promotion['id'] = promotion_element.attrib['id'] promotion['name'] = promotion_element.findtext('name') promotion['description'] = promotion_element.findtext('description') From 12d08b322cd163a3b14a7d3e88fd0866b3705583 Mon Sep 17 00:00:00 2001 From: Ryan Johnston Date: Mon, 24 Aug 2015 15:18:47 -0400 Subject: [PATCH 17/24] Don't request response twice. Verify response is return before trying to parse. Bubble up coupon code to promotion.code. --- sharpy/product.py | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/sharpy/product.py b/sharpy/product.py index 17992b9..f7810b9 100644 --- a/sharpy/product.py +++ b/sharpy/product.py @@ -276,10 +276,10 @@ def get_all_promotions(self): except NotFound: response = None - response = self.client.make_request(path='promotions/get') - promotions_parser = PromotionsParser() - promotions_data = promotions_parser.parse_xml(response.content) - promotions = [Promotion(**promotion_data) for promotion_data in promotions_data] + if response: + promotions_parser = PromotionsParser() + promotions_data = promotions_parser.parse_xml(response.content) + promotions = [Promotion(**promotion_data) for promotion_data in promotions_data] return promotions @@ -810,6 +810,9 @@ def __init__(self, id=None, code=None, name=None, description=None, super(Promotion, self).__init__() + def __unicode__(self): + return u'{0} ({1})'.format(self.name, self.code) + def load_data(self, id=None, code=None, name=None, description=None, created_datetime=None, incentives=None, coupons=None): @@ -820,4 +823,8 @@ def load_data(self, id=None, code=None, name=None, description=None, self.created = created_datetime self.incentives = incentives - self.coupons = coupons \ No newline at end of file + self.coupons = coupons + + # Bring coupon code up to parent promotion + if self.code is None and self.coupons and len(self.coupons) > 0: + self.code = self.coupons[0].get('code') From 6072a77cc4d19fa0855f8f23ee320894bd79b39f Mon Sep 17 00:00:00 2001 From: Ryan Johnston Date: Mon, 24 Aug 2015 15:20:20 -0400 Subject: [PATCH 18/24] Add unit test for new methods. Skipping failing tests due to issues on cheddar's side. --- tests/client_tests.py | 13 +++- tests/product_tests.py | 161 ++++++++++++++++++++++++++++------------- 2 files changed, 120 insertions(+), 54 deletions(-) diff --git a/tests/client_tests.py b/tests/client_tests.py index 571cc64..10432ba 100644 --- a/tests/client_tests.py +++ b/tests/client_tests.py @@ -93,8 +93,9 @@ def test_make_request_access_denied(self): client = self.get_client(username=bad_username) client.make_request(path) - @raises(BadRequest) + @raises(NotFound) def test_make_request_bad_request(self): + """ Attempt to grab the plans without adding /get to the url. """ path = 'plans' client = self.get_client() client.make_request(path) @@ -104,7 +105,8 @@ def test_make_request_not_found(self): path = 'things-which-dont-exist' client = self.get_client() client.make_request(path) - + + @unittest.skip('Skip until deleting customers is working') @clear_users def test_post_request(self): path = 'customers/new' @@ -118,7 +120,7 @@ def test_post_request(self): client = self.get_client() client.make_request(path, data=data) - + @unittest.skip('Skip until deleting customers is working') def generate_error_response(self, auxcode=None, path=None, params=None, **overrides): ''' Creates a request to cheddar which should return an error @@ -242,9 +244,12 @@ def test_format_datetime_with_now(self): self.assertEquals(expected, result) + @unittest.skip('I can not figure this out.') @clear_users def test_chedder_update_customer_error(self): - # Overriding the zipcode so a customer actually gets created + """ + Test overriding the zipcode so a customer actually gets updated. + """ overrides = { 'subscription[ccZip]': 12345 } diff --git a/tests/product_tests.py b/tests/product_tests.py index 16dcbc9..c0852e5 100644 --- a/tests/product_tests.py +++ b/tests/product_tests.py @@ -137,59 +137,73 @@ def get_customer_with_items(self, **kwargs): customer = self.get_customer(**data) return customer - + + @unittest.skip('Skip until deleting customers is working') @clear_users def test_simple_create_customer(self): self.get_customer() - + + @unittest.skip('Skip until deleting customers is working') @clear_users def test_create_customer_with_company(self): self.get_customer(company='Test Co') - + + @unittest.skip('Skip until deleting customers is working') @clear_users def test_create_customer_with_meta_data(self): self.get_customer(meta_data = {'key_1': 'value_1', 'key2': 'value_2'}) - + + @unittest.skip('Skip until deleting customers is working') @clear_users def test_create_customer_with_true_vat_exempt(self): self.get_customer(is_vat_exempt=True) - + + @unittest.skip('Skip until deleting customers is working') @clear_users def test_create_customer_with_false_vat_exempt(self): self.get_customer(is_vat_exempt=False) - + + @unittest.skip('Skip until deleting customers is working') @clear_users def test_create_customer_with_vat_number(self): self.get_customer(vat_number=12345) - + + @unittest.skip('Skip until deleting customers is working') @clear_users def test_create_customer_with_notes(self): self.get_customer(notes='This is a test note!') - + + @unittest.skip('Skip until deleting customers is working') @clear_users def test_create_customer_with_first_contact_datetime(self): self.get_customer(first_contact_datetime=datetime.now()) - + + @unittest.skip('Skip until deleting customers is working') @clear_users def test_create_customer_with_referer(self): self.get_customer(referer='http://saaspire.com/test.html') - + + @unittest.skip('Skip until deleting customers is working') @clear_users def test_create_customer_with_campaign_term(self): self.get_customer(campaign_term='testing') - + + @unittest.skip('Skip until deleting customers is working') @clear_users def test_create_customer_with_campaign_name(self): self.get_customer(campaign_name='testing') - + + @unittest.skip('Skip until deleting customers is working') @clear_users def test_create_customer_with_campaign_source(self): self.get_customer(campaign_source='testing') - + + @unittest.skip('Skip until deleting customers is working') @clear_users def test_create_customer_with_campaign_content(self): self.get_customer(campaign_content='testing') - + + @unittest.skip('Skip until deleting customers is working') @clear_users def test_create_customer_with_initial_bill_date(self): initial_bill_date = datetime.utcnow() + timedelta(days=60) @@ -201,11 +215,13 @@ def test_create_customer_with_initial_bill_date(self): # if the request is made around UTC midnight diff = initial_bill_date.date() - real_bill_date.date() self.assertLessEqual(diff.days, 1) - + + @unittest.skip('Skip until deleting customers is working') @clear_users def test_create_paid_customer(self): self.get_customer(**self.paid_defaults) - + + @unittest.skip('Skip until deleting customers is working') @clear_users def test_create_paid_customer_with_charges(self): data = copy(self.paid_defaults) @@ -214,7 +230,8 @@ def test_create_paid_customer_with_charges(self): charges.append({'code': 'charge2', 'quantity': 3, 'each_amount': 4}) data['charges'] = charges self.get_customer(**data) - + + @unittest.skip('Skip until deleting customers is working') @clear_users def test_create_paid_customer_with_decimal_charges(self): data = copy(self.paid_defaults) @@ -224,6 +241,7 @@ def test_create_paid_customer_with_decimal_charges(self): data['charges'] = charges self.get_customer(**data) + @unittest.skip('Skip until deleting customers is working') @clear_users def test_create_paid_customer_with_items(self): data = copy(self.paid_defaults) @@ -234,7 +252,7 @@ def test_create_paid_customer_with_items(self): data['plan_code'] = 'TRACKED_MONTHLY' self.get_customer(**data) - + @unittest.skip('Skip until deleting customers is working') @clear_users def test_create_paid_customer_with_decimal_quantity_items(self): data = copy(self.paid_defaults) @@ -245,11 +263,13 @@ def test_create_paid_customer_with_decimal_quantity_items(self): data['plan_code'] = 'TRACKED_MONTHLY' self.get_customer(**data) + @unittest.skip('Skip until deleting customers is working') @clear_users def test_create_paypal_customer(self): data = copy(self.paypal_defaults) self.get_customer(**data) + @unittest.skip('Skip until deleting customers is working') @clear_users def test_update_paypal_customer(self): data = copy(self.paypal_defaults) @@ -260,7 +280,7 @@ def test_update_paypal_customer(self): cancel_url='http://example.com/update-cancel/', ) - + @unittest.skip('Skip until deleting customers is working') @clear_users def test_customer_repr(self): customer = self.get_customer() @@ -269,7 +289,8 @@ def test_customer_repr(self): result = repr(customer) self.assertEquals(expected, result) - + + @unittest.skip('Skip until deleting customers is working') @clear_users def test_subscription_repr(self): customer = self.get_customer() @@ -279,7 +300,8 @@ def test_subscription_repr(self): result = repr(subscription) self.assertIn(expected, result) - + + @unittest.skip('Skip until deleting customers is working') @clear_users def test_pricing_plan_repr(self): customer = self.get_customer() @@ -290,8 +312,8 @@ def test_pricing_plan_repr(self): result = repr(plan) self.assertEquals(expected, result) - - + + @unittest.skip('Skip until deleting customers is working') @clear_users def test_item_repr(self): customer = self.get_customer_with_items() @@ -302,7 +324,8 @@ def test_item_repr(self): result = repr(item) self.assertEquals(expected, result) - + + @unittest.skip('Duplicate transaction error. 6 seconds.') @clear_users def test_get_customers(self): customer1 = self.get_customer() @@ -319,7 +342,8 @@ def test_get_customers(self): fetched_customers = product.get_customers() self.assertEquals(2, len(fetched_customers)) - + + @unittest.skip('Duplicate transaction error. 6 seconds.') @clear_users def test_get_customer(self): created_customer = self.get_customer() @@ -331,7 +355,8 @@ def test_get_customer(self): self.assertEquals(created_customer.first_name, fetched_customer.first_name) self.assertEquals(created_customer.last_name, fetched_customer.last_name) self.assertEquals(created_customer.email, fetched_customer.email) - + + @unittest.skip('Skip until deleting customers is working') @clear_users def test_simple_customer_update(self): new_name = 'Different' @@ -343,7 +368,8 @@ def test_simple_customer_update(self): fetched_customer = product.get_customer(code=customer.code) self.assertEquals(customer.first_name, fetched_customer.first_name) - + + @unittest.skip('Skip until deleting customers is working') @clear_users @raises(NotFound) def test_delete_customer(self): @@ -355,8 +381,8 @@ def test_delete_customer(self): customer.delete() fetched_customer = product.get_customer(code=customer.code) - - + + @unittest.skip('Skip until deleting customers is working') @clear_users def test_delete_all_customers(self): customer_1 = self.get_customer() @@ -370,7 +396,8 @@ def test_delete_all_customers(self): fetched_customers = product.get_customers() self.assertEquals(0, len(fetched_customers)) - + + @unittest.skip('Skip until deleting customers is working') @clear_users def test_cancel_subscription(self): customer = self.get_customer() @@ -398,19 +425,23 @@ def assert_increment(self, quantity=None): fetched_customer = product.get_customer(code=customer.code) fetched_item = customer.subscription.items[item.code] self.assertEquals(item.quantity_used, fetched_item.quantity_used) - + + @unittest.skip('Skip until deleting customers is working') @clear_users def test_simple_increment(self): self.assert_increment() - + + @unittest.skip('Skip until deleting customers is working') @clear_users def test_int_increment(self): self.assert_increment(1) - + + @unittest.skip('Skip until deleting customers is working') @clear_users def test_float_increment(self): self.assert_increment(1.234) - + + @unittest.skip('Skip until deleting customers is working') @clear_users def test_decimal_increment(self): self.assert_increment(Decimal('1.234')) @@ -430,19 +461,23 @@ def assert_decrement(self, quantity=None): fetched_customer = product.get_customer(code=customer.code) fetched_item = customer.subscription.items[item.code] self.assertEquals(item.quantity_used, fetched_item.quantity_used) - + + @unittest.skip('Skip until deleting customers is working') @clear_users def test_simple_decrement(self): self.assert_decrement() - + + @unittest.skip('Duplicate transaction error. 6 seconds.') @clear_users def test_int_decrement(self): self.assert_decrement(1) - + + @unittest.skip('Skip until deleting customers is working') @clear_users def test_float_decrement(self): self.assert_decrement(1.234) - + + @unittest.skip('Skip until deleting customers is working') @clear_users def test_decimal_decrement(self): self.assert_decrement(Decimal('1.234')) @@ -461,15 +496,18 @@ def assert_set(self, quantity): fetched_customer = product.get_customer(code=customer.code) fetched_item = customer.subscription.items[item.code] self.assertEquals(item.quantity_used, fetched_item.quantity_used) - + + @unittest.skip('Duplicate transaction error. 6 seconds.') @clear_users def test_int_set(self): self.assert_set(1) - + + @unittest.skip('Skip until deleting customers is working') @clear_users def test_float_set(self): self.assert_set(1.234) - + + @unittest.skip('Skip until deleting customers is working') @clear_users def test_decimal_set(self): self.assert_set(Decimal('1.234')) @@ -509,27 +547,28 @@ def assert_charged(self, code, each_amount, quantity=None, self.assertAlmostEqual(Decimal(each_amount), fetched_charge['each_amount'], places=2) self.assertEqual(quantity, fetched_charge['quantity']) self.assertEqual(description, fetched_charge['description']) - + + @unittest.skip('Skip until deleting customers is working') @clear_users def test_add_charge(self): self.assert_charged(code='TEST-CHARGE', each_amount=1, quantity=1) - - @clear_users - def test_add_float_charge(self): - self.assert_charged(code='TEST-CHARGE', each_amount=2.3, quantity=2) - + + @unittest.skip('Skip until deleting customers is working') @clear_users def test_add_float_charge(self): self.assert_charged(code='TEST-CHARGE', each_amount=2.3, quantity=2) + @unittest.skip('Skip until deleting customers is working') @clear_users def test_add_decimal_charge(self): self.assert_charged(code='TEST-CHARGE', each_amount=Decimal('2.3'), quantity=3) - + + @unittest.skip('Skip until deleting customers is working') @clear_users def test_add_charge_with_descriptions(self): self.assert_charged(code='TEST-CHARGE', each_amount=1, quantity=1, description="A test charge") - + + @unittest.skip('Skip until deleting customers is working') @clear_users def test_add_credit(self): self.assert_charged(code='TEST-CHARGE', each_amount=-1, quantity=1) @@ -574,6 +613,7 @@ def assertOneTimeInvoice(self, charges): invoice_type = 'one-time', ) + @unittest.skip('Skip until deleting customers is working') @clear_users def test_add_simple_one_time_invoice(self): charges = [{ @@ -584,6 +624,7 @@ def test_add_simple_one_time_invoice(self): self.assertOneTimeInvoice(charges) + @unittest.skip('Skip until deleting customers is working') @clear_users def test_add_one_time_invoice_with_description(self): charges = [{ @@ -595,7 +636,7 @@ def test_add_one_time_invoice_with_description(self): self.assertOneTimeInvoice(charges) - + @unittest.skip('Skip until deleting customers is working') @clear_users def test_add_one_time_invoice_with_multiple_charges(self): charges = [{ @@ -612,3 +653,23 @@ def test_add_one_time_invoice_with_multiple_charges(self): },] self.assertOneTimeInvoice(charges) + + def test_get_all_promotions(self): + ''' Test get all promotions. ''' + product = self.get_product() + promotions = product.get_all_promotions() + + self.assertEquals(2, len(promotions)) + for promotion in promotions: + assert promotion.coupons[0].get('code') in ('COUPON', 'COUPON2') + + def test_get_promotion(self): + ''' Test get a single promotion. ''' + product = self.get_product() + promotion = product.get_promotion('COUPON') + + self.assertEqual(unicode(promotion), 'Coupon (COUPON)') + self.assertEqual(promotion.name, 'Coupon') + self.assertEqual(promotion.coupons[0].get('code'), 'COUPON') + self.assertEqual(promotion.incentives[0].get('percentage'), '10') + self.assertEqual(promotion.incentives[0].get('expiration_datetime'), None) From 3a25cdf50c2c465fd1fd037426ffb3166c8836fd Mon Sep 17 00:00:00 2001 From: Ryan Johnston Date: Thu, 27 Aug 2015 13:33:26 -0400 Subject: [PATCH 19/24] Update readme.rst --- tests/readme.rst | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/readme.rst b/tests/readme.rst index 59bb58e..325ac3d 100644 --- a/tests/readme.rst +++ b/tests/readme.rst @@ -58,6 +58,7 @@ The following promotions are required for unit tests: +----------------+---------------+--------+-----------+ Be sure to turn on the native gateway credit card option in Configuration > Product settings > Gateway Settings. +Be sure to turn on the paypal option in Configuration > Product settings > Gateway Settings or Quick Setup > Billing solution. I checked the "Use standard payments (PayPal account to PayPal account)" checkbox. Config ====== From 1824bcfa7585a1ebc72482ef0f0e66d9147aad54 Mon Sep 17 00:00:00 2001 From: Ryan Johnston Date: Thu, 27 Aug 2015 15:11:56 -0400 Subject: [PATCH 20/24] parse_promotions is not needed because it is not used. --- sharpy/parsers.py | 9 --------- 1 file changed, 9 deletions(-) diff --git a/sharpy/parsers.py b/sharpy/parsers.py index 7183c1f..52c7aa4 100644 --- a/sharpy/parsers.py +++ b/sharpy/parsers.py @@ -340,16 +340,7 @@ def parse_xml(self, xml_str): for promotion_xml in promotions_xml: promotion = self.parse_promotion(promotion_xml) promotions.append(promotion) - - return promotions - def parse_promotions(self, promotions_element): - promotions = [] - - if promotions_element is not None: - for promotion_element in promotions_element: - promotions.append(self.parse_promotion(promotion_element)) - return promotions def parse_promotion(self, promotion_element): From 84088308414b5da7024ff4a883860d1832e5a206 Mon Sep 17 00:00:00 2001 From: Ryan Johnston Date: Thu, 27 Aug 2015 15:12:45 -0400 Subject: [PATCH 21/24] The convention used in the other classes is to include a __repr__. Include a __repr__ for Promotion. --- sharpy/product.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/sharpy/product.py b/sharpy/product.py index f7810b9..817260d 100644 --- a/sharpy/product.py +++ b/sharpy/product.py @@ -810,6 +810,9 @@ def __init__(self, id=None, code=None, name=None, description=None, super(Promotion, self).__init__() + def __repr__(self): + return u'Promotion: %s (%s)' % (self.name, self.code,) + def __unicode__(self): return u'{0} ({1})'.format(self.name, self.code) From 721cd389db642be17e4b8f4c4d6b4945cbadb7c2 Mon Sep 17 00:00:00 2001 From: Ryan Johnston Date: Thu, 27 Aug 2015 15:14:56 -0400 Subject: [PATCH 22/24] Also consider clearing customers a failure if success is not in the results. Related to a specific cheddar bug where it only returns . --- tests/testing_tools/utils.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/testing_tools/utils.py b/tests/testing_tools/utils.py index faa96bf..0b5d616 100644 --- a/tests/testing_tools/utils.py +++ b/tests/testing_tools/utils.py @@ -16,5 +16,5 @@ def clear_users(): response, content = h.request(url, 'POST') - if response.status != 200: - raise Exception('Could not clear users. Recieved a response of %s %s ' % (response.status, response.reason)) + if response.status != 200 or 'success' not in content: + raise Exception('Could not clear users. Recieved a response of %s %s \n %s' % (response.status, response.reason, content)) From 6e22417789a4e4b25477f6fe0bb777bd9abd43f4 Mon Sep 17 00:00:00 2001 From: Ryan Johnston Date: Thu, 27 Aug 2015 15:16:39 -0400 Subject: [PATCH 23/24] Remove skipped decorator from tests. --- tests/client_tests.py | 3 --- 1 file changed, 3 deletions(-) diff --git a/tests/client_tests.py b/tests/client_tests.py index 10432ba..f3e612f 100644 --- a/tests/client_tests.py +++ b/tests/client_tests.py @@ -106,7 +106,6 @@ def test_make_request_not_found(self): client = self.get_client() client.make_request(path) - @unittest.skip('Skip until deleting customers is working') @clear_users def test_post_request(self): path = 'customers/new' @@ -120,7 +119,6 @@ def test_post_request(self): client = self.get_client() client.make_request(path, data=data) - @unittest.skip('Skip until deleting customers is working') def generate_error_response(self, auxcode=None, path=None, params=None, **overrides): ''' Creates a request to cheddar which should return an error @@ -244,7 +242,6 @@ def test_format_datetime_with_now(self): self.assertEquals(expected, result) - @unittest.skip('I can not figure this out.') @clear_users def test_chedder_update_customer_error(self): """ From 77af8cc6b32313375de32b8b4248646b2332a021 Mon Sep 17 00:00:00 2001 From: Ryan Johnston Date: Thu, 27 Aug 2015 15:18:04 -0400 Subject: [PATCH 24/24] Add unittests for __repr__ and __unicode__ on the Promotion object. Remove the skip test decorator from unit tests. Add work around for duplicate transaction failures. --- tests/product_tests.py | 84 ++++++++++++++++-------------------------- 1 file changed, 32 insertions(+), 52 deletions(-) diff --git a/tests/product_tests.py b/tests/product_tests.py index c0852e5..b834c8d 100644 --- a/tests/product_tests.py +++ b/tests/product_tests.py @@ -1,3 +1,6 @@ +import random +import string + from copy import copy from datetime import date, datetime, timedelta from decimal import Decimal @@ -116,6 +119,13 @@ def test_plan_initial_bill_date(self): def get_customer(self, **kwargs): customer_data = copy(self.customer_defaults) + # We need to make unique customers with the same data. + # Cheddar recomends we pass a garbage field. + # http://support.cheddargetter.com/discussions/problems/8342-duplicate-post + # http://support.cheddargetter.com/kb/api-8/error-handling#duplicate + random_string = ''.join(random.SystemRandom().choice( + string.ascii_uppercase + string.digits) for _ in range(5)) + customer_data.update({'notes': random_string}) customer_data.update(kwargs) product = self.get_product() @@ -138,72 +148,58 @@ def get_customer_with_items(self, **kwargs): return customer - @unittest.skip('Skip until deleting customers is working') @clear_users def test_simple_create_customer(self): self.get_customer() - @unittest.skip('Skip until deleting customers is working') @clear_users def test_create_customer_with_company(self): self.get_customer(company='Test Co') - @unittest.skip('Skip until deleting customers is working') @clear_users def test_create_customer_with_meta_data(self): self.get_customer(meta_data = {'key_1': 'value_1', 'key2': 'value_2'}) - @unittest.skip('Skip until deleting customers is working') @clear_users def test_create_customer_with_true_vat_exempt(self): self.get_customer(is_vat_exempt=True) - @unittest.skip('Skip until deleting customers is working') @clear_users def test_create_customer_with_false_vat_exempt(self): self.get_customer(is_vat_exempt=False) - @unittest.skip('Skip until deleting customers is working') @clear_users def test_create_customer_with_vat_number(self): self.get_customer(vat_number=12345) - @unittest.skip('Skip until deleting customers is working') @clear_users def test_create_customer_with_notes(self): self.get_customer(notes='This is a test note!') - @unittest.skip('Skip until deleting customers is working') @clear_users def test_create_customer_with_first_contact_datetime(self): self.get_customer(first_contact_datetime=datetime.now()) - @unittest.skip('Skip until deleting customers is working') @clear_users def test_create_customer_with_referer(self): self.get_customer(referer='http://saaspire.com/test.html') - @unittest.skip('Skip until deleting customers is working') @clear_users def test_create_customer_with_campaign_term(self): self.get_customer(campaign_term='testing') - @unittest.skip('Skip until deleting customers is working') @clear_users def test_create_customer_with_campaign_name(self): self.get_customer(campaign_name='testing') - @unittest.skip('Skip until deleting customers is working') @clear_users def test_create_customer_with_campaign_source(self): self.get_customer(campaign_source='testing') - @unittest.skip('Skip until deleting customers is working') @clear_users def test_create_customer_with_campaign_content(self): self.get_customer(campaign_content='testing') - @unittest.skip('Skip until deleting customers is working') @clear_users def test_create_customer_with_initial_bill_date(self): initial_bill_date = datetime.utcnow() + timedelta(days=60) @@ -216,12 +212,10 @@ def test_create_customer_with_initial_bill_date(self): diff = initial_bill_date.date() - real_bill_date.date() self.assertLessEqual(diff.days, 1) - @unittest.skip('Skip until deleting customers is working') @clear_users def test_create_paid_customer(self): self.get_customer(**self.paid_defaults) - @unittest.skip('Skip until deleting customers is working') @clear_users def test_create_paid_customer_with_charges(self): data = copy(self.paid_defaults) @@ -231,7 +225,6 @@ def test_create_paid_customer_with_charges(self): data['charges'] = charges self.get_customer(**data) - @unittest.skip('Skip until deleting customers is working') @clear_users def test_create_paid_customer_with_decimal_charges(self): data = copy(self.paid_defaults) @@ -241,7 +234,6 @@ def test_create_paid_customer_with_decimal_charges(self): data['charges'] = charges self.get_customer(**data) - @unittest.skip('Skip until deleting customers is working') @clear_users def test_create_paid_customer_with_items(self): data = copy(self.paid_defaults) @@ -252,7 +244,6 @@ def test_create_paid_customer_with_items(self): data['plan_code'] = 'TRACKED_MONTHLY' self.get_customer(**data) - @unittest.skip('Skip until deleting customers is working') @clear_users def test_create_paid_customer_with_decimal_quantity_items(self): data = copy(self.paid_defaults) @@ -263,13 +254,11 @@ def test_create_paid_customer_with_decimal_quantity_items(self): data['plan_code'] = 'TRACKED_MONTHLY' self.get_customer(**data) - @unittest.skip('Skip until deleting customers is working') @clear_users def test_create_paypal_customer(self): data = copy(self.paypal_defaults) self.get_customer(**data) - @unittest.skip('Skip until deleting customers is working') @clear_users def test_update_paypal_customer(self): data = copy(self.paypal_defaults) @@ -280,7 +269,6 @@ def test_update_paypal_customer(self): cancel_url='http://example.com/update-cancel/', ) - @unittest.skip('Skip until deleting customers is working') @clear_users def test_customer_repr(self): customer = self.get_customer() @@ -290,7 +278,6 @@ def test_customer_repr(self): self.assertEquals(expected, result) - @unittest.skip('Skip until deleting customers is working') @clear_users def test_subscription_repr(self): customer = self.get_customer() @@ -301,7 +288,6 @@ def test_subscription_repr(self): self.assertIn(expected, result) - @unittest.skip('Skip until deleting customers is working') @clear_users def test_pricing_plan_repr(self): customer = self.get_customer() @@ -313,7 +299,6 @@ def test_pricing_plan_repr(self): self.assertEquals(expected, result) - @unittest.skip('Skip until deleting customers is working') @clear_users def test_item_repr(self): customer = self.get_customer_with_items() @@ -325,7 +310,6 @@ def test_item_repr(self): self.assertEquals(expected, result) - @unittest.skip('Duplicate transaction error. 6 seconds.') @clear_users def test_get_customers(self): customer1 = self.get_customer() @@ -340,10 +324,8 @@ def test_get_customers(self): product = self.get_product() fetched_customers = product.get_customers() - self.assertEquals(2, len(fetched_customers)) - @unittest.skip('Duplicate transaction error. 6 seconds.') @clear_users def test_get_customer(self): created_customer = self.get_customer() @@ -356,7 +338,6 @@ def test_get_customer(self): self.assertEquals(created_customer.last_name, fetched_customer.last_name) self.assertEquals(created_customer.email, fetched_customer.email) - @unittest.skip('Skip until deleting customers is working') @clear_users def test_simple_customer_update(self): new_name = 'Different' @@ -369,7 +350,6 @@ def test_simple_customer_update(self): fetched_customer = product.get_customer(code=customer.code) self.assertEquals(customer.first_name, fetched_customer.first_name) - @unittest.skip('Skip until deleting customers is working') @clear_users @raises(NotFound) def test_delete_customer(self): @@ -382,7 +362,7 @@ def test_delete_customer(self): customer.delete() fetched_customer = product.get_customer(code=customer.code) - @unittest.skip('Skip until deleting customers is working') + @clear_users def test_delete_all_customers(self): customer_1 = self.get_customer() @@ -397,7 +377,6 @@ def test_delete_all_customers(self): fetched_customers = product.get_customers() self.assertEquals(0, len(fetched_customers)) - @unittest.skip('Skip until deleting customers is working') @clear_users def test_cancel_subscription(self): customer = self.get_customer() @@ -426,22 +405,18 @@ def assert_increment(self, quantity=None): fetched_item = customer.subscription.items[item.code] self.assertEquals(item.quantity_used, fetched_item.quantity_used) - @unittest.skip('Skip until deleting customers is working') @clear_users def test_simple_increment(self): self.assert_increment() - @unittest.skip('Skip until deleting customers is working') @clear_users def test_int_increment(self): self.assert_increment(1) - @unittest.skip('Skip until deleting customers is working') @clear_users def test_float_increment(self): self.assert_increment(1.234) - @unittest.skip('Skip until deleting customers is working') @clear_users def test_decimal_increment(self): self.assert_increment(Decimal('1.234')) @@ -462,22 +437,18 @@ def assert_decrement(self, quantity=None): fetched_item = customer.subscription.items[item.code] self.assertEquals(item.quantity_used, fetched_item.quantity_used) - @unittest.skip('Skip until deleting customers is working') @clear_users def test_simple_decrement(self): self.assert_decrement() - @unittest.skip('Duplicate transaction error. 6 seconds.') @clear_users def test_int_decrement(self): self.assert_decrement(1) - @unittest.skip('Skip until deleting customers is working') @clear_users def test_float_decrement(self): self.assert_decrement(1.234) - @unittest.skip('Skip until deleting customers is working') @clear_users def test_decimal_decrement(self): self.assert_decrement(Decimal('1.234')) @@ -497,17 +468,14 @@ def assert_set(self, quantity): fetched_item = customer.subscription.items[item.code] self.assertEquals(item.quantity_used, fetched_item.quantity_used) - @unittest.skip('Duplicate transaction error. 6 seconds.') @clear_users def test_int_set(self): self.assert_set(1) - @unittest.skip('Skip until deleting customers is working') @clear_users def test_float_set(self): self.assert_set(1.234) - @unittest.skip('Skip until deleting customers is working') @clear_users def test_decimal_set(self): self.assert_set(Decimal('1.234')) @@ -548,27 +516,22 @@ def assert_charged(self, code, each_amount, quantity=None, self.assertEqual(quantity, fetched_charge['quantity']) self.assertEqual(description, fetched_charge['description']) - @unittest.skip('Skip until deleting customers is working') @clear_users def test_add_charge(self): self.assert_charged(code='TEST-CHARGE', each_amount=1, quantity=1) - @unittest.skip('Skip until deleting customers is working') @clear_users def test_add_float_charge(self): self.assert_charged(code='TEST-CHARGE', each_amount=2.3, quantity=2) - - @unittest.skip('Skip until deleting customers is working') + @clear_users def test_add_decimal_charge(self): self.assert_charged(code='TEST-CHARGE', each_amount=Decimal('2.3'), quantity=3) - @unittest.skip('Skip until deleting customers is working') @clear_users def test_add_charge_with_descriptions(self): self.assert_charged(code='TEST-CHARGE', each_amount=1, quantity=1, description="A test charge") - @unittest.skip('Skip until deleting customers is working') @clear_users def test_add_credit(self): self.assert_charged(code='TEST-CHARGE', each_amount=-1, quantity=1) @@ -613,7 +576,6 @@ def assertOneTimeInvoice(self, charges): invoice_type = 'one-time', ) - @unittest.skip('Skip until deleting customers is working') @clear_users def test_add_simple_one_time_invoice(self): charges = [{ @@ -624,7 +586,6 @@ def test_add_simple_one_time_invoice(self): self.assertOneTimeInvoice(charges) - @unittest.skip('Skip until deleting customers is working') @clear_users def test_add_one_time_invoice_with_description(self): charges = [{ @@ -636,7 +597,6 @@ def test_add_one_time_invoice_with_description(self): self.assertOneTimeInvoice(charges) - @unittest.skip('Skip until deleting customers is working') @clear_users def test_add_one_time_invoice_with_multiple_charges(self): charges = [{ @@ -673,3 +633,23 @@ def test_get_promotion(self): self.assertEqual(promotion.coupons[0].get('code'), 'COUPON') self.assertEqual(promotion.incentives[0].get('percentage'), '10') self.assertEqual(promotion.incentives[0].get('expiration_datetime'), None) + + def test_promotion_repr(self): + ''' Test the internal __repr___ method of Promotion. ''' + product = self.get_product() + promotion = product.get_promotion('COUPON') + + expected = 'Promotion: Coupon (COUPON)' + result = repr(promotion) + + self.assertEquals(expected, result) + + def test_promotion_unicode(self): + ''' Test the internal __unicode___ method of Promotion. ''' + product = self.get_product() + promotion = product.get_promotion('COUPON') + + expected = 'Coupon (COUPON)' + result = unicode(promotion) + + self.assertEquals(expected, result)