Add tests and docs for inspect view in ModelViewSet

pull/11024/head
Sage Abdullah 2023-10-05 14:06:18 +01:00 zatwierdzone przez Matt Westcott
rodzic 9468128da5
commit aee4f42a7d
3 zmienionych plików z 141 dodań i 7 usunięć

Wyświetl plik

@ -89,12 +89,16 @@ Viewsets are Wagtail's mechanism for defining a group of related admin views wit
.. autoattribute:: export_filename
.. autoattribute:: search_fields
.. autoattribute:: search_backend_name
.. autoattribute:: inspect_view_enabled
.. autoattribute:: inspect_view_fields
.. autoattribute:: inspect_view_fields_exclude
.. autoattribute:: index_view_class
.. autoattribute:: add_view_class
.. autoattribute:: edit_view_class
.. autoattribute:: delete_view_class
.. autoattribute:: history_view_class
.. autoattribute:: usage_view_class
.. autoattribute:: history_view_class
.. autoattribute:: inspect_view_class
.. autoattribute:: template_prefix
.. autoattribute:: index_template_name
.. autoattribute:: index_results_template_name
@ -102,6 +106,7 @@ Viewsets are Wagtail's mechanism for defining a group of related admin views wit
.. autoattribute:: edit_template_name
.. autoattribute:: delete_template_name
.. autoattribute:: history_template_name
.. autoattribute:: inspect_template_name
```
## ModelViewSetGroup
@ -163,9 +168,6 @@ Viewsets are Wagtail's mechanism for defining a group of related admin views wit
.. autoattribute:: model
.. autoattribute:: chooser_per_page
.. autoattribute:: ordering
.. autoattribute:: inspect_view_enabled
.. autoattribute:: inspect_view_fields
.. autoattribute:: inspect_view_fields_exclude
.. autoattribute:: admin_url_namespace
.. autoattribute:: base_url_path
.. autoattribute:: chooser_admin_url_namespace
@ -187,7 +189,6 @@ Viewsets are Wagtail's mechanism for defining a group of related admin views wit
.. autoattribute:: lock_view_class
.. autoattribute:: unlock_view_class
.. autoattribute:: chooser_viewset_class
.. autoattribute:: inspect_template_name
.. automethod:: get_queryset
.. automethod:: get_edit_handler
.. automethod:: get_form_class

Wyświetl plik

@ -3,11 +3,12 @@ from io import BytesIO
from django.conf import settings
from django.contrib.admin.utils import quote
from django.contrib.auth import get_permission_codename
from django.contrib.auth.models import Permission
from django.contrib.contenttypes.models import ContentType
from django.test import TestCase
from django.urls import reverse
from django.utils.formats import date_format
from django.urls import NoReverseMatch, reverse
from django.utils.formats import date_format, localize
from django.utils.timezone import make_aware
from openpyxl import load_workbook
@ -761,6 +762,30 @@ class TestBreadcrumbs(AdminTemplateTestUtils, WagtailTestUtils, TestCase):
]
self.assertBreadcrumbsItemsRendered(items, response.content)
def test_inspect_view(self):
inspect_url = reverse(
"feature_complete_toy:inspect",
args=(quote(self.object.pk),),
)
response = self.client.get(inspect_url)
items = [
{
"url": reverse("feature_complete_toy:index"),
"label": "Feature complete toys",
},
{
"url": reverse(
"feature_complete_toy:edit", args=(quote(self.object.pk),)
),
"label": str(self.object),
},
{
"url": "",
"label": "Inspect",
},
]
self.assertBreadcrumbsItemsRendered(items, response.content)
class TestLegacyPatterns(WagtailTestUtils, TestCase):
# RemovedInWagtail60Warning: legacy integer pk-based URLs will be removed
@ -1036,6 +1061,105 @@ class TestUsageView(WagtailTestUtils, TestCase):
self.assertIsNotNone(usage_link)
class TestInspectView(WagtailTestUtils, TestCase):
def setUp(self):
self.user = self.login()
@classmethod
def setUpTestData(cls):
cls.object = FeatureCompleteToy.objects.create(name="Test Toy")
cls.url = reverse("feature_complete_toy:inspect", args=(quote(cls.object.pk),))
cls.edit_url = reverse(
"feature_complete_toy:edit", args=(quote(cls.object.pk),)
)
cls.delete_url = reverse(
"feature_complete_toy:delete", args=(quote(cls.object.pk),)
)
def test_simple(self):
response = self.client.get(self.url)
expected_fields = ["Strid", "Release date"]
expected_values = [
# The pk may contain whitespace at the start/end, it's hard to
# distinguish from the whitespace in the HTML so just strip it
self.object.pk.strip(),
localize(self.object.release_date),
]
self.assertEqual(response.status_code, 200)
self.assertTemplateUsed(response, "wagtailadmin/generic/inspect.html")
soup = self.get_soup(response.content)
fields = [dt.text.strip() for dt in soup.select("dt")]
values = [dd.text.strip() for dd in soup.select("dd")]
self.assertEqual(fields, expected_fields)
self.assertEqual(values, expected_values)
# One in the breadcrumb, one at the bottom
self.assertEqual(len(soup.find_all("a", attrs={"href": self.edit_url})), 2)
self.assertEqual(len(soup.find_all("a", attrs={"href": self.delete_url})), 1)
def test_inspect_view_fields(self):
# The alt1 viewset has a custom inspect_view_fields and inspect_view_fields_exclude
response = self.client.get(
reverse("fctoy_alt1:inspect", args=(quote(self.object.pk),))
)
expected_fields = ["Name"]
expected_values = ["Test Toy"]
self.assertEqual(response.status_code, 200)
self.assertTemplateUsed(response, "wagtailadmin/generic/inspect.html")
soup = self.get_soup(response.content)
fields = [dt.text.strip() for dt in soup.select("dt")]
values = [dd.text.strip() for dd in soup.select("dd")]
self.assertEqual(fields, expected_fields)
self.assertEqual(values, expected_values)
def test_disabled(self):
# An alternate viewset for the same model without inspect_view_enabled = True
with self.assertRaises(NoReverseMatch):
reverse("fctoy-alt2:inspect", args=(quote(self.object.pk),))
def test_without_permission(self):
self.user.is_superuser = False
self.user.save()
admin_permission = Permission.objects.get(
content_type__app_label="wagtailadmin", codename="access_admin"
)
self.user.user_permissions.add(admin_permission)
response = self.client.get(self.url)
self.assertEqual(response.status_code, 302)
self.assertRedirects(response, reverse("wagtailadmin_home"))
def test_only_add_permission(self):
self.user.is_superuser = False
self.user.user_permissions.add(
Permission.objects.get(
content_type__app_label="wagtailadmin", codename="access_admin"
),
Permission.objects.get(
content_type__app_label=self.object._meta.app_label,
codename=get_permission_codename("add", self.object._meta),
),
)
self.user.save()
response = self.client.get(self.url)
expected_fields = ["Strid", "Release date"]
expected_values = [
# The pk may contain whitespace at the start/end, it's hard to
# distinguish from the whitespace in the HTML so just strip it
self.object.pk.strip(),
localize(self.object.release_date),
]
self.assertEqual(response.status_code, 200)
self.assertTemplateUsed(response, "wagtailadmin/generic/inspect.html")
soup = self.get_soup(response.content)
fields = [dt.text.strip() for dt in soup.select("dt")]
values = [dd.text.strip() for dd in soup.select("dd")]
self.assertEqual(fields, expected_fields)
self.assertEqual(values, expected_values)
self.assertEqual(len(soup.find_all("a", attrs={"href": self.edit_url})), 0)
self.assertEqual(len(soup.find_all("a", attrs={"href": self.delete_url})), 0)
class TestListingButtons(WagtailTestUtils, TestCase):
def setUp(self):
self.user = self.login()
@ -1066,6 +1190,11 @@ class TestListingButtons(WagtailTestUtils, TestCase):
f"Edit '{self.object}'",
reverse("feature_complete_toy:edit", args=[quote(self.object.pk)]),
),
(
"Inspect",
f"Inspect '{self.object}'",
reverse("feature_complete_toy:inspect", args=[quote(self.object.pk)]),
),
(
"Delete",
f"Delete '{self.object}'",

Wyświetl plik

@ -213,6 +213,8 @@ class FeatureCompleteToyViewSet(ModelViewSet):
list_per_page = 5
ordering = ["name", "-release_date"]
# search_fields derived from the model
inspect_view_enabled = True
inspect_view_fields = ["strid", "release_date"]
class FCToyAlt1ViewSet(ModelViewSet):
@ -221,6 +223,8 @@ class FCToyAlt1ViewSet(ModelViewSet):
list_filter = {"name": ["icontains"]}
form_fields = ["name"]
menu_label = "FC Toys Alt 1"
inspect_view_enabled = True
inspect_view_fields_exclude = ["strid", "release_date"]
def get_index_view_kwargs(self, **kwargs):
return super().get_index_view_kwargs(is_searchable=False, **kwargs)