diff --git a/.gitignore b/.gitignore index 0d20b64..9c57cf8 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1,6 @@ +# Byte-compiled *.pyc +__pycache__/ + +# Packaging +django_carton.egg-info/ diff --git a/carton/tests/settings.py b/carton/tests/settings.py index 1cda748..44dd4a6 100644 --- a/carton/tests/settings.py +++ b/carton/tests/settings.py @@ -14,6 +14,11 @@ 'carton.tests', ) +MIDDLEWARE_CLASSES = ( + 'django.contrib.sessions.middleware.SessionMiddleware', + 'django.middleware.common.CommonMiddleware', +) + ROOT_URLCONF = 'carton.tests.urls' SECRET_KEY = 'any-key' diff --git a/carton/tests/tests.py b/carton/tests/tests.py index 6895911..5e75844 100644 --- a/carton/tests/tests.py +++ b/carton/tests/tests.py @@ -1,117 +1,176 @@ +from importlib import import_module + +from django.conf import settings from django.core.urlresolvers import reverse -from django.test import TestCase +from django.test import RequestFactory, TestCase + +from carton.cart import Cart from carton.tests.models import Product +from carton.tests.views import show try: from django.test import override_settings except ImportError: - from django.test.utils import override_settings + from django.test.utils import override_settings class CartTests(TestCase): def setUp(self): + engine = import_module(settings.SESSION_ENGINE) + self.session = engine.SessionStore() + self.session.save() + self.client.cookies[settings.SESSION_COOKIE_NAME] = self.session.session_key + + self.factory = RequestFactory() + + self.cart = Cart(self.session) + self.deer = Product.objects.create(name='deer', price=10.0, custom_id=1) self.moose = Product.objects.create(name='moose', price=20.0, custom_id=2) - self.url_add = reverse('carton-tests-add') - self.url_show = reverse('carton-tests-show') - self.url_remove = reverse('carton-tests-remove') - self.url_remove_single = reverse('carton-tests-remove-single') - self.url_quantity = reverse('carton-tests-set-quantity') - self.url_clear = reverse('carton-tests-clear') - self.deer_data = {'product_id': self.deer.pk} - self.moose_data = {'product_id': self.moose.pk} + + def show_response(self): + """ + Utility method to return a response from the `show` view. + """ + request = self.factory.get(reverse('carton-tests-show')) + request.session = self.session + + return show(request) def test_product_is_added(self): - self.client.post(self.url_add, self.deer_data) - response = self.client.get(self.url_show) - self.assertContains(response, '1 deer for $10.0') + """ + Can a product be added to the cart? + """ + self.cart.add(self.deer, 10.00, 1) + self.session.save() + + self.assertContains(self.show_response(), '1 deer for $10.0') def test_multiple_products_are_added(self): - self.client.post(self.url_add, self.deer_data) - self.client.post(self.url_add, self.moose_data) - response = self.client.get(self.url_show) + """ + Can multiple products be added to the cart? + """ + self.cart.add(self.deer, 10.00, 1) + self.cart.add(self.moose, 20.00, 1) + self.session.save() + + response = self.show_response() + self.assertContains(response, '1 deer for $10.0') self.assertContains(response, '1 moose for $20.0') def test_stale_item_is_removed_from_cart(self): - # Items that are not anymore reference in the database should not be kept in cart. - self.client.post(self.url_add, self.deer_data) - self.client.post(self.url_add, self.moose_data) - response = self.client.get(self.url_show) + """ + Are items which are not in the database kept out of the cart? + """ + self.cart.add(self.deer, 10.00, 1) + self.cart.add(self.moose, 20.00, 1) + self.session.save() + + response = self.show_response() + self.assertContains(response, 'deer') self.assertContains(response, 'moose') + self.deer.delete() - response = self.client.get(self.url_show) + + response = self.show_response() + self.assertNotContains(response, 'deer') self.assertContains(response, 'moose') def test_quantity_increases(self): - self.client.post(self.url_add, self.deer_data) - self.deer_data['quantity'] = 2 - self.client.post(self.url_add, self.deer_data) - response = self.client.get(self.url_show) - self.assertContains(response, '3 deer') + """ + Do multiple calls to `add` increase the quantity in the cart? + """ + self.cart.add(self.deer, 10.00, 1) + self.cart.add(self.deer, 10.00, 2) + self.session.save() + + self.assertContains(self.show_response(), '3 deer') def test_items_are_counted_properly(self): - self.deer_data['quantity'] = 2 - self.client.post(self.url_add, self.deer_data) - self.client.post(self.url_add, self.moose_data) - response = self.client.get(self.url_show) + """ + Are items in the cart counted correctly? + """ + self.cart.add(self.deer, 10.00, 2) + self.cart.add(self.moose, 20.00, 1) + self.session.save() + + response = self.show_response() + self.assertContains(response, 'items count: 3') self.assertContains(response, 'unique count: 2') - def test_price_is_updated(self): - # Let's give a discount: $1.5/product. That's handled on the test views. - self.deer_data['quantity'] = 2 - self.deer_data['discount'] = 1.5 - self.client.post(self.url_add, self.deer_data) - response = self.client.get(self.url_show) - # subtotal = 10*2 - 1.5*2 - self.assertContains(response, '2 deer for $17.0') - def test_products_are_removed_all_together(self): - self.deer_data['quantity'] = 3 - self.client.post(self.url_add, self.deer_data) - self.client.post(self.url_add, self.moose_data) - remove_data = {'product_id': self.deer.pk} - self.client.post(self.url_remove, remove_data) - response = self.client.get(self.url_show) + """ + Can all products of a single type be removed? + """ + self.cart.add(self.deer, 10.00, 3) + self.cart.add(self.moose, 20.00, 1) + self.session.save() + + self.cart.remove(self.deer) + + response = self.show_response() + self.assertNotContains(response, 'deer') self.assertContains(response, 'moose') def test_single_product_is_removed(self): - self.deer_data['quantity'] = 3 - self.client.post(self.url_add, self.deer_data) - remove_data = {'product_id': self.deer.pk} - self.client.post(self.url_remove_single, remove_data) - response = self.client.get(self.url_show) - self.assertContains(response, '2 deer') + """ + Can a single instance of a product be removed? + """ + self.cart.add(self.deer, 10.00, 3) + self.session.save() + + self.cart.remove_single(self.deer) + + self.assertContains(self.show_response(), '2 deer') def test_quantity_is_overwritten(self): - self.deer_data['quantity'] = 3 - self.client.post(self.url_add, self.deer_data) - self.deer_data['quantity'] = 4 - self.client.post(self.url_quantity, self.deer_data) - response = self.client.get(self.url_show) - self.assertContains(response, '4 deer') + """ + Can an items quantity be changed? + """ + self.cart.add(self.deer, 10.00, 3) + self.session.save() + + self.cart.set_quantity(self.deer, 4) + + self.assertContains(self.show_response(), '4 deer') def test_cart_items_are_cleared(self): - self.client.post(self.url_add, self.deer_data) - self.client.post(self.url_add, self.moose_data) - self.client.post(self.url_clear) - response = self.client.get(self.url_show) + """ + Can a cart be entirely cleared? + """ + self.cart.add(self.deer, 10.00, 1) + self.cart.add(self.moose, 20.00, 1) + self.cart.clear() + self.session.save() + + response = self.show_response() + self.assertNotContains(response, 'deer') self.assertNotContains(response, 'moose') @override_settings(CART_PRODUCT_LOOKUP={'price__gt': 1}) def test_custom_product_filter_are_applied(self): - # We modify the queryset to exclude some products. For these excluded - # we should not be able to add them in the cart. - exclude = Product.objects.create(name='EXCLUDE', price=0.99, custom_id=100) - exclude_data = {'product_id': exclude.pk} - self.client.post(self.url_add, self.deer_data) - self.client.post(self.url_add, exclude_data) - response = self.client.get(self.url_show) + """ + We modify the cart queryset to exclude some products. We + should not be able to add excluded products to the cart. + """ + exclude = Product.objects.create( + name='EXCLUDED', + price=0.99, + custom_id=100, + ) + + self.cart.add(self.deer, 10.00, 1) + self.cart.add(exclude, exclude.price, 1) + self.session.save() + + response = self.show_response() + self.assertNotContains(response, 'EXCLUDE') self.assertContains(response, 'deer') diff --git a/carton/tests/urls.py b/carton/tests/urls.py index b7a75a5..9adfe67 100644 --- a/carton/tests/urls.py +++ b/carton/tests/urls.py @@ -1,11 +1,7 @@ from django.conf.urls import url, patterns -urlpatterns = patterns('carton.tests.views', +urlpatterns = patterns( + 'carton.tests.views', url(r'^show/$', 'show', name='carton-tests-show'), - url(r'^add/$', 'add', name='carton-tests-add'), - url(r'^remove/$', 'remove', name='carton-tests-remove'), - url(r'^remove-single/$', 'remove_single', name='carton-tests-remove-single'), - url(r'^clear/$', 'clear', name='carton-tests-clear'), - url(r'^set-quantity/$', 'set_quantity', name='carton-tests-set-quantity'), ) diff --git a/carton/tests/views.py b/carton/tests/views.py index 4bb865d..386c1ed 100644 --- a/carton/tests/views.py +++ b/carton/tests/views.py @@ -1,56 +1,25 @@ from django.http import HttpResponse from carton.cart import Cart -from carton.tests.models import Product def show(request): cart = Cart(request.session) - response = '' - for item in cart.items: - response += '%(quantity)s %(item)s for $%(price)s\n' % { - 'quantity': item.quantity, - 'item': item.product.name, - 'price': item.subtotal, - } - response += 'items count: %s\n' % cart.count - response += 'unique count: %s\n' % cart.unique_count - return HttpResponse(response) - - -def add(request): - cart = Cart(request.session) - product = Product.objects.get(pk=request.POST.get('product_id')) - quantity = request.POST.get('quantity', 1) - discount = request.POST.get('discount', 0) - price = product.price - float(discount) - cart.add(product, price, quantity) - return HttpResponse() + template = """ + {} {} for ${} + items count: {} + unique count: {} + """ + + response = ''.join( + template.format( + item.quantity, + item.product.name, + item.subtotal, + cart.count, + cart.unique_count, + ) for item in cart.items + ) -def remove(request): - cart = Cart(request.session) - product = Product.objects.get(pk=request.POST.get('product_id')) - cart.remove(product) - return HttpResponse() - - -def remove_single(request): - cart = Cart(request.session) - product = Product.objects.get(pk=request.POST.get('product_id')) - cart.remove_single(product) - return HttpResponse() - - -def clear(request): - cart = Cart(request.session) - cart.clear() - return HttpResponse() - - -def set_quantity(request): - cart = Cart(request.session) - product = Product.objects.get(pk=request.POST.get('product_id')) - quantity = request.POST.get('quantity') - cart.set_quantity(product, quantity) - return HttpResponse() + return HttpResponse(response)