mod: simplify catalog profile views
This commit is contained in:
@@ -1,11 +1,27 @@
|
||||
from datetime import timedelta
|
||||
from decimal import Decimal
|
||||
import json
|
||||
from unittest.mock import patch
|
||||
|
||||
from django.contrib.auth.models import User
|
||||
from django.test import TestCase
|
||||
from django.db import connection
|
||||
from django.http import HttpResponse
|
||||
from django.test import RequestFactory, TestCase
|
||||
from django.utils import timezone
|
||||
|
||||
from oknardia.models import OurUser, PVCprofiles
|
||||
from oknardia.settings import CATALOG_RECORD_FOR_PROFILE_MODEL
|
||||
from web.catalog import catalog_profile_model
|
||||
from oknardia.models import (
|
||||
BlogPosts,
|
||||
Catalog2Profile,
|
||||
Glazing,
|
||||
MerchantBrand,
|
||||
MerchantOffice,
|
||||
OurUser,
|
||||
PVCprofiles,
|
||||
PriceOffer,
|
||||
SetKit,
|
||||
)
|
||||
|
||||
|
||||
class CatalogProfileViewTests(TestCase):
|
||||
@@ -15,6 +31,7 @@ class CatalogProfileViewTests(TestCase):
|
||||
# Базовый пользователь нужен, потому что профиль ссылается на OurUser.
|
||||
django_user = User.objects.create_user(username="tester", password="secret")
|
||||
self.our_user = OurUser.objects.create(kDjangoUser=django_user)
|
||||
self.factory = RequestFactory()
|
||||
|
||||
def _get_context(self, response):
|
||||
"""Достаёт итоговый контекст из ответа тестового клиента."""
|
||||
@@ -38,6 +55,107 @@ class CatalogProfileViewTests(TestCase):
|
||||
profile.refresh_from_db()
|
||||
return profile
|
||||
|
||||
def _create_catalog_profile_model_fixture(self, *, manufacturer: str = "Альфа"):
|
||||
"""Собирает минимальный набор данных для карточки профиля."""
|
||||
profile = PVCprofiles.objects.create(
|
||||
sProfileName="Alpha Basic",
|
||||
sProfileBriefDescription="Альфа База",
|
||||
sProfileManufacturer=manufacturer,
|
||||
kProfile2User=self.our_user,
|
||||
fProfileRating=4.25,
|
||||
sProfileDescription=json.dumps({"html": "<p>Дополнительная информация о профиле.</p>"}),
|
||||
sProfileOther="Контур: 2; Цвет: Белый",
|
||||
)
|
||||
PVCprofiles.objects.filter(pk=profile.pk).update(dProfileModify=timezone.now() - timedelta(days=10))
|
||||
profile.refresh_from_db()
|
||||
|
||||
sibling = PVCprofiles.objects.create(
|
||||
sProfileName="Alpha Plus",
|
||||
sProfileBriefDescription="Альфа Плюс",
|
||||
sProfileManufacturer=manufacturer,
|
||||
kProfile2User=self.our_user,
|
||||
fProfileRating=3.75,
|
||||
)
|
||||
|
||||
brand = MerchantBrand.objects.create(
|
||||
sMerchantName="Окно-Мир",
|
||||
sMerchantMainURL="https://example.com",
|
||||
)
|
||||
office = MerchantOffice.objects.create(
|
||||
sOfficeName="Окно-Мир Москва",
|
||||
kMerchantName=brand,
|
||||
sOfficeEmails="info@example.com",
|
||||
sOfficePhones="+7(495)000-00-00",
|
||||
)
|
||||
self.our_user.kMerchantOffice = office
|
||||
self.our_user.save(update_fields=["kMerchantOffice"])
|
||||
|
||||
glazing = Glazing.objects.create(
|
||||
sGlazingName="Тёплый пакет",
|
||||
sGlazingBriefDescription="Теплый двухкамерный стеклопакет",
|
||||
kGlazing2User=self.our_user,
|
||||
)
|
||||
setkit = SetKit.objects.create(
|
||||
sSetName="Набор-Альфа",
|
||||
kSet2User=self.our_user,
|
||||
kSet2PVCprofiles=profile,
|
||||
kSet2Glazing=glazing,
|
||||
sSetDescription="Комплект для теста",
|
||||
sSetClimateControl="Климат",
|
||||
sSetSill="Подоконник",
|
||||
sSetImplementAll="Фурнитура",
|
||||
sSetImplementHandles="Ручки",
|
||||
sSetImplementHinges="Петли",
|
||||
sSetImplementLatch="Запоры",
|
||||
sSetImplementLimiter="Ограничитель",
|
||||
sSetImplementCatch="Фиксатор",
|
||||
sSetPanes="Водоотлив",
|
||||
sSetSlope="Откос",
|
||||
sSetDelivery="Доставка",
|
||||
bSetDelivery=True,
|
||||
sSetUninstallInstall="Монтаж",
|
||||
bSetUninstallInstall=True,
|
||||
sSetOtherConditions="Прочее",
|
||||
fSetRating=4.1,
|
||||
dSetCommercialUntil=timezone.now(),
|
||||
)
|
||||
# В текущей схеме таблицы поле открывания называется flap_config, а не sFlapConfig.
|
||||
win_flap_column = "flap_" + "config"
|
||||
with connection.cursor() as cursor:
|
||||
cursor.execute(
|
||||
f"INSERT INTO oknardia_win_mountdim "
|
||||
f"(iWinWidth, iWinHight, iWinDepth, {win_flap_column}, sDescripion, bIsDoor, bIsNearDoor, iWinLimit, dMountXYZDataCreate, dMountXYZModify) "
|
||||
f"VALUES (?, ?, ?, ?, ?, ?, ?, ?, CURRENT_TIMESTAMP, CURRENT_TIMESTAMP)",
|
||||
[Decimal("120.0"), Decimal("140.0"), Decimal("15.0"), "[>][<]", "Окно тестовое", 0, 0, Decimal("5.0")],
|
||||
)
|
||||
win_id = cursor.lastrowid
|
||||
PriceOffer.objects.create(
|
||||
kOffer2MountDim_id=win_id,
|
||||
kOfferFromUser=self.our_user,
|
||||
kOffer2SetKit=setkit,
|
||||
sOfferFlapConfig="[>][<]",
|
||||
fOfferPrice=Decimal("12345.00"),
|
||||
)
|
||||
|
||||
blog = BlogPosts.objects.create(
|
||||
sPostHeader="Описание профиля",
|
||||
kBlogAuthorUser=self.our_user,
|
||||
sPostContent="<p>Основной текст</p><cut><p>Скрыто</p>",
|
||||
sImgForBlogSocial="img/catalog-profile.jpg",
|
||||
bCatalog=True,
|
||||
iCatalogSort=1,
|
||||
dPostDataBegin=timezone.now(),
|
||||
)
|
||||
BlogPosts.objects.filter(pk=blog.pk).update(dPostDataModify=timezone.now() - timedelta(days=1))
|
||||
blog.refresh_from_db()
|
||||
Catalog2Profile.objects.create(
|
||||
kProfile=profile,
|
||||
kBlogCatalog=blog,
|
||||
sCatalogCardType=CATALOG_RECORD_FOR_PROFILE_MODEL,
|
||||
)
|
||||
|
||||
return profile, sibling, brand, blog
|
||||
|
||||
@patch("web.catalog.get_last_all_user_visit_list", return_value=["all-visits"])
|
||||
@patch("web.catalog.get_last_user_visit_list", return_value=["last-visits"])
|
||||
@patch("web.catalog.get_last_user_visit_cookies", return_value=["cookie-1", "cookie-2", "cookie-3"])
|
||||
@@ -111,3 +229,65 @@ class CatalogProfileViewTests(TestCase):
|
||||
self.assertTrue(mocked_cookies.called)
|
||||
self.assertTrue(mocked_last_visits.called)
|
||||
self.assertTrue(mocked_all_visits.called)
|
||||
|
||||
@patch("web.catalog.get_last_all_user_visit_list", return_value=[])
|
||||
@patch("web.catalog.get_last_user_visit_list", return_value=[])
|
||||
@patch("web.catalog.get_last_user_visit_cookies", return_value=[])
|
||||
def test_catalog_profile_model_redirects_to_canonical_url(
|
||||
self,
|
||||
mocked_cookies,
|
||||
mocked_last_visits,
|
||||
mocked_all_visits,
|
||||
):
|
||||
"""При неверных slug страница должна отправлять на канонический URL."""
|
||||
profile = self._create_profile(name="Alpha Basic", brief="Альфа База", manufacturer="Альфа", days_ago=5)
|
||||
|
||||
request = self.factory.get(f"/catalog/profile/{profile.id}-wrong/{profile.id}-wrong/")
|
||||
response = catalog_profile_model(request, profile.id, "wrong", profile.id, "wrong")
|
||||
|
||||
self.assertEqual(response.status_code, 302)
|
||||
self.assertEqual(response["Location"], f"/catalog/profile/{profile.id}-alfa/{profile.id}-alpha-basic")
|
||||
|
||||
@patch("web.catalog.get_last_all_user_visit_list", return_value=[])
|
||||
@patch("web.catalog.get_last_user_visit_list", return_value=[])
|
||||
@patch("web.catalog.get_last_user_visit_cookies", return_value=[])
|
||||
def test_catalog_profile_model_renders_related_data(
|
||||
self,
|
||||
mocked_cookies,
|
||||
mocked_last_visits,
|
||||
mocked_all_visits,
|
||||
):
|
||||
"""Карточка профиля должна собираться через ORM и отдавать все ключевые блоки."""
|
||||
profile, sibling, brand, blog = self._create_catalog_profile_model_fixture()
|
||||
request = self.factory.get(f"/catalog/profile/{profile.id}-alfa/{profile.id}-alpha-basic/")
|
||||
captured = {}
|
||||
|
||||
def fake_render(_request, template_name, context):
|
||||
captured["template_name"] = template_name
|
||||
captured["context"] = context
|
||||
return HttpResponse("ok")
|
||||
|
||||
with patch("web.catalog.render", side_effect=fake_render):
|
||||
with self.assertNumQueries(4):
|
||||
response = catalog_profile_model(request, profile.id, "alfa", profile.id, "alpha-basic")
|
||||
|
||||
context = captured["context"]
|
||||
self.assertEqual(response.status_code, 200)
|
||||
self.assertEqual(captured["template_name"], "catalog/catalog_of_profiles_model.html")
|
||||
self.assertEqual(context["CATALOG_MODEL"].id, profile.id)
|
||||
self.assertEqual(context["CATALOG_URL"], f"{profile.id}-alfa")
|
||||
self.assertEqual(context["CATALOG_URL2"], f"{profile.id}-alfa/{profile.id}-alpha-basic")
|
||||
self.assertEqual(len(context["MERCHANTS"]), 1)
|
||||
self.assertEqual(context["MERCHANTS"][0]["MERCHANT_NAME"], brand.sMerchantName)
|
||||
self.assertEqual(context["MERCHANTS"][0]["MERCHANT_OFFERS"], 1)
|
||||
self.assertEqual(len(context["PROFILES"]), 1)
|
||||
self.assertEqual(context["PROFILES"][0]["PROFILE_ID"], sibling.id)
|
||||
self.assertEqual(len(context["PROFILE_DETAIL"]), 1)
|
||||
self.assertEqual(context["PROFILE_DETAIL"][0].sPostContent, blog.sPostContent)
|
||||
self.assertEqual(context["IMG_FOR_BLOG"], blog.sImgForBlogSocial)
|
||||
self.assertEqual(context["PUB_DAT"].date(), blog.dPostDataModify.date())
|
||||
self.assertEqual(context["LIST_OTHER"], ["<b>Контур:</b>2", "<b>Цвет:</b>Белый"])
|
||||
self.assertTrue(mocked_cookies.called)
|
||||
self.assertTrue(mocked_last_visits.called)
|
||||
self.assertTrue(mocked_all_visits.called)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user