From fb9abace01b6a9901ec9e4759c8f21d7f14f8216 Mon Sep 17 00:00:00 2001 From: Sage Abdullah Date: Tue, 22 Aug 2023 12:22:52 +0100 Subject: [PATCH] Add tests for passing dict list_filter and filterset_class --- .../tests/viewsets/test_model_viewset.py | 199 +++++++++++------- wagtail/test/testapp/models.py | 3 + wagtail/test/testapp/views.py | 34 ++- wagtail/test/testapp/wagtail_hooks.py | 4 +- 4 files changed, 162 insertions(+), 78 deletions(-) diff --git a/wagtail/admin/tests/viewsets/test_model_viewset.py b/wagtail/admin/tests/viewsets/test_model_viewset.py index 1054832878..784b679e62 100644 --- a/wagtail/admin/tests/viewsets/test_model_viewset.py +++ b/wagtail/admin/tests/viewsets/test_model_viewset.py @@ -157,11 +157,21 @@ class TestCustomColumns(WagtailTestUtils, TestCase): class TestListFilter(WagtailTestUtils, TestCase): + cases = { + "list": ("feature_complete_toy", "release_date", "Release date"), + "dict": ("fctoy_alt1", "name__icontains", "Name contains"), + "filterset_class": ( + "fctoy-alt2", + "release_date__year__lte", + "Release date year is less than or equal to", + ), + } + def setUp(self): self.user = self.login() - def get(self, params=None): - return self.client.get(reverse("feature_complete_toy:index"), params) + def get(self, url_namespace, params=None): + return self.client.get(reverse(f"{url_namespace}:index"), params) @classmethod def setUpTestData(cls): @@ -176,84 +186,123 @@ class TestListFilter(WagtailTestUtils, TestCase): def test_unfiltered_no_results(self): FeatureCompleteToy.objects.all().delete() - response = self.get() - self.assertContains(response, "There are no feature complete toys to display") - self.assertContains( - response, - '', - html=True, - ) - self.assertContains( - response, - '', - html=True, - ) - self.assertTemplateUsed(response, "wagtailadmin/shared/filters.html") + for case, (url_namespace, lookup, label_text) in self.cases.items(): + with self.subTest(case=case): + response = self.get(url_namespace) + self.assertTemplateUsed(response, "wagtailadmin/shared/filters.html") + self.assertContains( + response, + "There are no feature complete toys to display", + ) + self.assertNotContains( + response, + "No feature complete toys match your query", + ) + self.assertNotContains(response, "Buzz Lightyear") + self.assertNotContains(response, "Forky") + + soup = self.get_soup(response.content) + label = soup.select_one(f"label#id_{lookup}-label") + self.assertIsNotNone(label) + self.assertEqual(label.text.strip(), label_text) + input = soup.select_one(f"input#id_{lookup}") + self.assertIsNotNone(input) def test_unfiltered_with_results(self): - response = self.get() - self.assertTemplateUsed(response, "wagtailadmin/shared/filters.html") - self.assertContains(response, "Buzz Lightyear") - self.assertContains(response, "Forky") - self.assertNotContains(response, "There are 2 matches") - self.assertContains( - response, - '', - html=True, - ) - self.assertContains( - response, - '', - html=True, - ) + for case, (url_namespace, lookup, label_text) in self.cases.items(): + with self.subTest(case=case): + response = self.get(url_namespace) + self.assertTemplateUsed(response, "wagtailadmin/shared/filters.html") + self.assertContains(response, "Buzz Lightyear") + self.assertContains(response, "Forky") + self.assertNotContains(response, "There are 2 matches") + self.assertNotContains( + response, + "There are no feature complete toys to display", + ) + self.assertNotContains( + response, + "No feature complete toys match your query", + ) + + soup = self.get_soup(response.content) + label = soup.select_one(f"label#id_{lookup}-label") + self.assertIsNotNone(label) + self.assertEqual(label.text.strip(), label_text) + input = soup.select_one(f"input#id_{lookup}") + self.assertIsNotNone(input) def test_empty_filter_with_results(self): - response = self.get({"release_date": ""}) - self.assertTemplateUsed(response, "wagtailadmin/shared/filters.html") - self.assertContains(response, "Buzz Lightyear") - self.assertContains(response, "Forky") - self.assertNotContains(response, "There are 2 matches") - self.assertContains( - response, - '', - html=True, - ) - self.assertContains( - response, - '', - html=True, - ) + for case, (url_namespace, lookup, label_text) in self.cases.items(): + with self.subTest(case=case): + response = self.get(url_namespace, {lookup: ""}) + self.assertTemplateUsed(response, "wagtailadmin/shared/filters.html") + self.assertContains(response, "Buzz Lightyear") + self.assertContains(response, "Forky") + self.assertNotContains(response, "There are 2 matches") + self.assertNotContains( + response, + "No feature complete toys match your query", + ) + + soup = self.get_soup(response.content) + label = soup.select_one(f"label#id_{lookup}-label") + self.assertIsNotNone(label) + self.assertEqual(label.text.strip(), label_text) + input = soup.select_one(f"input#id_{lookup}") + self.assertIsNotNone(input) + self.assertFalse(input.attrs.get("value")) def test_filtered_no_results(self): - response = self.get({"release_date": "1970-01-01"}) - self.assertTemplateUsed(response, "wagtailadmin/shared/filters.html") - self.assertContains( - response, - "No feature complete toys match your query", - ) - self.assertContains( - response, - '', - html=True, - ) - self.assertContains( - response, - '', - html=True, - ) + lookup_values = { + "release_date": "1999-09-09", + "name__icontains": "Woody", + "release_date__year__lte": "1990", + } + for case, (url_namespace, lookup, label_text) in self.cases.items(): + with self.subTest(case=case): + value = lookup_values[lookup] + response = self.get(url_namespace, {lookup: value}) + self.assertTemplateUsed(response, "wagtailadmin/shared/filters.html") + self.assertContains( + response, + "No feature complete toys match your query", + ) + self.assertNotContains(response, "Buzz Lightyear") + self.assertNotContains(response, "Forky") + self.assertNotContains(response, "There are 2 matches") + + soup = self.get_soup(response.content) + label = soup.select_one(f"label#id_{lookup}-label") + self.assertIsNotNone(label) + self.assertEqual(label.text.strip(), label_text) + input = soup.select_one(f"input#id_{lookup}") + self.assertIsNotNone(input) + self.assertEqual(input.attrs.get("value"), value) def test_filtered_with_results(self): - response = self.get({"release_date": "1995-11-19"}) - self.assertTemplateUsed(response, "wagtailadmin/shared/filters.html") - self.assertContains(response, "Buzz Lightyear") - self.assertContains(response, "There is 1 match") - self.assertContains( - response, - '', - html=True, - ) - self.assertContains( - response, - '', - html=True, - ) + lookup_values = { + "release_date": "1995-11-19", + "name__icontains": "Ightyear", + "release_date__year__lte": "2017", + } + for case, (url_namespace, lookup, label_text) in self.cases.items(): + with self.subTest(case=case): + value = lookup_values[lookup] + response = self.get(url_namespace, {lookup: value}) + self.assertTemplateUsed(response, "wagtailadmin/shared/filters.html") + self.assertContains(response, "Buzz Lightyear") + self.assertContains(response, "There is 1 match") + self.assertNotContains(response, "Forky") + self.assertNotContains( + response, + "No feature complete toys match your query", + ) + + soup = self.get_soup(response.content) + label = soup.select_one(f"label#id_{lookup}-label") + self.assertIsNotNone(label) + self.assertEqual(label.text.strip(), label_text) + input = soup.select_one(f"input#id_{lookup}") + self.assertIsNotNone(input) + self.assertEqual(input.attrs.get("value"), value) diff --git a/wagtail/test/testapp/models.py b/wagtail/test/testapp/models.py index 8a31745f45..e8594572f9 100644 --- a/wagtail/test/testapp/models.py +++ b/wagtail/test/testapp/models.py @@ -2149,3 +2149,6 @@ class FeatureCompleteToy(models.Model): if (lowered := self.name.lower()) == lowered[::-1]: return None return False + + def __str__(self): + return f"{self.name} ({self.release_date})" diff --git a/wagtail/test/testapp/views.py b/wagtail/test/testapp/views.py index 6d6f4b0d22..737d1629a5 100644 --- a/wagtail/test/testapp/views.py +++ b/wagtail/test/testapp/views.py @@ -10,6 +10,7 @@ from django.utils.translation import gettext_lazy from wagtail.admin import messages from wagtail.admin.auth import user_passes_test +from wagtail.admin.filters import WagtailFilterSet from wagtail.admin.ui.tables import BooleanColumn, UpdatedAtColumn from wagtail.admin.views.generic import DeleteView, EditView, IndexView from wagtail.admin.viewsets.base import ViewSet, ViewSetGroup @@ -201,8 +202,39 @@ class FeatureCompleteToyViewSet(ModelViewSet): menu_label = "Feature Complete Toys" icon = "media" exclude_form_fields = () - add_to_admin_menu = True template_prefix = "customprefix/" index_template_name = "tests/fctoy_index.html" list_display = ["name", BooleanColumn("is_cool"), UpdatedAtColumn()] list_filter = ["name", "release_date"] + + +class FCToyAlt1ViewSet(ModelViewSet): + model = FeatureCompleteToy + icon = "media" + list_filter = {"name": ["icontains"]} + form_fields = ["name"] + menu_label = "FC Toys Alt 1" + + +class FCToyCustomFilterSet(WagtailFilterSet): + class Meta: + model = FeatureCompleteToy + fields = {"release_date": ["year__lte"]} + + +class ToyViewSetGroup(ModelViewSetGroup): + menu_label = "Toys" + menu_icon = "media" + + items = ( + FeatureCompleteToyViewSet, + FCToyAlt1ViewSet(name="fctoy_alt1"), + ModelViewSet( + name="fctoy-alt2", + menu_label="FC Toys Alt 2", + model=FeatureCompleteToy, + icon="media", + filterset_class=FCToyCustomFilterSet, + exclude_form_fields=(), + ), + ) diff --git a/wagtail/test/testapp/wagtail_hooks.py b/wagtail/test/testapp/wagtail_hooks.py index abbaadef8d..70a0e4f463 100644 --- a/wagtail/test/testapp/wagtail_hooks.py +++ b/wagtail/test/testapp/wagtail_hooks.py @@ -31,9 +31,9 @@ from wagtail.test.testapp.models import ( VariousOnDeleteModel, ) from wagtail.test.testapp.views import ( - FeatureCompleteToyViewSet, JSONModelViewSetGroup, MiscellaneousViewSetGroup, + ToyViewSetGroup, ) from .forms import FavouriteColourForm @@ -259,7 +259,7 @@ def register_json_model_viewsets(): @hooks.register("register_admin_viewset") def register_toy_viewset(): - return FeatureCompleteToyViewSet() + return ToyViewSetGroup() class FullFeaturedSnippetFilterSet(WagtailFilterSet):