Repository: fidals/shopelectro

Issue:
Stale previews on category page under load_more
At #641 fixed similar issue. But it was about product page.

https://www.shopelectro.ru/catalog/categories/akkumuliatory-270/


Discussion:

Resolving patch:
diff --git a/shopelectro/views/catalog.py b/shopelectro/views/catalog.py
--- a/shopelectro/views/catalog.py
+++ b/shopelectro/views/catalog.py
@@ -250,14 +250,22 @@ def load_more(request, category_slug, offset=0, limit=0, sorting=0, tags=None):
     products = paginated_page.object_list
     view = request.session.get('view_type', 'tile')
 
+    # products list has been sliced.
+    # So it can't be context's arg.
+    # We should create not sliced list with the same data.
+    products_to_filter = (
+        models.Product.objects
+        .filter(id__in=[p.id for p in products])
+        .order_by(sorting_option.directed_field)
+    )
     data_from_context = (
         context.Category(
             url_kwargs={},
             request=request,
             page=category.page,
-            products=models.Product.objects.all(),
+            products=products_to_filter,
             product_pages=models.ProductPage.objects.filter(
-                shopelectro_product__in=products
+                shopelectro_product__in=products_to_filter
             ),
         )
         | context.TaggedCategory(tags=models.Tag.objects.all())


Test patch:
diff --git a/shopelectro/management/commands/test_db.py b/shopelectro/management/commands/test_db.py
--- a/shopelectro/management/commands/test_db.py
+++ b/shopelectro/management/commands/test_db.py
@@ -34,7 +34,7 @@ class Command(BaseCommand):
         'assets/gold_deer.jpg'
     )
 
-    PRODUCT_WITH_IMAGE = 1
+    PRODUCTS_WITH_IMAGE = [1, 113]
 
     def __init__(self):
         super(BaseCommand, self).__init__()
@@ -94,6 +94,8 @@ def save_dump():
             output='shopelectro/fixtures/dump.json'
         )
 
+    # @todo #645:30m Move test_db's product_id to generator. stb2
+    #  Now it uses dirty autoincrement.
     @property
     def product_id(self):
         self._product_id += 1
@@ -161,7 +163,8 @@ def create_product(parent: se_models.Category, tags_, price_factor):
             for tag in tags_:
                 product.tags.add(tag)
 
-            if product.id == self.PRODUCT_WITH_IMAGE:
+            if product.id in self.PRODUCTS_WITH_IMAGE:
+                create_images(product.page)
                 create_images(product.page)
 
         def fill_with_products(to_fill, tags_, count):
diff --git a/shopelectro/tests/tests_selenium_admin.py b/shopelectro/tests/tests_selenium_admin.py
--- a/shopelectro/tests/tests_selenium_admin.py
+++ b/shopelectro/tests/tests_selenium_admin.py
@@ -66,7 +66,6 @@ def setUpClass(cls):
         cls.change_products_url = cls.live_server_url + reverse(
             'admin:shopelectro_productpage_changelist')
         cls.title_text = 'Shopelectro administration'
-        cls.product_table = 'paginator'
         cls.active_products = '//*[@id="changelist-filter"]/ul[1]/li[2]/a'
         cls.inactive_products = '//*[@id="changelist-filter"]/ul[1]/li[3]/a'
         cls.price_filter = '//*[@id="changelist-filter"]/ul[2]/li[3]/a'
@@ -119,10 +118,11 @@ def open_nodes(*args):
             (By.ID, self.tree_product_id)
         ))
 
-    def get_table_with_products(self):
+    def get_paginator_text(self) -> str:
+        """Contain text about table elements count."""
         return self.wait.until(EC.visibility_of_element_located(
-            (By.CLASS_NAME, self.product_table)
-        ))
+            (By.CLASS_NAME, 'paginator')
+        )).text
 
     def click_jstree_context_menu_items(self, item_index):
         def get_tree_item():
@@ -168,14 +168,12 @@ def test_image_filter(self):
         self.wait_page_loading()
 
         self.browser.find_element_by_xpath(self.filter_by_has_image).click()
