Files
santeh-ray/favorites/tests.py
Azimkin 29d8302a4f
All checks were successful
Build and Push Docker Image / build (push) Successful in 51s
feat: add favorites feature for users
- Implemented `Favorite` model with unique user-item constraint and timestamped records
- Added `favorites:index` and `favorites:toggle` views with AJAX support for toggling favorites
- Built templates and front-end assets for the favorites page and integration with item grids
- Extended header with favorites link and dynamic counter
- Added tests covering models, views, and templates for the favorites functionality
- Updated admin to enable management of favorites via Django admin interface
2026-05-10 20:06:12 +02:00

121 lines
4.8 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
from django.contrib.auth import get_user_model
from django.db import IntegrityError
from django.test import TestCase
from django.urls import reverse
from favorites.models import Favorite
from items.models import Category, Item, ItemImage, Subcategory
User = get_user_model()
class FavoritePageTests(TestCase):
def setUp(self):
self.user = User.objects.create_user(
username="marina",
email="marina@example.com",
password="StrongPassword123",
is_active=True,
)
self.plumbing = Category.objects.create(name="Сантехника", slug="plumbing")
self.sinks = Subcategory.objects.create(name="Мойки", slug="sinks", category=self.plumbing)
self.taps = Subcategory.objects.create(name="Смесители", slug="taps", category=self.plumbing)
self.sink = Item.objects.create(
name="Кухонная мойка",
slug="kitchen-sink",
category=self.plumbing,
subcategory=self.sinks,
description="Искусственный камень",
price="1600.00",
is_available=True,
)
self.tap = Item.objects.create(
name="Смеситель Mono",
slug="mono-tap",
category=self.plumbing,
subcategory=self.taps,
description="Однорычажный смеситель",
price="320.00",
is_available=False,
)
def test_favorites_page_redirects_unauthenticated_users(self):
response = self.client.get(reverse("favorites:index"))
self.assertEqual(response.status_code, 302)
self.assertIn(reverse("users:login"), response["Location"])
def test_favorites_page_shows_empty_state(self):
self.client.force_login(self.user)
response = self.client.get(reverse("favorites:index"))
self.assertEqual(response.status_code, 200)
self.assertContains(response, "В избранном пока нет товаров.")
def test_favorites_page_shows_items_in_tile_grid(self):
self.client.force_login(self.user)
ItemImage.objects.create(
item=self.sink,
image="items/sink-primary.jpg",
alt="Главное фото мойки",
sort_order=0,
is_primary=True,
)
Favorite.objects.create(user=self.user, item=self.tap)
Favorite.objects.create(user=self.user, item=self.sink)
response = self.client.get(reverse("favorites:index"))
self.assertEqual(response.status_code, 200)
self.assertContains(response, "Избранное")
self.assertContains(response, "Кухонная мойка")
self.assertContains(response, "Смеситель Mono")
self.assertContains(response, "/media/items/sink-primary.jpg")
self.assertContains(response, 'href="/catalog/plumbing/kitchen-sink/"', html=False)
self.assertContains(response, 'href="/catalog/plumbing/mono-tap/"', html=False)
self.assertContains(response, "Удалить из избранного")
def test_toggle_endpoint_adds_and_removes_favorite(self):
self.client.force_login(self.user)
add_response = self.client.post(
reverse("favorites:toggle"),
data={"item_id": self.sink.pk, "next": reverse("favorites:index")},
)
self.assertRedirects(add_response, reverse("favorites:index"))
self.assertTrue(Favorite.objects.filter(user=self.user, item=self.sink).exists())
remove_response = self.client.post(
reverse("favorites:toggle"),
data={"item_id": self.sink.pk, "next": reverse("favorites:index")},
)
self.assertRedirects(remove_response, reverse("favorites:index"))
self.assertFalse(Favorite.objects.filter(user=self.user, item=self.sink).exists())
def test_toggle_endpoint_returns_json_for_ajax_requests(self):
self.client.force_login(self.user)
response = self.client.post(
reverse("favorites:toggle"),
data={"item_id": self.sink.pk, "next": reverse("favorites:index")},
HTTP_X_REQUESTED_WITH="XMLHttpRequest",
HTTP_ACCEPT="application/json",
)
self.assertEqual(response.status_code, 200)
self.assertEqual(response["Content-Type"], "application/json")
self.assertEqual(response.json()["item_id"], self.sink.pk)
self.assertTrue(response.json()["is_favorite"])
self.assertEqual(response.json()["favorite_count"], 1)
self.assertTrue(Favorite.objects.filter(user=self.user, item=self.sink).exists())
def test_favorite_pair_is_unique_per_user_and_item(self):
Favorite.objects.create(user=self.user, item=self.sink)
with self.assertRaises(IntegrityError):
Favorite.objects.create(user=self.user, item=self.sink)