From cba259473bc828ba9a075fbd216c8ffce8189d5d Mon Sep 17 00:00:00 2001 From: Artemiy Rodionov Date: Fri, 9 Nov 2018 18:20:34 +0300 Subject: [PATCH] Create tests: ProductsContext and TagsContext. Fix a lot of code. --- catalog/models.py | 2 +- catalog/newcontext/__init__.py | 1 + catalog/newcontext/products.py | 28 +++++++++++---- catalog/newcontext/tags.py | 5 +-- tests/catalog/test_context.py | 62 ++++++++++++++++++++++++++++++++++ 5 files changed, 88 insertions(+), 10 deletions(-) create mode 100644 tests/catalog/test_context.py diff --git a/catalog/models.py b/catalog/models.py index 5bfb9fe..e2f400d 100644 --- a/catalog/models.py +++ b/catalog/models.py @@ -134,7 +134,7 @@ def tagged(self, tags): # See docs for details: # https://www.postgresql.org/docs/10/static/sql-select.html#SQL-DISTINCT # https://docs.djangoproject.com/en/2.1/ref/models/querysets/#django.db.models.query.QuerySet.distinct - return self.filter(tags__in=self._tags).distinct() + return self.filter(tags__in=tags).distinct() class ProductManager(models.Manager.from_queryset(ProductQuerySet)): diff --git a/catalog/newcontext/__init__.py b/catalog/newcontext/__init__.py index 542a0f3..f1b53f0 100644 --- a/catalog/newcontext/__init__.py +++ b/catalog/newcontext/__init__.py @@ -1 +1,2 @@ # @todo #183:120m Implement Page, PaginatedProducts context classes. +from . import context, products, tags diff --git a/catalog/newcontext/products.py b/catalog/newcontext/products.py index d156119..05b0246 100644 --- a/catalog/newcontext/products.py +++ b/catalog/newcontext/products.py @@ -1,11 +1,24 @@ import typing +from django.conf import settings from django.db.models import QuerySet from catalog.newcontext.context import Context, Products, Tags from catalog.models import AbstractCategory +class SortingOption: + def __init__(self, index=0): + options = settings.CATEGORY_SORTING_OPTIONS[index] + self.label = options['label'] + self.field = options['field'] + self.direction = options['direction'] + + @property + def directed_field(self): + return self.direction + self.field + + class ActiveProducts(Products): def __init__(self, products: Products): @@ -19,7 +32,7 @@ class OrderedProducts(Products): def __init__(self, products: Products, req_kwargs): self._products = products - self._sorting_index = self._req_kwargs.get('sorting', 0) + self._sorting_index = req_kwargs.get('sorting', 0) def qs(self): return self._products.qs().order_by( @@ -43,9 +56,9 @@ def qs(self): return self._products.qs().get_category_descendants(self._category) -class ProductsByTags(Products): +class TaggedProducts(Products): - def __init__(self, products: Products, tags_context: Tags): + def __init__(self, products: Products, tags: Tags): self._products = products self._tags = tags @@ -57,7 +70,7 @@ def qs(self): return self._products.qs() -class ProductBrand(Context): +class ProductBrands(Context): def __init__(self, products: Products, tags: Tags): self._products = products @@ -77,17 +90,18 @@ def context(self): } -class ProductImages +class ProductImages(Context): - def __init__(self, products: Products): + def __init__(self, products: Products, images: QuerySet): self._products = products + self._images = images def context(self): page_product_map = { product.page: product for product in self._products.qs() } - images = Image.objects.get_main_images_by_pages(page_product_map.keys()) + images = self._images.get_main_images_by_pages(page_product_map.keys()) product_images = { product: images.get(page) for page, product in page_product_map.items() diff --git a/catalog/newcontext/tags.py b/catalog/newcontext/tags.py index 0da326f..0148ad3 100644 --- a/catalog/newcontext/tags.py +++ b/catalog/newcontext/tags.py @@ -1,6 +1,7 @@ from catalog.newcontext.context import Context, Tags, Products from django.db.models import QuerySet +from django.http import Http404 class GroupedTags(Context): @@ -23,7 +24,7 @@ def __init__(self, tags: Tags, req_kwargs): def qs(self): tags = self._tags.qs() if not self._raw_tags: - tags.none() + return tags.none() return tags.parsed(self._raw_tags) @@ -35,5 +36,5 @@ def __init__(self, tags: Tags): def qs(self): tags = self._tags.qs() if not tags.exists(): - raise http.Http404('No such tag.') + raise Http404('No such tag.') return tags diff --git a/tests/catalog/test_context.py b/tests/catalog/test_context.py new file mode 100644 index 0000000..14a196f --- /dev/null +++ b/tests/catalog/test_context.py @@ -0,0 +1,62 @@ +import unittest + +from django.test import TestCase, override_settings +from django.http import Http404 + +from catalog import newcontext as context +from tests.catalog import models as catalog_models + + +def mocked_ctx(qs_attrs=None, context_attrs=None): + ctx = unittest.mock.Mock() + ctx.qs.return_value = unittest.mock.Mock(**(qs_attrs or {})) + ctx.context.return_value = unittest.mock.Mock(**(context_attrs or {})) + + return ctx + + +class ProductsContext(TestCase): + + @override_settings(CATEGORY_SORTING_OPTIONS={ + 1: {'label': 'price', 'field': 'price', 'direction': ''} + }) + def test_ordered_products(self): + products_ctx = mocked_ctx() + context.products.OrderedProducts(products_ctx, {'sorting': 1}).qs() + self.assertTrue(products_ctx.qs().order_by.called) + self.assertEqual(products_ctx.qs().order_by.call_args[0][0], 'price') + + def test_tagged_products(self): + products_ctx = mocked_ctx() + context.products.TaggedProducts( + products_ctx, mocked_ctx(qs_attrs={'exists.return_value': True}), + ).qs() + + self.assertTrue(products_ctx.qs().tagged.called) + + def test_non_tagged_products(self): + """If there are no tags, then products don't changed.""" + products_ctx = mocked_ctx() + context.products.TaggedProducts( + products_ctx, mocked_ctx(qs_attrs={'exists.return_value': False}), + ).qs() + + self.assertFalse(products_ctx.qs().tagged.called) + + +class TagsContext(TestCase): + + def test_parsed_tags(self): + tags_ctx = mocked_ctx() + raw_tags = 'test' + context.tags.ParsedTags(tags_ctx, {'tags': raw_tags}).qs() + self.assertTrue(tags_ctx.qs().parsed.called) + + def test_unparsed_tags(self): + tags_ctx = mocked_ctx() + context.tags.ParsedTags(tags_ctx, {}).qs() + self.assertFalse(tags_ctx.qs().parsed.called) + + def test_404_check_tags(self): + with self.assertRaises(Http404): + context.tags.Checked404Tags(mocked_ctx(qs_attrs={'exists.return_value': False})).qs()