feat: added tests for wishlist
This commit is contained in:
+3
-1
@@ -10,7 +10,9 @@ class ProductFilter(django_filters.FilterSet):
|
|||||||
field_name="name", lookup_expr="icontains", label=_("Nombre")
|
field_name="name", lookup_expr="icontains", label=_("Nombre")
|
||||||
)
|
)
|
||||||
tags = django_filters.BaseInFilter(field_name="tags", label=_("Etiquetas"))
|
tags = django_filters.BaseInFilter(field_name="tags", label=_("Etiquetas"))
|
||||||
category = django_filters.BaseInFilter(field_name="categories", label=_("Categorías"))
|
category = django_filters.BaseInFilter(
|
||||||
|
field_name="categories", label=_("Categorías")
|
||||||
|
)
|
||||||
price_lt = django_filters.NumberFilter(method="filter_price_lt")
|
price_lt = django_filters.NumberFilter(method="filter_price_lt")
|
||||||
price_gt = django_filters.NumberFilter(method="filter_price_gt")
|
price_gt = django_filters.NumberFilter(method="filter_price_gt")
|
||||||
o = OrderingFilter(
|
o = OrderingFilter(
|
||||||
|
|||||||
@@ -1,9 +1,10 @@
|
|||||||
# Generated by Django 5.1.3 on 2024-12-31 09:48
|
# Generated by Django 5.1.3 on 2024-12-31 09:48
|
||||||
|
|
||||||
|
import uuid
|
||||||
|
from decimal import Decimal
|
||||||
|
|
||||||
import django.db.models.deletion
|
import django.db.models.deletion
|
||||||
import django.utils.timezone
|
import django.utils.timezone
|
||||||
import uuid
|
|
||||||
from decimal import Decimal
|
|
||||||
from django.conf import settings
|
from django.conf import settings
|
||||||
from django.db import migrations, models
|
from django.db import migrations, models
|
||||||
|
|
||||||
|
|||||||
+29
-10
@@ -37,11 +37,26 @@ class Tag(models.Model):
|
|||||||
|
|
||||||
class ProductCategory(models.Model):
|
class ProductCategory(models.Model):
|
||||||
name = models.CharField(max_length=32)
|
name = models.CharField(max_length=32)
|
||||||
parent = models.ForeignKey('shop.ProductCategory', on_delete=models.SET_NULL, null=True, blank=True, verbose_name=_('categoría padre'))
|
parent = models.ForeignKey(
|
||||||
promoted = models.BooleanField(default=False, verbose_name=_('promocionada'))
|
"shop.ProductCategory",
|
||||||
hidden = models.BooleanField(default=False, verbose_name=_('oculta'))
|
on_delete=models.SET_NULL,
|
||||||
show_in_navbar = models.BooleanField(default=False, verbose_name=_('mostrar en cabecera'))
|
null=True,
|
||||||
slug = models.SlugField(max_length=48, blank=True, default="", verbose_name=_("slug"), unique=True, db_index=True)
|
blank=True,
|
||||||
|
verbose_name=_("categoría padre"),
|
||||||
|
)
|
||||||
|
promoted = models.BooleanField(default=False, verbose_name=_("promocionada"))
|
||||||
|
hidden = models.BooleanField(default=False, verbose_name=_("oculta"))
|
||||||
|
show_in_navbar = models.BooleanField(
|
||||||
|
default=False, verbose_name=_("mostrar en cabecera")
|
||||||
|
)
|
||||||
|
slug = models.SlugField(
|
||||||
|
max_length=48,
|
||||||
|
blank=True,
|
||||||
|
default="",
|
||||||
|
verbose_name=_("slug"),
|
||||||
|
unique=True,
|
||||||
|
db_index=True,
|
||||||
|
)
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
return self.name
|
return self.name
|
||||||
@@ -89,7 +104,9 @@ class Product(TimestampedModel):
|
|||||||
"files.FileUpload", blank=True, verbose_name=_("imágenes")
|
"files.FileUpload", blank=True, verbose_name=_("imágenes")
|
||||||
)
|
)
|
||||||
tags = models.ManyToManyField("shop.Tag", blank=True, verbose_name=_("etiquetas"))
|
tags = models.ManyToManyField("shop.Tag", blank=True, verbose_name=_("etiquetas"))
|
||||||
categories = models.ManyToManyField("shop.ProductCategory", blank=True, verbose_name=_("categorías"))
|
categories = models.ManyToManyField(
|
||||||
|
"shop.ProductCategory", blank=True, verbose_name=_("categorías")
|
||||||
|
)
|
||||||
brand = models.ForeignKey(
|
brand = models.ForeignKey(
|
||||||
"shop.Brand",
|
"shop.Brand",
|
||||||
blank=True,
|
blank=True,
|
||||||
@@ -504,9 +521,11 @@ class ShippingMethod(models.Model):
|
|||||||
|
|
||||||
|
|
||||||
class WishlistedProduct(TimestampedModel):
|
class WishlistedProduct(TimestampedModel):
|
||||||
user = models.ForeignKey(User, on_delete=models.CASCADE, verbose_name=_('usuario'))
|
user = models.ForeignKey(User, on_delete=models.CASCADE, verbose_name=_("usuario"))
|
||||||
product = models.ForeignKey('shop.Product', on_delete=models.CASCADE, verbose_name=_('producto'))
|
product = models.ForeignKey(
|
||||||
|
"shop.Product", on_delete=models.CASCADE, verbose_name=_("producto")
|
||||||
|
)
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
verbose_name = _('productos deseados')
|
verbose_name = _("productos deseados")
|
||||||
verbose_name_plural = _('productos deseados')
|
verbose_name_plural = _("productos deseados")
|
||||||
|
|||||||
@@ -4,7 +4,9 @@ from web.models import WebSettings
|
|||||||
|
|
||||||
def web_settings(request):
|
def web_settings(request):
|
||||||
settings = WebSettings.load()
|
settings = WebSettings.load()
|
||||||
navbar_categories = ProductCategory.objects.filter(hidden=False, show_in_navbar=True)
|
navbar_categories = ProductCategory.objects.filter(
|
||||||
|
hidden=False, show_in_navbar=True
|
||||||
|
)
|
||||||
|
|
||||||
return {
|
return {
|
||||||
"logo": settings.logo.url if settings.logo else "",
|
"logo": settings.logo.url if settings.logo else "",
|
||||||
|
|||||||
@@ -13,5 +13,7 @@ class TestCategoryView(TestCase, CreateProductsMixin):
|
|||||||
category = ProductCategory.objects.create(
|
category = ProductCategory.objects.create(
|
||||||
name="category 1", show_in_navbar=True, hidden=False
|
name="category 1", show_in_navbar=True, hidden=False
|
||||||
)
|
)
|
||||||
response = self.client.get(reverse("web:category_view", kwargs={"slug": category.slug}))
|
response = self.client.get(
|
||||||
|
reverse("web:category_view", kwargs={"slug": category.slug})
|
||||||
|
)
|
||||||
assert response.status_code == 200
|
assert response.status_code == 200
|
||||||
|
|||||||
@@ -0,0 +1,56 @@
|
|||||||
|
from django.contrib.auth.models import User
|
||||||
|
from django.test import TestCase
|
||||||
|
from django.urls import reverse
|
||||||
|
|
||||||
|
from shop.models import Cart, CartItem, WishlistedProduct
|
||||||
|
from shop.tests.mixins import CreateProductsMixin
|
||||||
|
from web.settings import ANONYMOUS_CART_ID_COOKIE_NAME
|
||||||
|
|
||||||
|
|
||||||
|
class TestWishlist(TestCase, CreateProductsMixin):
|
||||||
|
def setUp(self):
|
||||||
|
self.product = self.create_product()
|
||||||
|
self.user = User.objects.create_user("vader", "darth@vader.com", "ihatesand")
|
||||||
|
|
||||||
|
def test_logged_user_wishlist_button_for_non_wishlisted_product(self):
|
||||||
|
assert WishlistedProduct.objects.count() == 0
|
||||||
|
self.client.force_login(self.user)
|
||||||
|
response = self.client.get(
|
||||||
|
reverse("web:wishlist_button", kwargs={"pk": self.product.pk})
|
||||||
|
)
|
||||||
|
assert response.status_code == 200
|
||||||
|
|
||||||
|
def test_logged_user_wishlist_button_for_wishlisted_product(self):
|
||||||
|
WishlistedProduct.objects.create(
|
||||||
|
user=self.user,
|
||||||
|
product=self.product,
|
||||||
|
)
|
||||||
|
self.client.force_login(self.user)
|
||||||
|
response = self.client.get(
|
||||||
|
reverse("web:wishlist_button", kwargs={"pk": self.product.pk})
|
||||||
|
)
|
||||||
|
assert response.status_code == 200
|
||||||
|
|
||||||
|
def test_logged_user_create_wishlisted_product(self):
|
||||||
|
assert WishlistedProduct.objects.count() == 0
|
||||||
|
self.client.force_login(self.user)
|
||||||
|
response = self.client.post(
|
||||||
|
reverse("web:add_to_wishlist"),
|
||||||
|
{
|
||||||
|
"product": self.product.pk,
|
||||||
|
}
|
||||||
|
)
|
||||||
|
assert response.status_code == 201
|
||||||
|
assert WishlistedProduct.objects.filter(user=self.user, product=self.product).exists()
|
||||||
|
|
||||||
|
def test_logged_user_delete_wishlisted_product(self):
|
||||||
|
wishlisted = WishlistedProduct.objects.create(
|
||||||
|
user=self.user,
|
||||||
|
product=self.product,
|
||||||
|
)
|
||||||
|
self.client.force_login(self.user)
|
||||||
|
response = self.client.post(
|
||||||
|
reverse("web:delete_from_wishlist", kwargs={"pk": wishlisted.pk})
|
||||||
|
)
|
||||||
|
assert response.status_code == 204
|
||||||
|
assert not WishlistedProduct.objects.filter(user=self.user, product=self.product).exists()
|
||||||
+11
-7
@@ -6,12 +6,12 @@ from web.views.web import (
|
|||||||
add_cart_item,
|
add_cart_item,
|
||||||
add_to_wishlist,
|
add_to_wishlist,
|
||||||
cart_detail,
|
cart_detail,
|
||||||
|
category_view,
|
||||||
delete_cart_item,
|
delete_cart_item,
|
||||||
delete_from_wishlist,
|
delete_from_wishlist,
|
||||||
index,
|
index,
|
||||||
manifest,
|
manifest,
|
||||||
product_detail,
|
product_detail,
|
||||||
category_view,
|
|
||||||
)
|
)
|
||||||
|
|
||||||
app_name = "web"
|
app_name = "web"
|
||||||
@@ -21,26 +21,30 @@ urlpatterns = [
|
|||||||
path("categories/<str:slug>/", category_view, name="category_view"),
|
path("categories/<str:slug>/", category_view, name="category_view"),
|
||||||
path("products/<int:pk>/<str:slug>/", product_detail, name="product_detail"),
|
path("products/<int:pk>/<str:slug>/", product_detail, name="product_detail"),
|
||||||
path("cart/", cart_detail, name="cart_detail"),
|
path("cart/", cart_detail, name="cart_detail"),
|
||||||
|
|
||||||
# users
|
# users
|
||||||
path("login/", login, name="login"),
|
path("login/", login, name="login"),
|
||||||
path("logout/", logout, name="logout"),
|
path("logout/", logout, name="logout"),
|
||||||
path("register/", register, name="register"),
|
path("register/", register, name="register"),
|
||||||
path("reset-password/", reset_password, name="reset-password"),
|
path("reset-password/", reset_password, name="reset-password"),
|
||||||
path("my-account/", my_account, name="my_account"),
|
path("my-account/", my_account, name="my_account"),
|
||||||
|
|
||||||
# components
|
# components
|
||||||
path("web/components/products/", list_products, name="list_products"),
|
path("web/components/products/", list_products, name="list_products"),
|
||||||
path("web/components/cart-dropdown/", cart_dropdown, name="cart_dropdown"),
|
path("web/components/cart-dropdown/", cart_dropdown, name="cart_dropdown"),
|
||||||
path("web/components/cart/", cart, name="cart"),
|
path("web/components/cart/", cart, name="cart"),
|
||||||
path("web/components/wishlist-button/<int:pk>/", wishlist_button, name="wishlist_button"),
|
path(
|
||||||
|
"web/components/wishlist-button/<int:pk>/",
|
||||||
|
wishlist_button,
|
||||||
|
name="wishlist_button",
|
||||||
|
),
|
||||||
# api
|
# api
|
||||||
path("web/add-cart-item/", add_cart_item, name="add_cart_item"),
|
path("web/add-cart-item/", add_cart_item, name="add_cart_item"),
|
||||||
path("web/delete-cart-item/<int:pk>/", delete_cart_item, name="delete_cart_item"),
|
path("web/delete-cart-item/<int:pk>/", delete_cart_item, name="delete_cart_item"),
|
||||||
path("web/add-to-wishlist/", add_to_wishlist, name="add_to_wishlist"),
|
path("web/add-to-wishlist/", add_to_wishlist, name="add_to_wishlist"),
|
||||||
path("web/delete-from-wishlist/<int:pk>/", delete_from_wishlist, name="delete_from_wishlist"),
|
path(
|
||||||
|
"web/delete-from-wishlist/<int:pk>/",
|
||||||
|
delete_from_wishlist,
|
||||||
|
name="delete_from_wishlist",
|
||||||
|
),
|
||||||
# manifest
|
# manifest
|
||||||
path("manifest.json", manifest, name="manifest_json"),
|
path("manifest.json", manifest, name="manifest_json"),
|
||||||
]
|
]
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
from decimal import Decimal
|
from decimal import Decimal
|
||||||
|
|
||||||
from django.shortcuts import render, get_object_or_404
|
from django.shortcuts import get_object_or_404, render
|
||||||
from django.views.generic import TemplateView
|
from django.views.generic import TemplateView
|
||||||
|
|
||||||
from shop.filters import ProductFilter
|
from shop.filters import ProductFilter
|
||||||
@@ -76,11 +76,13 @@ def cart(request, *args, **kwargs):
|
|||||||
|
|
||||||
|
|
||||||
class WishlistButton(TemplateView):
|
class WishlistButton(TemplateView):
|
||||||
template_name = 'components/products/wishlist_button.html'
|
template_name = "components/products/wishlist_button.html"
|
||||||
|
|
||||||
def get_context_data(self, **kwargs):
|
def get_context_data(self, **kwargs):
|
||||||
product = get_object_or_404(Product, pk=self.kwargs.get('pk'))
|
product = get_object_or_404(Product, pk=self.kwargs.get("pk"))
|
||||||
is_wishlisted = WishlistedProduct.objects.filter(user=self.request.user, product=product).exists()
|
is_wishlisted = WishlistedProduct.objects.filter(
|
||||||
|
user=self.request.user, product=product
|
||||||
|
).exists()
|
||||||
|
|
||||||
return {
|
return {
|
||||||
"is_wishlisted": is_wishlisted,
|
"is_wishlisted": is_wishlisted,
|
||||||
|
|||||||
+4
-2
@@ -27,7 +27,7 @@ class CategoryView(TemplateView):
|
|||||||
|
|
||||||
def get_context_data(self, **kwargs):
|
def get_context_data(self, **kwargs):
|
||||||
settings = WebSettings.load()
|
settings = WebSettings.load()
|
||||||
slug = kwargs.get('slug')
|
slug = kwargs.get("slug")
|
||||||
category = ProductCategory.objects.get(slug=slug)
|
category = ProductCategory.objects.get(slug=slug)
|
||||||
|
|
||||||
return {
|
return {
|
||||||
@@ -140,7 +140,9 @@ def add_to_wishlist(request, *args, **kwargs):
|
|||||||
]
|
]
|
||||||
)
|
)
|
||||||
def delete_from_wishlist(request, pk, *args, **kwargs):
|
def delete_from_wishlist(request, pk, *args, **kwargs):
|
||||||
wishlisted_item = get_object_or_404(WishlistedProduct, product_id=pk, user=request.user)
|
wishlisted_item = get_object_or_404(
|
||||||
|
WishlistedProduct, product_id=pk, user=request.user
|
||||||
|
)
|
||||||
wishlisted_item.delete()
|
wishlisted_item.delete()
|
||||||
return HttpResponse(status=204, headers={"HX-Trigger": "updated-wishlist"})
|
return HttpResponse(status=204, headers={"HX-Trigger": "updated-wishlist"})
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user