Files
santeh-ray/orders/tests.py
Azimkin 1188cef7be
All checks were successful
Build and Push Docker Image / build (push) Successful in 27s
Make product cards fully clickable
2026-06-16 00:06:21 +02:00

313 lines
13 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.core import mail
from django.db import IntegrityError
from django.test import TestCase, override_settings
from django.urls import reverse
from items.models import Category, Item, ItemImage, Subcategory
from orders.models import Cart, CartItem, Order, OrderItem
User = get_user_model()
@override_settings(
MEDIA_URL="/media/",
EMAIL_BACKEND="django.core.mail.backends.locmem.EmailBackend",
ADMINISTRATOR_EMAIL="admin@example.com",
)
class CartFlowTests(TestCase):
def setUp(self):
self.user = User.objects.create_user(
username="cart-user",
email="cart@example.com",
password="StrongPassword123",
is_active=True,
)
self.category = Category.objects.create(name="Сантехника", slug="plumbing")
self.subcategory = Subcategory.objects.create(name="Мойки", slug="sinks", category=self.category)
self.item = Item.objects.create(
name="Кухонная мойка",
slug="kitchen-sink",
category=self.category,
subcategory=self.subcategory,
description="Искусственный камень",
price="1600.00",
is_available=True,
)
self.unavailable_item = Item.objects.create(
name="Смеситель",
slug="tap",
category=self.category,
subcategory=self.subcategory,
description="Недоступный товар",
price="400.00",
is_available=False,
)
def checkout_data(self, **overrides):
data = {
"delivery_method": "courier",
"region": "Минск",
"address": "ул. Тимирязева, 123",
"payment_method": "card",
"customer_name": "Иван Петров",
"phone": "+375296881819",
"email": "buyer@example.com",
"recipient_matches_customer": "on",
"promo_code": "SPRING",
"terms_accepted": "on",
}
data.update(overrides)
return data
def test_cart_item_is_unique_per_cart(self):
cart = Cart.objects.create(user=self.user)
CartItem.objects.create(cart=cart, item=self.item, quantity=1)
with self.assertRaises(IntegrityError):
CartItem.objects.create(cart=cart, item=self.item, quantity=2)
def test_add_remove_and_update_quantity_for_authenticated_user(self):
self.client.force_login(self.user)
add_response = self.client.post(
reverse("orders:add"),
data={"item_id": self.item.id, "next": reverse("orders:cart")},
)
self.assertRedirects(add_response, reverse("orders:cart"))
self.assertTrue(CartItem.objects.filter(cart__user=self.user, item=self.item, quantity=1).exists())
update_response = self.client.post(
reverse("orders:update_quantity"),
data={"item_id": self.item.id, "quantity": 3, "next": reverse("orders:cart")},
)
self.assertRedirects(update_response, reverse("orders:cart"))
self.assertTrue(CartItem.objects.filter(cart__user=self.user, item=self.item, quantity=3).exists())
remove_response = self.client.post(
reverse("orders:remove"),
data={"item_id": self.item.id, "next": reverse("orders:cart")},
)
self.assertRedirects(remove_response, reverse("orders:cart"))
self.assertFalse(CartItem.objects.filter(cart__user=self.user, item=self.item).exists())
def test_add_endpoint_rejects_unavailable_item(self):
self.client.force_login(self.user)
response = self.client.post(
reverse("orders:add"),
data={"item_id": self.unavailable_item.id, "next": reverse("orders:cart")},
follow=True,
)
self.assertEqual(response.status_code, 200)
self.assertFalse(CartItem.objects.filter(cart__user=self.user, item=self.unavailable_item).exists())
self.assertContains(response, "Недоступный товар нельзя добавить в корзину.")
def test_cart_page_shows_authenticated_user_items(self):
cart = Cart.objects.create(user=self.user)
CartItem.objects.create(cart=cart, item=self.item, quantity=2)
ItemImage.objects.create(
item=self.item,
image="items/cart-item.jpg",
alt="Фото мойки",
is_primary=True,
)
self.client.force_login(self.user)
response = self.client.get(reverse("orders:cart"))
self.assertEqual(response.status_code, 200)
self.assertContains(response, "Кухонная мойка")
self.assertContains(response, "Оформление заказа")
self.assertContains(response, "1600,00 руб.")
self.assertContains(response, "3200,00 руб.")
self.assertContains(response, "3295,00 руб.")
self.assertContains(response, "/media/items/cart-item.jpg")
self.assertContains(
response,
'<a class="cart-item__overlay" href="/catalog/plumbing/kitchen-sink/"',
html=False,
)
self.assertContains(response, 'id="cart-increment-', html=False)
self.assertContains(response, 'action="/orders/cart/remove/"', html=False)
self.assertNotContains(response, 'name="promo_code"', html=False)
def test_cart_page_redirects_guest_to_login(self):
response = self.client.get(reverse("orders:cart"))
self.assertEqual(response.status_code, 302)
self.assertIn(reverse("users:login"), response["Location"])
def test_checkout_creates_paid_order_clears_cart_and_sends_email(self):
cart = Cart.objects.create(user=self.user)
CartItem.objects.create(cart=cart, item=self.item, quantity=2)
self.client.force_login(self.user)
response = self.client.post(reverse("orders:checkout"), data=self.checkout_data())
order = Order.objects.get()
self.assertRedirects(response, reverse("orders:success", kwargs={"order_id": order.id}))
self.assertEqual(order.status, Order.Status.PAID)
self.assertEqual(order.products_total, 3200)
self.assertEqual(order.discount_total, 0)
self.assertEqual(order.delivery_total, 50)
self.assertEqual(order.floor_lift_total, 45)
self.assertEqual(order.total, 3295)
self.assertEqual(order.promo_code, "SPRING")
self.assertFalse(CartItem.objects.filter(cart=cart).exists())
order_item = OrderItem.objects.get(order=order)
self.assertEqual(order_item.item_name, "Кухонная мойка")
self.assertEqual(order_item.quantity, 2)
self.assertEqual(order_item.line_total, 3200)
self.assertEqual(len(mail.outbox), 1)
self.assertEqual(mail.outbox[0].to, ["buyer@example.com"])
self.assertEqual(mail.outbox[0].bcc, ["admin@example.com"])
self.assertIn(f"заказ №{order.id}", mail.outbox[0].subject.lower())
self.assertIn("Кухонная мойка", mail.outbox[0].body)
def test_checkout_rejects_empty_cart(self):
self.client.force_login(self.user)
response = self.client.post(reverse("orders:checkout"), data=self.checkout_data())
self.assertRedirects(response, reverse("orders:cart"))
self.assertFalse(Order.objects.exists())
self.assertEqual(len(mail.outbox), 0)
def test_checkout_requires_address_for_courier_delivery(self):
cart = Cart.objects.create(user=self.user)
CartItem.objects.create(cart=cart, item=self.item, quantity=1)
self.client.force_login(self.user)
response = self.client.post(
reverse("orders:checkout"),
data=self.checkout_data(region="", address=""),
)
self.assertEqual(response.status_code, 400)
self.assertContains(response, "Укажите регион доставки.", status_code=400)
self.assertContains(response, "Укажите адрес доставки.", status_code=400)
self.assertFalse(Order.objects.exists())
def test_checkout_pickup_does_not_require_address_or_add_services(self):
cart = Cart.objects.create(user=self.user)
CartItem.objects.create(cart=cart, item=self.item, quantity=1)
self.client.force_login(self.user)
response = self.client.post(
reverse("orders:checkout"),
data=self.checkout_data(delivery_method="pickup", region="", address=""),
)
order = Order.objects.get()
self.assertRedirects(response, reverse("orders:success", kwargs={"order_id": order.id}))
self.assertEqual(order.delivery_total, 0)
self.assertEqual(order.floor_lift_total, 0)
self.assertEqual(order.total, 1600)
def test_buy_now_page_is_available_to_guest(self):
response = self.client.get(reverse("orders:buy_now", kwargs={"item_id": self.item.id}))
self.assertEqual(response.status_code, 200)
self.assertContains(response, "Оформление заказа")
self.assertContains(response, "Кухонная мойка")
self.assertContains(response, f'action="{reverse("orders:buy_now", kwargs={"item_id": self.item.id})}"', html=False)
self.assertNotContains(response, "cart-remove-", html=False)
def test_buy_now_rejects_unavailable_item(self):
response = self.client.get(reverse("orders:buy_now", kwargs={"item_id": self.unavailable_item.id}))
self.assertEqual(response.status_code, 404)
def test_buy_now_creates_guest_order_without_cart_and_sends_email(self):
response = self.client.post(
reverse("orders:buy_now", kwargs={"item_id": self.item.id}),
data=self.checkout_data(),
)
order = Order.objects.get()
self.assertRedirects(response, reverse("orders:success", kwargs={"order_id": order.id}))
self.assertIsNone(order.user)
self.assertEqual(order.products_total, 1600)
self.assertEqual(order.delivery_total, 50)
self.assertEqual(order.floor_lift_total, 45)
self.assertEqual(order.total, 1695)
self.assertFalse(Cart.objects.exists())
order_item = OrderItem.objects.get(order=order)
self.assertEqual(order_item.item_name, "Кухонная мойка")
self.assertEqual(order_item.quantity, 1)
self.assertEqual(order_item.line_total, 1600)
self.assertIn(order.id, self.client.session["guest_order_ids"])
self.assertEqual(len(mail.outbox), 1)
self.assertEqual(mail.outbox[0].to, ["buyer@example.com"])
def test_guest_success_page_requires_session_order_access(self):
order = Order.objects.create(
user=None,
customer_name="Иван Петров",
phone="+375296881819",
email="buyer@example.com",
delivery_method=Order.DeliveryMethod.COURIER,
region="Минск",
address="ул. Тимирязева, 123",
payment_method=Order.PaymentMethod.CARD,
products_total=1600,
discount_total=0,
delivery_total=50,
floor_lift_total=45,
total=1695,
status=Order.Status.PAID,
)
response = self.client.get(reverse("orders:success", kwargs={"order_id": order.id}))
self.assertEqual(response.status_code, 404)
def test_guest_success_page_allows_session_order_access(self):
response = self.client.post(
reverse("orders:buy_now", kwargs={"item_id": self.item.id}),
data=self.checkout_data(),
)
order = Order.objects.get()
self.assertRedirects(response, reverse("orders:success", kwargs={"order_id": order.id}))
success_response = self.client.get(reverse("orders:success", kwargs={"order_id": order.id}))
self.assertEqual(success_response.status_code, 200)
self.assertContains(success_response, f"Заказ №{order.id} оформлен")
def test_success_page_is_only_available_to_order_owner(self):
other_user = User.objects.create_user(
username="other-user",
email="other@example.com",
password="StrongPassword123",
is_active=True,
)
order = Order.objects.create(
user=self.user,
customer_name="Иван Петров",
phone="+375296881819",
email="buyer@example.com",
delivery_method=Order.DeliveryMethod.COURIER,
region="Минск",
address="ул. Тимирязева, 123",
payment_method=Order.PaymentMethod.CARD,
products_total=1600,
discount_total=0,
delivery_total=50,
floor_lift_total=45,
total=1695,
status=Order.Status.PAID,
)
self.client.force_login(other_user)
response = self.client.get(reverse("orders:success", kwargs={"order_id": order.id}))
self.assertEqual(response.status_code, 404)