Adding more tests, finding more errors - again!

This commit is contained in:
Víðir Valberg Guðmundsson 2019-03-29 20:58:35 +01:00
parent 2ce2205bd3
commit c69bf46255
3 changed files with 177 additions and 77 deletions

View file

@ -17,7 +17,7 @@ class OrderQuerySet(QuerySet):
return self.filter(cancelled=False) return self.filter(cancelled=False)
def open(self): def open(self):
return self.filter(open__isnull=True) return self.filter(open__isnull=False)
def paid(self): def paid(self):
return self.filter(paid=True) return self.filter(paid=True)

View file

@ -5,7 +5,7 @@ from psycopg2.extras import DateTimeTZRange
from shop.forms import OrderProductRelationForm from shop.forms import OrderProductRelationForm
from utils.factories import UserFactory from utils.factories import UserFactory
from .factories import ProductFactory, OrderProductRelationFactory from .factories import ProductFactory, OrderProductRelationFactory, OrderFactory
class ProductAvailabilityTest(TestCase): class ProductAvailabilityTest(TestCase):
@ -111,7 +111,12 @@ class TestProductDetailView(TestCase):
self.product = ProductFactory() self.product = ProductFactory()
self.path = reverse("shop:product_detail", kwargs={"slug": self.product.slug}) self.path = reverse("shop:product_detail", kwargs={"slug": self.product.slug})
def test_product_is_available(self): def test_product_is_available_for_anonymous_user(self):
response = self.client.get(self.path)
self.assertEqual(response.status_code, 200)
def test_product_is_available_for_logged_in_user(self):
self.client.force_login(self.user) self.client.force_login(self.user)
response = self.client.get(self.path) response = self.client.get(self.path)
@ -180,3 +185,100 @@ class TestProductDetailView(TestCase):
self.product.category.save() self.product.category.save()
response = self.client.get(self.path) response = self.client.get(self.path)
self.assertEquals(response.status_code, 404) self.assertEquals(response.status_code, 404)
class TestOrderDetailView(TestCase):
def setUp(self):
self.user = UserFactory()
self.order = OrderFactory(user=self.user)
self.path = reverse('shop:order_detail', kwargs={'pk': self.order.pk})
# We are using a formset which means we have to include some "management form" data.
self.base_form_data = {
'form-TOTAL_FORMS': '1',
'form-INITIAL_FORMS': '1',
'form-MAX_NUM_FORMS': '',
}
def test_redirects_when_no_products(self):
self.client.force_login(self.user)
response = self.client.get(self.path)
self.assertEquals(response.status_code, 302)
self.assertRedirects(response, reverse('shop:index'))
def test_redirects_when_cancelled(self):
self.client.force_login(self.user)
OrderProductRelationFactory(order=self.order)
self.order.cancelled = True
self.order.save()
response = self.client.get(self.path)
self.assertEquals(response.status_code, 302)
self.assertRedirects(response, reverse('shop:index'))
def test_remove_product(self):
self.client.force_login(self.user)
OrderProductRelationFactory(order=self.order)
orp = OrderProductRelationFactory(order=self.order)
order = orp.order
data = self.base_form_data
data['remove_product'] = orp.pk
response = self.client.post(self.path, data=data)
self.assertEquals(response.status_code, 200)
order.refresh_from_db()
self.assertEquals(order.products.count(), 1)
def test_remove_last_product_cancels_order(self):
self.client.force_login(self.user)
orp = OrderProductRelationFactory(order=self.order)
order = orp.order
data = self.base_form_data
data['remove_product'] = orp.pk
response = self.client.post(self.path, data=data)
self.assertEquals(response.status_code, 302)
self.assertRedirects(response, reverse('shop:index'))
order.refresh_from_db()
self.assertTrue(order.cancelled)
def test_cancel_order(self):
self.client.force_login(self.user)
orp = OrderProductRelationFactory(order=self.order)
order = orp.order
data = self.base_form_data
data['cancel_order'] = None
response = self.client.post(self.path, data=data)
self.assertEquals(response.status_code, 302)
self.assertRedirects(response, reverse('shop:index'))
order.refresh_from_db()
self.assertTrue(order.cancelled)
class TestOrderListView(TestCase):
def test_order_list_view_as_logged_in(self):
user = UserFactory()
self.client.force_login(user)
path = reverse('shop:order_list')
response = self.client.get(path)
self.assertEquals(response.status_code, 200)

