Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1 +1,6 @@
# Byte-compiled
*.pyc
__pycache__/

# Packaging
django_carton.egg-info/
5 changes: 5 additions & 0 deletions carton/tests/settings.py
Original file line number Diff line number Diff line change
Expand Up @@ -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'
Expand Down
195 changes: 127 additions & 68 deletions carton/tests/tests.py
Original file line number Diff line number Diff line change
@@ -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')
8 changes: 2 additions & 6 deletions carton/tests/urls.py
Original file line number Diff line number Diff line change
@@ -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'),
)
63 changes: 16 additions & 47 deletions carton/tests/views.py
Original file line number Diff line number Diff line change
@@ -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)