-        table = self.get_table_with_products().text
-
-        self.assertTrue('1' in table)
+        paginator_text = self.get_paginator_text()
+        self.assertTrue('2' in paginator_text)
 
         self.browser.find_element_by_xpath(self.filter_by_has_not_image).click()
-        table = self.get_table_with_products().text
-
-        self.assertTrue('299' in table)
+        paginator_text = self.get_paginator_text()
+        self.assertTrue('298' in paginator_text)
 
     def test_content_filter(self):
         """Content filter is able to filter pages by the presence of the content."""
@@ -183,12 +181,12 @@ def test_content_filter(self):
         self.wait_page_loading()
 
         self.browser.find_element_by_xpath(self.filter_by_has_content).click()
-        table = self.get_table_with_products().text
+        table = self.get_paginator_text()
 
         self.assertTrue('0' in table)
 
         self.browser.find_element_by_xpath(self.filter_by_has_not_content).click()
-        table = self.get_table_with_products().text
+        table = self.get_paginator_text()
 
         self.assertTrue('300' in table)
 
diff --git a/shopelectro/tests/tests_views.py b/shopelectro/tests/tests_views.py
--- a/shopelectro/tests/tests_views.py
+++ b/shopelectro/tests/tests_views.py
@@ -28,7 +28,7 @@
 
 
 def reverse_catalog_url(
-    url: str,
+    route: str,
     route_kwargs: dict,
     tags: models.TagQuerySet=None,
     sorting: int=None,
@@ -43,7 +43,7 @@ def reverse_catalog_url(
     if sorting is not None:
         route_kwargs['sorting'] = sorting
 
-    return f'{reverse(url, kwargs=route_kwargs)}{query_string}'
+    return f'{reverse(route, kwargs=route_kwargs)}{query_string}'
 
 
 def get_page_number(response):
@@ -68,10 +68,11 @@ def get_category_page(
         tags: models.TagQuerySet=None,
         sorting: int=None,
         query_string: dict=None,
+        route='category',
     ):
         category = category or self.category
         return self.client.get(reverse_catalog_url(
-            'category', {'slug': category.page.slug}, tags, sorting, query_string,
+            route, {'slug': category.page.slug}, tags, sorting, query_string,
         ))
 
 
@@ -309,10 +310,13 @@ class LoadMore(TestCase):
 
     fixtures = ['dump.json']
     DEFAULT_LIMIT = 48
+    PRODUCT_ID_WITH_IMAGE = 114
 
     def setUp(self):
         self.category = models.Category.objects_.root_nodes().select_related('page').first()
 
+    # @todo #645:15m Reuse get_category_page method in LoadMore.load_more
+    #  BaseCatalogTestCase.get_category_page.
     def load_more(
         self,
         category: models.Category=None,
@@ -334,6 +338,14 @@ def load_more(
             'load_more', route_kwargs, tags, sorting, query_string,
         ))
 
+    def get_load_more_soup(self, *args, **kwargs) -> BeautifulSoup:
+        """Use interface of `self.load_more` method."""
+        load_more_response = self.load_more(*args, **kwargs)
+        return BeautifulSoup(
+            load_more_response.content.decode('utf-8'),
+            'html.parser'
+        )
+
     def test_pagination_numbering_first_page(self):
         self.assertEqual(get_page_number(self.load_more()), 1)
 
@@ -351,6 +363,16 @@ def test_pagination_numbering_rest_page(self):
             2,
         )
 
+    def test_image_previews(self):
+        """Load_more button should load product with image previews."""
+        load_more_soup = self.get_load_more_soup(offset=self.DEFAULT_LIMIT)
+        img_path = (
+            load_more_soup
+            .find('a', href=f'/catalog/products/{self.PRODUCT_ID_WITH_IMAGE}/')
+            .find('img')['src']
+        )
+        self.assertNotIn('logo', img_path)
+
 
 @tag('fast')
 class SitemapXML(TestCase):