View file

@ -224,16 +224,18 @@ class ProductDetailView(FormView, DetailView):
def get_form_kwargs(self): def get_form_kwargs(self):
kwargs = super().get_form_kwargs() kwargs = super().get_form_kwargs()
kwargs['instance'] = self.opr if hasattr(self, 'opr'):
kwargs['instance'] = self.opr
return kwargs return kwargs
def get_initial(self): def get_initial(self):
if self.opr: if hasattr(self, 'opr'):
return {'quantity': self.opr.quantity} return {'quantity': self.opr.quantity}
return super().get_initial() return None
def get_context_data(self, **kwargs): def get_context_data(self, **kwargs):
if hasattr(self.opr, 'order'): # If the OrderProductRelation already exists it has a primary key in the database
if self.request.user.is_authenticated and self.opr.pk:
kwargs['already_in_order'] = True kwargs['already_in_order'] = True
return super().get_context_data(**kwargs) return super().get_context_data(**kwargs)
@ -241,7 +243,10 @@ class ProductDetailView(FormView, DetailView):
def dispatch(self, request, *args, **kwargs): def dispatch(self, request, *args, **kwargs):
self.object = self.get_object() self.object = self.get_object()
self.opr = None if not self.object.category.public:
# this product is not publicly available
raise Http404("Product not found")
if self.request.user.is_authenticated: if self.request.user.is_authenticated:
try: try:
self.opr = OrderProductRelation.objects.get( self.opr = OrderProductRelation.objects.get(
@ -255,31 +260,23 @@ class ProductDetailView(FormView, DetailView):
quantity=1, quantity=1,
) )
if not self.object.category.public:
# this product is not publicly available
raise Http404("Product not found")
return super(ProductDetailView, self).dispatch( return super(ProductDetailView, self).dispatch(
request, *args, **kwargs request, *args, **kwargs
) )
def form_valid(self, form): def form_valid(self, form):
product = self.get_object() opr = form.save(commit=False)
quantity = form.cleaned_data.get('quantity')
if not hasattr(self.opr, 'order'): if not opr.pk:
self.opr.order = Order.objects.create( opr.order, _ = Order.objects.get_or_create(user=self.request.user, open=True, cancelled=False)
user=self.request.user,
)
self.opr.quantity = quantity opr.save()
self.opr.save()
messages.info( messages.info(
self.request, self.request,
'{}x {} has been added to your order.'.format( '{}x {} has been added to your order.'.format(
quantity, opr.quantity,
product.name opr.product.name
) )
) )
@ -329,7 +326,7 @@ class OrderDetailView(LoginRequiredMixin, EnsureUserOwnsOrderMixin, EnsureOrderH
return HttpResponseRedirect(reverse_lazy('shop:index')) return HttpResponseRedirect(reverse_lazy('shop:index'))
# Then see if the user is cancelling the order. # Then see if the user is cancelling the order.
if 'cancel_order' in request.POST: elif 'cancel_order' in request.POST:
order.mark_as_cancelled() order.mark_as_cancelled()
messages.info(request, 'Order cancelled!') messages.info(request, 'Order cancelled!')
return HttpResponseRedirect(reverse_lazy('shop:index')) return HttpResponseRedirect(reverse_lazy('shop:index'))
@ -338,66 +335,67 @@ class OrderDetailView(LoginRequiredMixin, EnsureUserOwnsOrderMixin, EnsureOrderH
# so from now on we do stuff that require us to check stock. # so from now on we do stuff that require us to check stock.
# We use a formset for this to be able to display exactly # We use a formset for this to be able to display exactly
# which product is not in stock if that is the case. # which product is not in stock if that is the case.
formset = OrderProductRelationFormSet( else:
request.POST, formset = OrderProductRelationFormSet(
queryset=OrderProductRelation.objects.filter(order=order), request.POST,
) queryset=OrderProductRelation.objects.filter(order=order),
# If the formset is not valid it means that we cannot fulfill the order, so return and inform the user.
if not formset.is_valid():
messages.error(
request,
"Some of the products you are ordering are out of stock. Review the order and try again."
)
return self.render_to_response(
self.get_context_data(order_product_formset=formset)
) )
# No stock issues, proceed to check if the user is updating the order. # If the formset is not valid it means that we cannot fulfill the order, so return and inform the user.
if 'update_order' in request.POST: if not formset.is_valid():
# We have already made sure the formset is valid, so just save it to update quantities. messages.error(
formset.save() request,
"Some of the products you are ordering are out of stock. Review the order and try again."
order.customer_comment = request.POST.get('customer_comment') or '' )
order.invoice_address = request.POST.get('invoice_address') or '' return self.render_to_response(
order.save() self.get_context_data(order_product_formset=formset)
# Then at last see if the user is paying for the order.
payment_method = request.POST.get('payment_method')
if payment_method in order.PAYMENT_METHODS:
if not request.POST.get('accept_terms'):
messages.error(request, "You need to accept the general terms and conditions before you can continue!")
return HttpResponseRedirect(
reverse_lazy('shop:order_detail', kwargs={'pk': order.pk})
) )
# Set payment method and mark the order as closed # No stock issues, proceed to check if the user is updating the order.
order.payment_method = payment_method if 'update_order' in request.POST:
order.open = None # We have already made sure the formset is valid, so just save it to update quantities.
order.customer_comment = request.POST.get('customer_comment') or '' formset.save()
order.invoice_address = request.POST.get('invoice_address') or ''
order.save()
reverses = { order.customer_comment = request.POST.get('customer_comment') or ''
Order.CREDIT_CARD: reverse_lazy( order.invoice_address = request.POST.get('invoice_address') or ''
'shop:epay_form', order.save()
kwargs={'pk': order.id}
),
Order.BLOCKCHAIN: reverse_lazy(
'shop:coinify_pay',
kwargs={'pk': order.id}
),
Order.BANK_TRANSFER: reverse_lazy(
'shop:bank_transfer',
kwargs={'pk': order.id}
),
Order.CASH: reverse_lazy(
'shop:cash',
kwargs={'pk': order.id}
)
}
return HttpResponseRedirect(reverses[payment_method]) # Then at last see if the user is paying for the order.
payment_method = request.POST.get('payment_method')
if payment_method in order.PAYMENT_METHODS:
if not request.POST.get('accept_terms'):
messages.error(request, "You need to accept the general terms and conditions before you can continue!")
return HttpResponseRedirect(
reverse_lazy('shop:order_detail', kwargs={'pk': order.pk})
)
# Set payment method and mark the order as closed
order.payment_method = payment_method
order.open = None
order.customer_comment = request.POST.get('customer_comment') or ''
order.invoice_address = request.POST.get('invoice_address') or ''
order.save()
reverses = {
Order.CREDIT_CARD: reverse_lazy(
'shop:epay_form',
kwargs={'pk': order.id}
),
Order.BLOCKCHAIN: reverse_lazy(
'shop:coinify_pay',
kwargs={'pk': order.id}
),
Order.BANK_TRANSFER: reverse_lazy(
'shop:bank_transfer',
kwargs={'pk': order.id}
),
Order.CASH: reverse_lazy(
'shop:cash',
kwargs={'pk': order.id}
)
}
return HttpResponseRedirect(reverses[payment_method])
return super(OrderDetailView, self).get(request, *args, **kwargs) return super(OrderDetailView, self).get(request, *args, **kwargs)