Initial commit
This commit is contained in:
0
env/lib/python3.10/site-packages/wagtail/admin/tests/pages/__init__.py
vendored
Normal file
0
env/lib/python3.10/site-packages/wagtail/admin/tests/pages/__init__.py
vendored
Normal file
BIN
env/lib/python3.10/site-packages/wagtail/admin/tests/pages/__pycache__/__init__.cpython-310.pyc
vendored
Normal file
BIN
env/lib/python3.10/site-packages/wagtail/admin/tests/pages/__pycache__/__init__.cpython-310.pyc
vendored
Normal file
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
BIN
env/lib/python3.10/site-packages/wagtail/admin/tests/pages/__pycache__/test_preview.cpython-310.pyc
vendored
Normal file
BIN
env/lib/python3.10/site-packages/wagtail/admin/tests/pages/__pycache__/test_preview.cpython-310.pyc
vendored
Normal file
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
0
env/lib/python3.10/site-packages/wagtail/admin/tests/pages/test_bulk_actions/__init__.py
vendored
Normal file
0
env/lib/python3.10/site-packages/wagtail/admin/tests/pages/test_bulk_actions/__init__.py
vendored
Normal file
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
34
env/lib/python3.10/site-packages/wagtail/admin/tests/pages/test_bulk_actions/test_bulk_action.py
vendored
Normal file
34
env/lib/python3.10/site-packages/wagtail/admin/tests/pages/test_bulk_actions/test_bulk_action.py
vendored
Normal file
@@ -0,0 +1,34 @@
|
||||
from django.test import TestCase
|
||||
from django.urls import reverse
|
||||
|
||||
from wagtail.test.utils import WagtailTestUtils
|
||||
|
||||
|
||||
class TestBulkActionDispatcher(WagtailTestUtils, TestCase):
|
||||
def setUp(self):
|
||||
# Login
|
||||
self.user = self.login()
|
||||
|
||||
def test_bulk_action_invalid_action(self):
|
||||
url = reverse(
|
||||
"wagtail_bulk_action",
|
||||
args=(
|
||||
"wagtailcore",
|
||||
"page",
|
||||
"ships",
|
||||
),
|
||||
)
|
||||
response = self.client.get(url)
|
||||
self.assertEqual(response.status_code, 404)
|
||||
|
||||
def test_bulk_action_invalid_model(self):
|
||||
url = reverse(
|
||||
"wagtail_bulk_action",
|
||||
args=(
|
||||
"doesnotexist",
|
||||
"doesnotexist",
|
||||
"doesnotexist",
|
||||
),
|
||||
)
|
||||
response = self.client.get(url)
|
||||
self.assertEqual(response.status_code, 404)
|
||||
364
env/lib/python3.10/site-packages/wagtail/admin/tests/pages/test_bulk_actions/test_bulk_delete.py
vendored
Normal file
364
env/lib/python3.10/site-packages/wagtail/admin/tests/pages/test_bulk_actions/test_bulk_delete.py
vendored
Normal file
@@ -0,0 +1,364 @@
|
||||
from unittest import mock
|
||||
|
||||
from django.contrib.auth.models import Permission
|
||||
from django.db.models.signals import post_delete, pre_delete
|
||||
from django.http import HttpRequest
|
||||
from django.http.response import HttpResponse
|
||||
from django.test import TestCase
|
||||
from django.urls import reverse
|
||||
|
||||
from wagtail.admin.views.pages.bulk_actions.page_bulk_action import PageBulkAction
|
||||
from wagtail.models import Page
|
||||
from wagtail.signals import page_unpublished
|
||||
from wagtail.test.testapp.models import SimplePage
|
||||
from wagtail.test.utils import WagtailTestUtils
|
||||
|
||||
|
||||
class TestBulkDelete(WagtailTestUtils, TestCase):
|
||||
def setUp(self):
|
||||
# Find root page
|
||||
self.root_page = Page.objects.get(id=2)
|
||||
|
||||
# Add child pages
|
||||
self.child_pages = [
|
||||
SimplePage(
|
||||
title=f"Hello world!-{i}", slug=f"hello-world-{i}", content=f"hello-{i}"
|
||||
)
|
||||
for i in range(1, 5)
|
||||
]
|
||||
# first three child pages will be deleted
|
||||
self.pages_to_be_deleted = self.child_pages[:3]
|
||||
self.pages_not_to_be_deleted = self.child_pages[3:]
|
||||
for child_page in self.child_pages:
|
||||
self.root_page.add_child(instance=child_page)
|
||||
|
||||
# map of the form { page: [child_pages] } to be added
|
||||
self.grandchildren_pages = {
|
||||
self.pages_to_be_deleted[0]: [
|
||||
SimplePage(
|
||||
title="Hello world!-a", slug="hello-world-a", content="hello-a"
|
||||
)
|
||||
],
|
||||
self.pages_to_be_deleted[1]: [
|
||||
SimplePage(
|
||||
title="Hello world!-b", slug="hello-world-b", content="hello-b"
|
||||
),
|
||||
SimplePage(
|
||||
title="Hello world!-c", slug="hello-world-c", content="hello-c"
|
||||
),
|
||||
],
|
||||
}
|
||||
|
||||
for child_page, grandchild_pages in self.grandchildren_pages.items():
|
||||
for grandchild_page in grandchild_pages:
|
||||
child_page.add_child(instance=grandchild_page)
|
||||
|
||||
self.url = (
|
||||
reverse(
|
||||
"wagtail_bulk_action",
|
||||
args=(
|
||||
"wagtailcore",
|
||||
"page",
|
||||
"delete",
|
||||
),
|
||||
)
|
||||
+ "?"
|
||||
)
|
||||
for child_page in self.pages_to_be_deleted:
|
||||
self.url += f"&id={child_page.id}"
|
||||
|
||||
# Login
|
||||
self.user = self.login()
|
||||
|
||||
def test_bulk_delete_get(self):
|
||||
response = self.client.get(self.url)
|
||||
self.assertEqual(response.status_code, 200)
|
||||
# deletion should not actually happen on GET
|
||||
for child_page in self.child_pages:
|
||||
self.assertTrue(SimplePage.objects.filter(id=child_page.id).exists())
|
||||
|
||||
html = response.content.decode()
|
||||
for child_page in self.pages_to_be_deleted:
|
||||
# check if the pages to be deleted and number of descendant pages are displayed
|
||||
needle = "<li>"
|
||||
needle += '<a href="{edit_page_url}" target="_blank" rel="noreferrer">{page_title}</a>'.format(
|
||||
edit_page_url=reverse("wagtailadmin_pages:edit", args=[child_page.id]),
|
||||
page_title=child_page.title,
|
||||
)
|
||||
descendants = len(self.grandchildren_pages.get(child_page, []))
|
||||
if descendants:
|
||||
needle += "<p>"
|
||||
if descendants == 1:
|
||||
needle += "This will also delete one more subpage."
|
||||
else:
|
||||
needle += f"This will also delete {descendants} more subpages."
|
||||
needle += "</p>"
|
||||
needle += "</li>"
|
||||
self.assertInHTML(needle, html)
|
||||
|
||||
def test_page_delete_specific_admin_title(self):
|
||||
response = self.client.get(self.url)
|
||||
self.assertEqual(response.status_code, 200)
|
||||
|
||||
# The number of pages to be deleted is shown on the delete confirmation page.
|
||||
self.assertContains(response, f"Delete {len(self.pages_to_be_deleted)} pages")
|
||||
|
||||
def test_page_delete_bad_permissions(self):
|
||||
# Remove privileges from user
|
||||
self.user.is_superuser = False
|
||||
self.user.user_permissions.add(
|
||||
Permission.objects.get(
|
||||
content_type__app_label="wagtailadmin", codename="access_admin"
|
||||
)
|
||||
)
|
||||
self.user.save()
|
||||
|
||||
# Get delete page
|
||||
response = self.client.get(self.url)
|
||||
|
||||
# Check that the user received a 200 redirect response
|
||||
self.assertEqual(response.status_code, 200)
|
||||
|
||||
# Check that the deletion has not happened
|
||||
for child_page in self.child_pages:
|
||||
self.assertTrue(SimplePage.objects.filter(id=child_page.id).exists())
|
||||
|
||||
html = response.content.decode()
|
||||
|
||||
self.assertInHTML(
|
||||
"<p>You don't have permission to delete these pages</p>", html
|
||||
)
|
||||
|
||||
for child_page in self.pages_to_be_deleted:
|
||||
self.assertInHTML(f"<li>{child_page.title}</li>", html)
|
||||
|
||||
self.assertTagInHTML(
|
||||
f"""<form action="{self.url}" method="POST"></form>""",
|
||||
html,
|
||||
count=0,
|
||||
)
|
||||
|
||||
def test_bulk_delete_post(self):
|
||||
# Connect a mock signal handler to page_unpublished signal
|
||||
mock_handler = mock.MagicMock()
|
||||
page_unpublished.connect(mock_handler)
|
||||
|
||||
try:
|
||||
# Post
|
||||
response = self.client.post(self.url)
|
||||
|
||||
# Should be redirected to explorer page
|
||||
self.assertEqual(response.status_code, 302)
|
||||
|
||||
# treebeard should report no consistency problems with the tree
|
||||
self.assertFalse(
|
||||
any(Page.find_problems()), msg="treebeard found consistency problems"
|
||||
)
|
||||
|
||||
# Check that the child pages to be deleted are gone
|
||||
for child_page in self.pages_to_be_deleted:
|
||||
self.assertFalse(SimplePage.objects.filter(id=child_page.id).exists())
|
||||
|
||||
# Check that the child pages not to be deleted remain
|
||||
for child_page in self.pages_not_to_be_deleted:
|
||||
self.assertTrue(SimplePage.objects.filter(id=child_page.id).exists())
|
||||
|
||||
# Check that the page_unpublished signal was fired for all pages
|
||||
num_descendants = sum(len(i) for i in self.grandchildren_pages.values())
|
||||
self.assertEqual(
|
||||
mock_handler.call_count, len(self.pages_to_be_deleted) + num_descendants
|
||||
)
|
||||
|
||||
i = 0
|
||||
for child_page in self.pages_to_be_deleted:
|
||||
mock_call = mock_handler.mock_calls[i][2]
|
||||
i += 1
|
||||
self.assertEqual(mock_call["sender"], child_page.specific_class)
|
||||
self.assertEqual(mock_call["instance"], child_page)
|
||||
self.assertIsInstance(mock_call["instance"], child_page.specific_class)
|
||||
for grandchildren_page in self.grandchildren_pages.get(child_page, []):
|
||||
mock_call = mock_handler.mock_calls[i][2]
|
||||
i += 1
|
||||
self.assertEqual(
|
||||
mock_call["sender"], grandchildren_page.specific_class
|
||||
)
|
||||
self.assertEqual(mock_call["instance"], grandchildren_page)
|
||||
self.assertIsInstance(
|
||||
mock_call["instance"], grandchildren_page.specific_class
|
||||
)
|
||||
finally:
|
||||
page_unpublished.disconnect(mock_handler)
|
||||
|
||||
def test_bulk_delete_notlive_post(self):
|
||||
# Same as above, but this makes sure the page_unpublished signal is not fired
|
||||
# for the page that is not live when it is deleted
|
||||
|
||||
# Unpublish the first child page
|
||||
page_to_be_unpublished = self.pages_to_be_deleted[0]
|
||||
page_to_be_unpublished.unpublish(user=self.user)
|
||||
|
||||
# Connect a mock signal handler to page_unpublished signal
|
||||
mock_handler = mock.MagicMock()
|
||||
page_unpublished.connect(mock_handler)
|
||||
|
||||
try:
|
||||
# Post
|
||||
response = self.client.post(self.url)
|
||||
|
||||
# Should be redirected to explorer page
|
||||
self.assertEqual(response.status_code, 302)
|
||||
|
||||
# treebeard should report no consistency problems with the tree
|
||||
self.assertFalse(
|
||||
any(Page.find_problems()), msg="treebeard found consistency problems"
|
||||
)
|
||||
|
||||
# Check that the child pages to be deleted are gone
|
||||
for child_page in self.pages_to_be_deleted:
|
||||
self.assertFalse(SimplePage.objects.filter(id=child_page.id).exists())
|
||||
|
||||
# Check that the child pages not to be deleted remain
|
||||
for child_page in self.pages_not_to_be_deleted:
|
||||
self.assertTrue(SimplePage.objects.filter(id=child_page.id).exists())
|
||||
|
||||
# Check that the page_unpublished signal was not fired
|
||||
num_descendants = sum(len(v) for v in self.grandchildren_pages.values())
|
||||
self.assertEqual(
|
||||
mock_handler.call_count,
|
||||
len(self.pages_to_be_deleted) + num_descendants - 1,
|
||||
)
|
||||
|
||||
# check that only signals for other pages are fired
|
||||
i = 0
|
||||
for child_page in self.pages_to_be_deleted:
|
||||
if child_page.id != page_to_be_unpublished.id:
|
||||
mock_call = mock_handler.mock_calls[i][2]
|
||||
i += 1
|
||||
self.assertEqual(mock_call["sender"], child_page.specific_class)
|
||||
self.assertEqual(mock_call["instance"], child_page)
|
||||
self.assertIsInstance(
|
||||
mock_call["instance"], child_page.specific_class
|
||||
)
|
||||
for grandchildren_page in self.grandchildren_pages.get(child_page, []):
|
||||
mock_call = mock_handler.mock_calls[i][2]
|
||||
i += 1
|
||||
self.assertEqual(
|
||||
mock_call["sender"], grandchildren_page.specific_class
|
||||
)
|
||||
self.assertEqual(mock_call["instance"], grandchildren_page)
|
||||
self.assertIsInstance(
|
||||
mock_call["instance"], grandchildren_page.specific_class
|
||||
)
|
||||
finally:
|
||||
page_unpublished.disconnect(mock_handler)
|
||||
|
||||
def test_subpage_deletion(self):
|
||||
# Connect mock signal handlers to page_unpublished, pre_delete and post_delete signals
|
||||
unpublish_signals_received = []
|
||||
pre_delete_signals_received = []
|
||||
post_delete_signals_received = []
|
||||
|
||||
def page_unpublished_handler(sender, instance, **kwargs):
|
||||
unpublish_signals_received.append((sender, instance.pk))
|
||||
|
||||
def pre_delete_handler(sender, instance, **kwargs):
|
||||
pre_delete_signals_received.append((sender, instance.pk))
|
||||
|
||||
def post_delete_handler(sender, instance, **kwargs):
|
||||
post_delete_signals_received.append((sender, instance.pk))
|
||||
|
||||
page_unpublished.connect(page_unpublished_handler)
|
||||
pre_delete.connect(pre_delete_handler)
|
||||
post_delete.connect(post_delete_handler)
|
||||
|
||||
try:
|
||||
# Post
|
||||
response = self.client.post(self.url)
|
||||
|
||||
# Should be redirected to explorer page
|
||||
self.assertEqual(response.status_code, 302)
|
||||
|
||||
# treebeard should report no consistency problems with the tree
|
||||
self.assertFalse(
|
||||
any(Page.find_problems()), msg="treebeard found consistency problems"
|
||||
)
|
||||
|
||||
# Check that the child pages to be deleted are gone
|
||||
for child_page in self.pages_to_be_deleted:
|
||||
self.assertFalse(SimplePage.objects.filter(id=child_page.id).exists())
|
||||
|
||||
# Check that the child pages not to be deleted remain
|
||||
for child_page in self.pages_not_to_be_deleted:
|
||||
self.assertTrue(SimplePage.objects.filter(id=child_page.id).exists())
|
||||
|
||||
# Check that the subpages are also gone
|
||||
for grandchild_pages in self.grandchildren_pages.values():
|
||||
for grandchild_page in grandchild_pages:
|
||||
self.assertFalse(
|
||||
SimplePage.objects.filter(id=grandchild_page.id).exists()
|
||||
)
|
||||
|
||||
# Check that the signals were fired for all child and grandchild pages
|
||||
for child_page, grandchild_pages in self.grandchildren_pages.items():
|
||||
self.assertIn((SimplePage, child_page.id), unpublish_signals_received)
|
||||
self.assertIn((SimplePage, child_page.id), pre_delete_signals_received)
|
||||
self.assertIn((SimplePage, child_page.id), post_delete_signals_received)
|
||||
for grandchild_page in grandchild_pages:
|
||||
self.assertIn(
|
||||
(SimplePage, grandchild_page.id), unpublish_signals_received
|
||||
)
|
||||
self.assertIn(
|
||||
(SimplePage, grandchild_page.id), pre_delete_signals_received
|
||||
)
|
||||
self.assertIn(
|
||||
(SimplePage, grandchild_page.id), post_delete_signals_received
|
||||
)
|
||||
|
||||
self.assertEqual(response.status_code, 302)
|
||||
finally:
|
||||
page_unpublished.disconnect(page_unpublished_handler)
|
||||
pre_delete.disconnect(pre_delete_handler)
|
||||
post_delete.disconnect(post_delete_handler)
|
||||
|
||||
def test_before_delete_page_hook(self):
|
||||
def hook_func(request, action_type, pages, action_class_instance):
|
||||
self.assertEqual(action_type, "delete")
|
||||
self.assertIsInstance(request, HttpRequest)
|
||||
self.assertIsInstance(action_class_instance, PageBulkAction)
|
||||
for i, page in enumerate(pages):
|
||||
self.assertEqual(page.id, self.pages_to_be_deleted[i].id)
|
||||
return HttpResponse("Overridden!")
|
||||
|
||||
with self.register_hook("before_bulk_action", hook_func):
|
||||
response = self.client.post(self.url)
|
||||
|
||||
self.assertEqual(response.status_code, 200)
|
||||
self.assertEqual(response.content, b"Overridden!")
|
||||
|
||||
# Check that the child pages are not deleted
|
||||
for child_page in self.child_pages:
|
||||
self.assertTrue(SimplePage.objects.filter(id=child_page.id).exists())
|
||||
|
||||
def test_after_delete_page_hook(self):
|
||||
def hook_func(request, action_type, pages, action_class_instance):
|
||||
self.assertEqual(action_type, "delete")
|
||||
self.assertIsInstance(request, HttpRequest)
|
||||
self.assertIsInstance(action_class_instance, PageBulkAction)
|
||||
for i, page in enumerate(pages):
|
||||
self.assertEqual(page.id, self.pages_to_be_deleted[i].id)
|
||||
|
||||
return HttpResponse("Overridden!")
|
||||
|
||||
with self.register_hook("after_bulk_action", hook_func):
|
||||
response = self.client.post(self.url)
|
||||
|
||||
self.assertEqual(response.status_code, 200)
|
||||
self.assertEqual(response.content, b"Overridden!")
|
||||
|
||||
# Check that the child pages to be deleted are gone
|
||||
for child_page in self.pages_to_be_deleted:
|
||||
self.assertFalse(SimplePage.objects.filter(id=child_page.id).exists())
|
||||
|
||||
# Check that the child pages not to be deleted remain
|
||||
for child_page in self.pages_not_to_be_deleted:
|
||||
self.assertTrue(SimplePage.objects.filter(id=child_page.id).exists())
|
||||
321
env/lib/python3.10/site-packages/wagtail/admin/tests/pages/test_bulk_actions/test_bulk_move.py
vendored
Normal file
321
env/lib/python3.10/site-packages/wagtail/admin/tests/pages/test_bulk_actions/test_bulk_move.py
vendored
Normal file
@@ -0,0 +1,321 @@
|
||||
from unittest import mock
|
||||
|
||||
from django.contrib.auth import get_user_model
|
||||
from django.contrib.auth.models import Permission
|
||||
from django.http import HttpRequest, HttpResponse
|
||||
from django.test import TestCase
|
||||
from django.urls import reverse
|
||||
|
||||
from wagtail.admin.views.pages.bulk_actions.page_bulk_action import PageBulkAction
|
||||
from wagtail.models import Page
|
||||
from wagtail.signals import post_page_move, pre_page_move
|
||||
from wagtail.test.testapp.models import BusinessChild, SimplePage
|
||||
from wagtail.test.utils import WagtailTestUtils
|
||||
|
||||
|
||||
class TestBulkMove(WagtailTestUtils, TestCase):
|
||||
fixtures = ["test.json"]
|
||||
|
||||
def setUp(self):
|
||||
# Find root page
|
||||
self.root_page = Page.objects.get(id=2)
|
||||
|
||||
# Create three sections
|
||||
self.section_a = SimplePage(
|
||||
title="Section A", slug="section-a", content="hello"
|
||||
)
|
||||
self.root_page.add_child(instance=self.section_a)
|
||||
|
||||
self.section_b = SimplePage(
|
||||
title="Section B", slug="section-b", content="hello"
|
||||
)
|
||||
self.root_page.add_child(instance=self.section_b)
|
||||
|
||||
self.section_c = SimplePage(
|
||||
title="Section C", slug="section-c", content="hello"
|
||||
)
|
||||
self.root_page.add_child(instance=self.section_c)
|
||||
|
||||
# Add test page A into section A
|
||||
self.test_page_a = SimplePage(
|
||||
title="Hello world!", slug="hello-world-a", content="hello"
|
||||
)
|
||||
self.section_a.add_child(instance=self.test_page_a)
|
||||
|
||||
# Add test page B into section C
|
||||
self.test_page_b = SimplePage(
|
||||
title="Hello world!", slug="hello-world-b", content="hello"
|
||||
)
|
||||
self.section_c.add_child(instance=self.test_page_b)
|
||||
|
||||
# Add test page B_1 into section C
|
||||
self.test_page_b_1 = SimplePage(
|
||||
title="Hello world!", slug="hello-world-b-1", content="hello"
|
||||
)
|
||||
self.section_c.add_child(instance=self.test_page_b_1)
|
||||
|
||||
# Add test page A_1 into section C having same slug as test page A
|
||||
self.test_page_a_1 = SimplePage(
|
||||
title="Hello world!", slug="hello-world-a", content="hello"
|
||||
)
|
||||
self.section_c.add_child(instance=self.test_page_a_1)
|
||||
|
||||
# Add unpublished page to the root with a child page
|
||||
self.unpublished_page = SimplePage(
|
||||
title="Unpublished", slug="unpublished", content="hello"
|
||||
)
|
||||
sub_page = SimplePage(title="Sub Page", slug="sub-page", content="child")
|
||||
self.root_page.add_child(instance=self.unpublished_page)
|
||||
self.unpublished_page.add_child(instance=sub_page)
|
||||
|
||||
# unpublish pages last (used to validate the edit only permission)
|
||||
self.unpublished_page.unpublish()
|
||||
sub_page.unpublish()
|
||||
|
||||
self.pages_to_be_moved = [self.test_page_b, self.test_page_b_1]
|
||||
|
||||
self.url = (
|
||||
reverse(
|
||||
"wagtail_bulk_action",
|
||||
args=(
|
||||
"wagtailcore",
|
||||
"page",
|
||||
"move",
|
||||
),
|
||||
)
|
||||
+ f"?id={self.test_page_b.id}&id={self.test_page_b_1.id}"
|
||||
)
|
||||
|
||||
# Login
|
||||
self.user = self.login()
|
||||
|
||||
def test_bulk_move(self):
|
||||
response = self.client.get(self.url)
|
||||
self.assertEqual(response.status_code, 200)
|
||||
|
||||
html = response.content.decode()
|
||||
|
||||
self.assertInHTML("<p>Are you sure you want to move these pages?</p>", html)
|
||||
|
||||
self.assertInHTML(
|
||||
'<li><a href="{edit_page_url}" target="_blank" rel="noreferrer">Hello world! (simple page)</a></li>'.format(
|
||||
edit_page_url=reverse(
|
||||
"wagtailadmin_pages:edit", args=[self.test_page_b.id]
|
||||
),
|
||||
),
|
||||
html,
|
||||
)
|
||||
|
||||
def test_bulk_move_bad_permissions(self):
|
||||
# Remove privileges from user
|
||||
self.user.is_superuser = False
|
||||
self.user.user_permissions.add(
|
||||
Permission.objects.get(
|
||||
content_type__app_label="wagtailadmin", codename="access_admin"
|
||||
)
|
||||
)
|
||||
self.user.save()
|
||||
|
||||
# Get move page
|
||||
response = self.client.get(self.url)
|
||||
|
||||
self.assertEqual(response.status_code, 200)
|
||||
|
||||
html = response.content.decode()
|
||||
|
||||
self.assertInHTML("<p>You don't have permission to move these pages</p>", html)
|
||||
|
||||
for child_page in self.pages_to_be_moved:
|
||||
self.assertInHTML(f"<li>{child_page.title}</li>", html)
|
||||
|
||||
self.assertTagInHTML(
|
||||
f"""<form action="{self.url}" method="POST"></form>""",
|
||||
html,
|
||||
count=0,
|
||||
)
|
||||
|
||||
def test_user_without_bulk_delete_permission_can_move(self):
|
||||
# to verify that a user without bulk delete permission is able to move a page with a child page
|
||||
|
||||
self.client.logout()
|
||||
user = get_user_model().objects.get(email="siteeditor@example.com")
|
||||
self.login(user)
|
||||
|
||||
# ensure the bulk_delete is not applicable to this user
|
||||
can_bulk_delete = self.test_page_b.permissions_for_user(user).can_delete()
|
||||
self.assertFalse(can_bulk_delete)
|
||||
|
||||
response = self.client.get(
|
||||
reverse(
|
||||
"wagtail_bulk_action",
|
||||
args=(
|
||||
"wagtailcore",
|
||||
"page",
|
||||
"move",
|
||||
),
|
||||
)
|
||||
+ f"?id={self.unpublished_page.id}"
|
||||
)
|
||||
|
||||
self.assertEqual(response.status_code, 200)
|
||||
|
||||
def test_bulk_move_destination_not_allowed(self):
|
||||
page = BusinessChild(title="Section no child", slug="section-no-child")
|
||||
self.root_page.add_child(instance=page)
|
||||
|
||||
response = self.client.post(self.url, {"chooser": page.id})
|
||||
|
||||
html = response.content.decode()
|
||||
|
||||
self.assertInHTML(
|
||||
f"<p>The following pages cannot be moved to {page.title}</p>", html
|
||||
)
|
||||
|
||||
for child_page in self.pages_to_be_moved:
|
||||
self.assertInHTML(
|
||||
'<li><a href="{edit_page_url}" target="_blank" rel="noreferrer">{page_title}</a></li>'.format(
|
||||
edit_page_url=reverse(
|
||||
"wagtailadmin_pages:edit", args=[child_page.id]
|
||||
),
|
||||
page_title=child_page.title,
|
||||
),
|
||||
html,
|
||||
)
|
||||
|
||||
def test_bulk_move_slug_already_taken(self):
|
||||
temp_page_1 = SimplePage(
|
||||
title="Hello world!", slug="hello-world-b", content="hello"
|
||||
)
|
||||
temp_page_2 = SimplePage(
|
||||
title="Hello world!", slug="hello-world-b-1", content="hello"
|
||||
)
|
||||
self.section_b.add_child(instance=temp_page_1)
|
||||
self.section_b.add_child(instance=temp_page_2)
|
||||
|
||||
response = self.client.post(self.url, {"chooser": self.section_b.id})
|
||||
|
||||
html = response.content.decode()
|
||||
|
||||
self.assertInHTML(
|
||||
"<p>The following pages cannot be moved due to duplicate slugs</p>", html
|
||||
)
|
||||
|
||||
for child_page in self.pages_to_be_moved:
|
||||
self.assertInHTML(
|
||||
'<li><a href="{edit_page_url}" target="_blank" rel="noreferrer">{page_title}</a></li>'.format(
|
||||
edit_page_url=reverse(
|
||||
"wagtailadmin_pages:edit", args=[child_page.id]
|
||||
),
|
||||
page_title=child_page.title,
|
||||
),
|
||||
html,
|
||||
)
|
||||
|
||||
def test_bulk_move_triggers_signals(self):
|
||||
# Connect a mock signal handler to pre_page_move and post_page_move signals
|
||||
pre_moved_handler = mock.MagicMock()
|
||||
post_moved_handler = mock.MagicMock()
|
||||
|
||||
pre_page_move.connect(pre_moved_handler)
|
||||
post_page_move.connect(post_moved_handler)
|
||||
|
||||
# Post to view confirm move page
|
||||
try:
|
||||
self.client.post(self.url, {"chooser": self.section_b.id})
|
||||
finally:
|
||||
# Disconnect mock handler to prevent cross-test pollution
|
||||
pre_page_move.disconnect(pre_moved_handler)
|
||||
post_page_move.disconnect(post_moved_handler)
|
||||
|
||||
# Check that the pre_page_move signals were fired
|
||||
self.assertTrue(
|
||||
pre_moved_handler.mock_calls[0].called_with(
|
||||
sender=self.test_page_b.specific_class,
|
||||
instance=self.test_page_b,
|
||||
parent_page_before=self.section_c,
|
||||
parent_page_after=self.section_b,
|
||||
url_path_before="/home/section-c/hello-world-b/",
|
||||
url_path_after="/home/section-b/hello-world-b/",
|
||||
)
|
||||
)
|
||||
self.assertTrue(
|
||||
pre_moved_handler.mock_calls[1].called_with(
|
||||
sender=self.test_page_b_1.specific_class,
|
||||
instance=self.test_page_b_1,
|
||||
parent_page_before=self.section_c,
|
||||
parent_page_after=self.section_b,
|
||||
url_path_before="/home/section-c/hello-world-b-1/",
|
||||
url_path_after="/home/section-b/hello-world-b-1/",
|
||||
)
|
||||
)
|
||||
|
||||
# Check that the post_page_move signals were fired
|
||||
self.assertTrue(
|
||||
post_moved_handler.mock_calls[0].called_with(
|
||||
sender=self.test_page_b.specific_class,
|
||||
instance=self.test_page_b,
|
||||
parent_page_before=self.section_c,
|
||||
parent_page_after=self.section_b,
|
||||
url_path_before="/home/section-c/hello-world-b/",
|
||||
url_path_after="/home/section-b/hello-world-b/",
|
||||
)
|
||||
)
|
||||
self.assertTrue(
|
||||
post_moved_handler.mock_calls[1].called_with(
|
||||
sender=self.test_page_b_1.specific_class,
|
||||
instance=self.test_page_b_1,
|
||||
parent_page_before=self.section_c,
|
||||
parent_page_after=self.section_b,
|
||||
url_path_before="/home/section-c/hello-world-b-1/",
|
||||
url_path_after="/home/section-b/hello-world-b-1/",
|
||||
)
|
||||
)
|
||||
|
||||
def test_before_bulk_move_hook(self):
|
||||
def hook_func(request, action_type, pages, action_class_instance):
|
||||
self.assertEqual(action_type, "move")
|
||||
self.assertIsInstance(request, HttpRequest)
|
||||
self.assertIsInstance(action_class_instance, PageBulkAction)
|
||||
for i, page in enumerate(pages):
|
||||
self.assertEqual(page.id, self.pages_to_be_moved[i].id)
|
||||
|
||||
return HttpResponse("Overridden!")
|
||||
|
||||
with self.register_hook("before_bulk_action", hook_func):
|
||||
response = self.client.post(self.url, {"chooser": self.section_b.id})
|
||||
|
||||
self.assertEqual(response.status_code, 200)
|
||||
self.assertEqual(response.content, b"Overridden!")
|
||||
|
||||
self.assertEqual(
|
||||
Page.objects.get(id=self.test_page_b.id).get_parent().id, self.section_c.id
|
||||
)
|
||||
self.assertEqual(
|
||||
Page.objects.get(id=self.test_page_b_1.id).get_parent().id,
|
||||
self.section_c.id,
|
||||
)
|
||||
|
||||
def test_after_bulk_move_hook(self):
|
||||
def hook_func(request, action_type, pages, action_class_instance):
|
||||
self.assertEqual(action_type, "move")
|
||||
self.assertIsInstance(request, HttpRequest)
|
||||
self.assertIsInstance(action_class_instance, PageBulkAction)
|
||||
for i, page in enumerate(pages):
|
||||
self.assertEqual(page.id, self.pages_to_be_moved[i].id)
|
||||
|
||||
return HttpResponse("Overridden!")
|
||||
|
||||
with self.register_hook("after_bulk_action", hook_func):
|
||||
response = self.client.post(self.url, {"chooser": self.section_b.id})
|
||||
|
||||
self.assertEqual(response.status_code, 200)
|
||||
self.assertEqual(response.content, b"Overridden!")
|
||||
|
||||
# pages should be moved
|
||||
self.assertEqual(
|
||||
Page.objects.get(id=self.test_page_b.id).get_parent().id, self.section_b.id
|
||||
)
|
||||
self.assertEqual(
|
||||
Page.objects.get(id=self.test_page_b_1.id).get_parent().id,
|
||||
self.section_b.id,
|
||||
)
|
||||
381
env/lib/python3.10/site-packages/wagtail/admin/tests/pages/test_bulk_actions/test_bulk_publish.py
vendored
Normal file
381
env/lib/python3.10/site-packages/wagtail/admin/tests/pages/test_bulk_actions/test_bulk_publish.py
vendored
Normal file
@@ -0,0 +1,381 @@
|
||||
from unittest import mock
|
||||
|
||||
from django.contrib.auth.models import Permission
|
||||
from django.http import HttpRequest, HttpResponse
|
||||
from django.test import TestCase
|
||||
from django.urls import reverse
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
|
||||
from wagtail.admin.views.pages.bulk_actions.page_bulk_action import PageBulkAction
|
||||
from wagtail.models import Page
|
||||
from wagtail.signals import page_published
|
||||
from wagtail.test.testapp.models import SimplePage
|
||||
from wagtail.test.utils import WagtailTestUtils
|
||||
|
||||
|
||||
class TestBulkPublish(WagtailTestUtils, TestCase):
|
||||
def setUp(self):
|
||||
self.root_page = Page.objects.get(id=2)
|
||||
|
||||
# Add child pages which will have already been published before we
|
||||
# bulk publish them.
|
||||
self.child_pages = [
|
||||
SimplePage(
|
||||
title=f"Hello world!-{i}",
|
||||
slug=f"hello-world-{i}",
|
||||
content=f"Hello world {i}!",
|
||||
live=False,
|
||||
)
|
||||
for i in range(1, 5)
|
||||
]
|
||||
|
||||
self.pages_to_be_published = self.child_pages[:3]
|
||||
self.pages_not_to_be_published = self.child_pages[3:]
|
||||
|
||||
for child_page in self.child_pages:
|
||||
self.root_page.add_child(instance=child_page)
|
||||
|
||||
for i, child_page in enumerate(self.child_pages):
|
||||
child_page.content = f"Hello published world {i}!"
|
||||
child_page.save_revision()
|
||||
|
||||
# Add an additional child page which will be bulk published from a
|
||||
# draft-only state.
|
||||
draft_page = SimplePage(
|
||||
title="Hello world!-5",
|
||||
slug="hello-world-5",
|
||||
content="Hello published world 5!",
|
||||
live=False,
|
||||
)
|
||||
|
||||
self.root_page.add_child(instance=draft_page)
|
||||
self.child_pages.append(draft_page)
|
||||
self.pages_to_be_published.append(draft_page)
|
||||
|
||||
self.url = (
|
||||
reverse(
|
||||
"wagtail_bulk_action",
|
||||
args=(
|
||||
"wagtailcore",
|
||||
"page",
|
||||
"publish",
|
||||
),
|
||||
)
|
||||
+ "?"
|
||||
)
|
||||
for child_page in self.pages_to_be_published:
|
||||
self.url += f"id={child_page.id}&"
|
||||
self.redirect_url = reverse("wagtailadmin_explore", args=(self.root_page.id,))
|
||||
|
||||
self.user = self.login()
|
||||
|
||||
def test_publish_view(self):
|
||||
"""
|
||||
This tests that the publish view responds with a publish confirm page
|
||||
"""
|
||||
# Request confirm publish page
|
||||
response = self.client.get(self.url)
|
||||
|
||||
# # Check that the user received a publish confirm page
|
||||
self.assertEqual(response.status_code, 200)
|
||||
self.assertTemplateUsed(
|
||||
response, "wagtailadmin/pages/bulk_actions/confirm_bulk_publish.html"
|
||||
)
|
||||
|
||||
# Page titles shown on the confirmation page should use SimplePage's custom get_admin_display_title method
|
||||
self.assertContains(response, "Hello world!-1 (simple page)")
|
||||
|
||||
def test_publish_view_invalid_page_id(self):
|
||||
"""
|
||||
This tests that the publish view returns an error if the page id is invalid
|
||||
"""
|
||||
# Request confirm publish page but with illegal page id
|
||||
response = self.client.get(
|
||||
reverse(
|
||||
"wagtail_bulk_action",
|
||||
args=(
|
||||
"wagtailcore",
|
||||
"page",
|
||||
"publish",
|
||||
),
|
||||
)
|
||||
)
|
||||
|
||||
# Check that the user received a 404 response
|
||||
self.assertEqual(response.status_code, 404)
|
||||
|
||||
def test_publish_view_bad_permissions(self):
|
||||
"""
|
||||
This tests that the publish view doesn't allow users without publish permissions
|
||||
"""
|
||||
# Remove privileges from user
|
||||
self.user.is_superuser = False
|
||||
self.user.user_permissions.add(
|
||||
Permission.objects.get(
|
||||
content_type__app_label="wagtailadmin", codename="access_admin"
|
||||
)
|
||||
)
|
||||
self.user.save()
|
||||
|
||||
# Request confirm publish page
|
||||
response = self.client.get(self.url)
|
||||
|
||||
# Check that the user received a 200 redirected response
|
||||
self.assertEqual(response.status_code, 200)
|
||||
|
||||
html = response.content.decode()
|
||||
|
||||
self.assertInHTML(
|
||||
"<p>You don't have permission to publish these pages</p>", html
|
||||
)
|
||||
|
||||
for child_page in self.pages_to_be_published:
|
||||
self.assertInHTML(f"<li>{child_page.title}</li>", html)
|
||||
|
||||
def test_publish_view_post(self):
|
||||
"""
|
||||
This posts to the publish view and checks that the page was published
|
||||
"""
|
||||
# Connect a mock signal handler to page_published signal
|
||||
mock_handler = mock.MagicMock()
|
||||
page_published.connect(mock_handler)
|
||||
|
||||
try:
|
||||
# Post to the publish page
|
||||
response = self.client.post(self.url)
|
||||
|
||||
# Should be redirected to explorer page
|
||||
self.assertEqual(response.status_code, 302)
|
||||
|
||||
# Check that the child pages were published
|
||||
for child_page in self.pages_to_be_published:
|
||||
published_page = SimplePage.objects.get(id=child_page.id)
|
||||
self.assertTrue(published_page.live)
|
||||
self.assertIn("Hello published", published_page.content)
|
||||
|
||||
# Check that the child pages not to be published remain
|
||||
for child_page in self.pages_not_to_be_published:
|
||||
self.assertFalse(Page.objects.get(id=child_page.id).live)
|
||||
|
||||
# Check that the page_published signal was fired
|
||||
self.assertEqual(mock_handler.call_count, len(self.pages_to_be_published))
|
||||
|
||||
for i, child_page in enumerate(self.pages_to_be_published):
|
||||
mock_call = mock_handler.mock_calls[i][2]
|
||||
self.assertEqual(mock_call["sender"], child_page.specific_class)
|
||||
self.assertEqual(mock_call["instance"], child_page)
|
||||
self.assertIsInstance(mock_call["instance"], child_page.specific_class)
|
||||
finally:
|
||||
page_published.disconnect(mock_handler)
|
||||
|
||||
def test_after_publish_page(self):
|
||||
def hook_func(request, action_type, pages, action_class_instance):
|
||||
self.assertEqual(action_type, "publish")
|
||||
self.assertIsInstance(request, HttpRequest)
|
||||
self.assertIsInstance(action_class_instance, PageBulkAction)
|
||||
for i, page in enumerate(pages):
|
||||
self.assertEqual(page.id, self.pages_to_be_published[i].id)
|
||||
|
||||
return HttpResponse("Overridden!")
|
||||
|
||||
with self.register_hook("after_bulk_action", hook_func):
|
||||
response = self.client.post(self.url)
|
||||
|
||||
self.assertEqual(response.status_code, 200)
|
||||
self.assertEqual(response.content, b"Overridden!")
|
||||
|
||||
for child_page in self.pages_to_be_published:
|
||||
child_page.refresh_from_db()
|
||||
self.assertEqual(child_page.status_string, _("live"))
|
||||
|
||||
def test_before_publish_page(self):
|
||||
def hook_func(request, action_type, pages, action_class_instance):
|
||||
self.assertEqual(action_type, "publish")
|
||||
self.assertIsInstance(request, HttpRequest)
|
||||
self.assertIsInstance(action_class_instance, PageBulkAction)
|
||||
for i, page in enumerate(pages):
|
||||
self.assertEqual(page.id, self.pages_to_be_published[i].id)
|
||||
|
||||
return HttpResponse("Overridden!")
|
||||
|
||||
with self.register_hook("before_bulk_action", hook_func):
|
||||
response = self.client.post(self.url)
|
||||
|
||||
self.assertEqual(response.status_code, 200)
|
||||
self.assertEqual(response.content, b"Overridden!")
|
||||
|
||||
def test_publish_descendants_view(self):
|
||||
"""
|
||||
This tests that the publish view responds with a publish confirm page that does not contain the form field 'include_descendants'
|
||||
"""
|
||||
# Get publish page for page with no descendants
|
||||
response = self.client.get(self.url)
|
||||
|
||||
# Check that the user received a publish confirm page
|
||||
self.assertEqual(response.status_code, 200)
|
||||
self.assertTemplateUsed(
|
||||
response, "wagtailadmin/pages/bulk_actions/confirm_bulk_publish.html"
|
||||
)
|
||||
# Check the form does not contain the checkbox field include_descendants
|
||||
self.assertNotContains(
|
||||
response,
|
||||
'name="include_descendants"',
|
||||
)
|
||||
|
||||
|
||||
class TestBulkPublishIncludingDescendants(WagtailTestUtils, TestCase):
|
||||
def setUp(self):
|
||||
self.root_page = Page.objects.get(id=2)
|
||||
|
||||
# Add child pages
|
||||
self.child_pages = [
|
||||
SimplePage(
|
||||
title=f"Hello world!-{i}",
|
||||
slug=f"hello-world-{i}",
|
||||
content=f"Hello world {i}!",
|
||||
live=False,
|
||||
)
|
||||
for i in range(1, 5)
|
||||
]
|
||||
self.pages_to_be_published = self.child_pages[:3]
|
||||
self.pages_not_to_be_published = self.child_pages[3:]
|
||||
|
||||
for child_page in self.child_pages:
|
||||
self.root_page.add_child(instance=child_page)
|
||||
|
||||
for i, child_page in enumerate(self.child_pages):
|
||||
child_page.content = f"Hello updated world {i}!"
|
||||
child_page.save_revision()
|
||||
|
||||
# Add grandchild pages which will have already been published before
|
||||
# we bulk publish them.
|
||||
# map of the form { page: [child_pages] } to be added
|
||||
self.grandchildren_pages = {
|
||||
self.pages_to_be_published[0]: [
|
||||
SimplePage(
|
||||
title="Hello world!-a",
|
||||
slug="hello-world-a",
|
||||
content="Hello world a!",
|
||||
live=False,
|
||||
)
|
||||
],
|
||||
self.pages_to_be_published[1]: [
|
||||
SimplePage(
|
||||
title="Hello world!-b",
|
||||
slug="hello-world-b",
|
||||
content="Hello world b!",
|
||||
live=False,
|
||||
),
|
||||
SimplePage(
|
||||
title="Hello world!-c",
|
||||
slug="hello-world-c",
|
||||
content="Hello world c!",
|
||||
live=False,
|
||||
),
|
||||
],
|
||||
}
|
||||
for child_page, grandchild_pages in self.grandchildren_pages.items():
|
||||
for grandchild_page in grandchild_pages:
|
||||
child_page.add_child(instance=grandchild_page)
|
||||
|
||||
for child_page, grandchild_pages in self.grandchildren_pages.items():
|
||||
for grandchild_page in grandchild_pages:
|
||||
grandchild_page.content = grandchild_page.content.replace(
|
||||
"Hello world", "Hello grandchild"
|
||||
)
|
||||
grandchild_page.save_revision()
|
||||
|
||||
# Add an additional grandchild page which will be bulk published from
|
||||
# a draft-only state.
|
||||
draft_page = SimplePage(
|
||||
title="Hello world!-d",
|
||||
slug="hello-world-d",
|
||||
content="Hello grandchild d!",
|
||||
live=False,
|
||||
)
|
||||
|
||||
self.pages_to_be_published[1].add_child(instance=draft_page)
|
||||
self.grandchildren_pages[self.pages_to_be_published[1]].append(draft_page)
|
||||
|
||||
self.url = (
|
||||
reverse(
|
||||
"wagtail_bulk_action",
|
||||
args=(
|
||||
"wagtailcore",
|
||||
"page",
|
||||
"publish",
|
||||
),
|
||||
)
|
||||
+ "?"
|
||||
)
|
||||
for child_page in self.pages_to_be_published:
|
||||
self.url += f"&id={child_page.id}"
|
||||
|
||||
self.user = self.login()
|
||||
|
||||
def test_publish_descendants_view(self):
|
||||
"""
|
||||
This tests that the publish view responds with a publish confirm page that contains the form field 'include_descendants'
|
||||
"""
|
||||
# Get publish page
|
||||
response = self.client.get(self.url)
|
||||
|
||||
# Check that the user received a publish confirm page
|
||||
self.assertEqual(response.status_code, 200)
|
||||
self.assertTemplateUsed(
|
||||
response, "wagtailadmin/pages/bulk_actions/confirm_bulk_publish.html"
|
||||
)
|
||||
# Check the form contains the checkbox field include_descendants
|
||||
self.assertContains(
|
||||
response,
|
||||
'name="include_descendants"',
|
||||
)
|
||||
|
||||
def test_publish_include_children_view_post(self):
|
||||
"""
|
||||
This posts to the publish view and checks that the page and its descendants were published
|
||||
"""
|
||||
# Post to the publish page
|
||||
response = self.client.post(self.url, {"include_descendants": "on"})
|
||||
|
||||
# Should be redirected to explorer page
|
||||
self.assertEqual(response.status_code, 302)
|
||||
|
||||
# Check that the child pages were published
|
||||
for child_page in self.pages_to_be_published:
|
||||
published_child_page = SimplePage.objects.get(id=child_page.id)
|
||||
self.assertTrue(published_child_page.live)
|
||||
self.assertIn("Hello updated", published_child_page.content)
|
||||
|
||||
# Check that the child pages not to be published remain
|
||||
for child_page in self.pages_not_to_be_published:
|
||||
self.assertFalse(Page.objects.get(id=child_page.id).live)
|
||||
|
||||
for grandchild_pages in self.grandchildren_pages.values():
|
||||
for grandchild_page in grandchild_pages:
|
||||
published_grandchild_page = SimplePage.objects.get(
|
||||
id=grandchild_page.id
|
||||
)
|
||||
self.assertTrue(published_grandchild_page.live)
|
||||
self.assertIn("Hello grandchild", published_grandchild_page.content)
|
||||
|
||||
def test_publish_not_include_children_view_post(self):
|
||||
"""
|
||||
This posts to the publish view and checks that the page was published but its descendants were not
|
||||
"""
|
||||
# Post to the publish page
|
||||
response = self.client.post(self.url, {})
|
||||
|
||||
# Should be redirected to explorer page
|
||||
self.assertEqual(response.status_code, 302)
|
||||
|
||||
# Check that the child pages were published
|
||||
for child_page in self.pages_to_be_published:
|
||||
published_child_page = SimplePage.objects.get(id=child_page.id)
|
||||
self.assertTrue(published_child_page.live)
|
||||
self.assertIn("Hello updated", published_child_page.content)
|
||||
|
||||
# Check that the descendant pages were not published
|
||||
for grandchild_pages in self.grandchildren_pages.values():
|
||||
for grandchild_page in grandchild_pages:
|
||||
self.assertFalse(Page.objects.get(id=grandchild_page.id).live)
|
||||
312
env/lib/python3.10/site-packages/wagtail/admin/tests/pages/test_bulk_actions/test_bulk_unpublish.py
vendored
Normal file
312
env/lib/python3.10/site-packages/wagtail/admin/tests/pages/test_bulk_actions/test_bulk_unpublish.py
vendored
Normal file
@@ -0,0 +1,312 @@
|
||||
from unittest import mock
|
||||
|
||||
from django.contrib.auth.models import Permission
|
||||
from django.http import HttpRequest, HttpResponse
|
||||
from django.test import TestCase
|
||||
from django.urls import reverse
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
|
||||
from wagtail.admin.views.pages.bulk_actions.page_bulk_action import PageBulkAction
|
||||
from wagtail.models import Page
|
||||
from wagtail.signals import page_unpublished
|
||||
from wagtail.test.testapp.models import SimplePage
|
||||
from wagtail.test.utils import WagtailTestUtils
|
||||
|
||||
|
||||
class TestBulkUnpublish(WagtailTestUtils, TestCase):
|
||||
def setUp(self):
|
||||
# Create pages to unpublish
|
||||
self.root_page = Page.objects.get(id=2)
|
||||
self.child_pages = [
|
||||
SimplePage(
|
||||
title=f"Hello world!-{i}", slug=f"hello-world-{i}", content=f"hello-{i}"
|
||||
)
|
||||
for i in range(1, 5)
|
||||
]
|
||||
# first three child pages will be unpublished
|
||||
self.pages_to_be_unpublished = self.child_pages[:3]
|
||||
self.pages_not_to_be_unpublished = self.child_pages[3:]
|
||||
for child_page in self.child_pages:
|
||||
self.root_page.add_child(instance=child_page)
|
||||
|
||||
self.url = (
|
||||
reverse(
|
||||
"wagtail_bulk_action",
|
||||
args=(
|
||||
"wagtailcore",
|
||||
"page",
|
||||
"unpublish",
|
||||
),
|
||||
)
|
||||
+ "?"
|
||||
)
|
||||
for child_page in self.pages_to_be_unpublished:
|
||||
self.url += f"&id={child_page.id}"
|
||||
self.redirect_url = reverse("wagtailadmin_explore", args=(self.root_page.id,))
|
||||
|
||||
# Login
|
||||
self.user = self.login()
|
||||
|
||||
def test_unpublish_view(self):
|
||||
"""
|
||||
This tests that the unpublish view responds with an unpublish confirm page
|
||||
"""
|
||||
# Request confirm unpublish page
|
||||
response = self.client.get(self.url)
|
||||
|
||||
# Check that the user received an unpublish confirm page
|
||||
self.assertEqual(response.status_code, 200)
|
||||
self.assertTemplateUsed(
|
||||
response, "wagtailadmin/pages/bulk_actions/confirm_bulk_unpublish.html"
|
||||
)
|
||||
|
||||
def test_unpublish_view_invalid_page_id(self):
|
||||
"""
|
||||
This tests that the unpublish view returns an error if the page id is invalid
|
||||
"""
|
||||
# Request confirm unpublish page but with illegal page id
|
||||
response = self.client.get(
|
||||
reverse(
|
||||
"wagtail_bulk_action",
|
||||
args=(
|
||||
"wagtailcore",
|
||||
"page",
|
||||
"unpublish",
|
||||
),
|
||||
)
|
||||
)
|
||||
|
||||
# Check that the user received a 404 response
|
||||
self.assertEqual(response.status_code, 404)
|
||||
|
||||
def test_unpublish_view_bad_permissions(self):
|
||||
"""
|
||||
This tests that the unpublish view doesn't allow users without unpublish permissions
|
||||
"""
|
||||
# Remove privileges from user
|
||||
self.user.is_superuser = False
|
||||
self.user.user_permissions.add(
|
||||
Permission.objects.get(
|
||||
content_type__app_label="wagtailadmin", codename="access_admin"
|
||||
)
|
||||
)
|
||||
self.user.save()
|
||||
|
||||
# Request confirm unpublish page
|
||||
response = self.client.get(self.url)
|
||||
|
||||
# Check that the user received a 200 redirected response
|
||||
self.assertEqual(response.status_code, 200)
|
||||
|
||||
html = response.content.decode()
|
||||
|
||||
self.assertInHTML(
|
||||
"<p>You don't have permission to unpublish these pages</p>", html
|
||||
)
|
||||
|
||||
for child_page in self.pages_to_be_unpublished:
|
||||
self.assertInHTML(f"<li>{child_page.title}</li>", html)
|
||||
|
||||
def test_unpublish_view_post(self):
|
||||
"""
|
||||
This posts to the unpublish view and checks that the page was unpublished
|
||||
"""
|
||||
# Connect a mock signal handler to page_unpublished signal
|
||||
mock_handler = mock.MagicMock()
|
||||
page_unpublished.connect(mock_handler)
|
||||
|
||||
try:
|
||||
# Post to the unpublish page
|
||||
response = self.client.post(self.url)
|
||||
|
||||
# Should be redirected to explorer page
|
||||
self.assertEqual(response.status_code, 302)
|
||||
|
||||
# Check that the child pages were unpublished
|
||||
for child_page in self.pages_to_be_unpublished:
|
||||
self.assertFalse(SimplePage.objects.get(id=child_page.id).live)
|
||||
|
||||
# Check that the child pages not to be unpublished remain
|
||||
for child_page in self.pages_not_to_be_unpublished:
|
||||
self.assertTrue(SimplePage.objects.get(id=child_page.id).live)
|
||||
|
||||
# Check that the page_unpublished signal was fired
|
||||
self.assertEqual(mock_handler.call_count, len(self.pages_to_be_unpublished))
|
||||
|
||||
for i, child_page in enumerate(self.pages_to_be_unpublished):
|
||||
mock_call = mock_handler.mock_calls[i][2]
|
||||
self.assertEqual(mock_call["sender"], child_page.specific_class)
|
||||
self.assertEqual(mock_call["instance"], child_page)
|
||||
self.assertIsInstance(mock_call["instance"], child_page.specific_class)
|
||||
finally:
|
||||
page_unpublished.disconnect(mock_handler)
|
||||
|
||||
def test_after_unpublish_page(self):
|
||||
def hook_func(request, action_type, pages, action_class_instance):
|
||||
self.assertEqual(action_type, "unpublish")
|
||||
self.assertIsInstance(request, HttpRequest)
|
||||
self.assertIsInstance(action_class_instance, PageBulkAction)
|
||||
for i, page in enumerate(pages):
|
||||
self.assertEqual(page.id, self.pages_to_be_unpublished[i].id)
|
||||
|
||||
return HttpResponse("Overridden!")
|
||||
|
||||
with self.register_hook("after_bulk_action", hook_func):
|
||||
response = self.client.post(self.url)
|
||||
|
||||
self.assertEqual(response.status_code, 200)
|
||||
self.assertEqual(response.content, b"Overridden!")
|
||||
|
||||
for child_page in self.pages_to_be_unpublished:
|
||||
child_page.refresh_from_db()
|
||||
self.assertEqual(child_page.status_string, _("draft"))
|
||||
|
||||
def test_before_unpublish_page(self):
|
||||
def hook_func(request, action_type, pages, action_class_instance):
|
||||
self.assertEqual(action_type, "unpublish")
|
||||
self.assertIsInstance(request, HttpRequest)
|
||||
self.assertIsInstance(action_class_instance, PageBulkAction)
|
||||
for i, page in enumerate(pages):
|
||||
self.assertEqual(page.id, self.pages_to_be_unpublished[i].id)
|
||||
|
||||
return HttpResponse("Overridden!")
|
||||
|
||||
with self.register_hook("before_bulk_action", hook_func):
|
||||
response = self.client.post(self.url)
|
||||
|
||||
self.assertEqual(response.status_code, 200)
|
||||
self.assertEqual(response.content, b"Overridden!")
|
||||
|
||||
def test_unpublish_descendants_view(self):
|
||||
"""
|
||||
This tests that the unpublish view responds with an unpublish confirm page that does not contain the form field 'include_descendants'
|
||||
"""
|
||||
# Get unpublish page for page with no descendants
|
||||
response = self.client.get(self.url)
|
||||
|
||||
# Check that the user received an unpublish confirm page
|
||||
self.assertEqual(response.status_code, 200)
|
||||
self.assertTemplateUsed(
|
||||
response, "wagtailadmin/pages/bulk_actions/confirm_bulk_unpublish.html"
|
||||
)
|
||||
# Check the form does not contain the checkbox field include_descendants
|
||||
self.assertContains(
|
||||
response,
|
||||
'name="include_descendants"',
|
||||
count=0,
|
||||
)
|
||||
|
||||
|
||||
class TestBulkUnpublishIncludingDescendants(WagtailTestUtils, TestCase):
|
||||
def setUp(self):
|
||||
# Find root page
|
||||
self.root_page = Page.objects.get(id=2)
|
||||
|
||||
self.child_pages = [
|
||||
SimplePage(
|
||||
title=f"Hello world!-{i}", slug=f"hello-world-{i}", content=f"hello-{i}"
|
||||
)
|
||||
for i in range(1, 5)
|
||||
]
|
||||
# first three child pages will be unpublished
|
||||
self.pages_to_be_unpublished = self.child_pages[:3]
|
||||
self.pages_not_to_be_unpublished = self.child_pages[3:]
|
||||
for child_page in self.child_pages:
|
||||
self.root_page.add_child(instance=child_page)
|
||||
|
||||
# map of the form { page: [child_pages] } to be added
|
||||
self.grandchildren_pages = {
|
||||
self.pages_to_be_unpublished[0]: [
|
||||
SimplePage(
|
||||
title="Hello world!-a", slug="hello-world-a", content="hello-a"
|
||||
)
|
||||
],
|
||||
self.pages_to_be_unpublished[1]: [
|
||||
SimplePage(
|
||||
title="Hello world!-b", slug="hello-world-b", content="hello-b"
|
||||
),
|
||||
SimplePage(
|
||||
title="Hello world!-c", slug="hello-world-c", content="hello-c"
|
||||
),
|
||||
],
|
||||
}
|
||||
|
||||
for child_page, grandchild_pages in self.grandchildren_pages.items():
|
||||
for grandchild_page in grandchild_pages:
|
||||
child_page.add_child(instance=grandchild_page)
|
||||
|
||||
self.url = (
|
||||
reverse(
|
||||
"wagtail_bulk_action",
|
||||
args=(
|
||||
"wagtailcore",
|
||||
"page",
|
||||
"unpublish",
|
||||
),
|
||||
)
|
||||
+ "?"
|
||||
)
|
||||
for child_page in self.pages_to_be_unpublished:
|
||||
self.url += f"&id={child_page.id}"
|
||||
self.redirect_url = reverse("wagtailadmin_explore", args=(self.root_page.id,))
|
||||
|
||||
self.user = self.login()
|
||||
|
||||
def test_unpublish_descendants_view(self):
|
||||
"""
|
||||
This tests that the unpublish view responds with an unpublish confirm page that contains the form field 'include_descendants'
|
||||
"""
|
||||
# Get unpublish page
|
||||
response = self.client.get(self.url)
|
||||
|
||||
# Check that the user received an unpublish confirm page
|
||||
self.assertEqual(response.status_code, 200)
|
||||
self.assertTemplateUsed(
|
||||
response, "wagtailadmin/pages/bulk_actions/confirm_bulk_unpublish.html"
|
||||
)
|
||||
# Check the form contains the checkbox field include_descendants
|
||||
self.assertContains(
|
||||
response,
|
||||
'name="include_descendants"',
|
||||
)
|
||||
|
||||
def test_unpublish_include_children_view_post(self):
|
||||
"""
|
||||
This posts to the unpublish view and checks that the page and its descendants were unpublished
|
||||
"""
|
||||
# Post to the unpublish page
|
||||
response = self.client.post(self.url, {"include_descendants": "on"})
|
||||
|
||||
# Should be redirected to explorer page
|
||||
self.assertEqual(response.status_code, 302)
|
||||
|
||||
# Check that the child pages were unpublished
|
||||
for child_page in self.pages_to_be_unpublished:
|
||||
self.assertFalse(SimplePage.objects.get(id=child_page.id).live)
|
||||
|
||||
# Check that the child pages not to be unpublished remain
|
||||
for child_page in self.pages_not_to_be_unpublished:
|
||||
self.assertTrue(SimplePage.objects.get(id=child_page.id).live)
|
||||
|
||||
for grandchild_pages in self.grandchildren_pages.values():
|
||||
for grandchild_page in grandchild_pages:
|
||||
self.assertFalse(SimplePage.objects.get(id=grandchild_page.id).live)
|
||||
|
||||
def test_unpublish_not_include_children_view_post(self):
|
||||
"""
|
||||
This posts to the unpublish view and checks that the page was unpublished but its descendants were not
|
||||
"""
|
||||
# Post to the unpublish page
|
||||
response = self.client.post(self.url, {})
|
||||
|
||||
# Should be redirected to explorer page
|
||||
self.assertEqual(response.status_code, 302)
|
||||
|
||||
# Check that the child pages were unpublished
|
||||
for child_page in self.pages_to_be_unpublished:
|
||||
self.assertFalse(SimplePage.objects.get(id=child_page.id).live)
|
||||
|
||||
# Check that the descendant pages were not unpublished
|
||||
for grandchild_pages in self.grandchildren_pages.values():
|
||||
for grandchild_page in grandchild_pages:
|
||||
self.assertTrue(SimplePage.objects.get(id=grandchild_page.id).live)
|
||||
36
env/lib/python3.10/site-packages/wagtail/admin/tests/pages/test_content_type_use_view.py
vendored
Normal file
36
env/lib/python3.10/site-packages/wagtail/admin/tests/pages/test_content_type_use_view.py
vendored
Normal file
@@ -0,0 +1,36 @@
|
||||
from django.test import TestCase
|
||||
from django.urls import reverse
|
||||
from django.utils.http import urlencode
|
||||
|
||||
from wagtail.test.testapp.models import EventPage
|
||||
from wagtail.test.utils import WagtailTestUtils
|
||||
|
||||
|
||||
class TestContentTypeUse(WagtailTestUtils, TestCase):
|
||||
fixtures = ["test.json"]
|
||||
|
||||
def setUp(self):
|
||||
self.user = self.login()
|
||||
self.christmas_page = EventPage.objects.get(title="Christmas")
|
||||
|
||||
def test_content_type_use(self):
|
||||
# Get use of event page
|
||||
request_url = reverse(
|
||||
"wagtailadmin_pages:type_use", args=("tests", "eventpage")
|
||||
)
|
||||
response = self.client.get(request_url)
|
||||
|
||||
# Check response
|
||||
self.assertEqual(response.status_code, 200)
|
||||
self.assertTemplateUsed(response, "wagtailadmin/generic/listing.html")
|
||||
self.assertTemplateUsed(response, "wagtailadmin/pages/usage_results.html")
|
||||
self.assertContains(response, "Christmas")
|
||||
|
||||
# Links to 'delete' etc should include a 'next' URL parameter pointing back here
|
||||
delete_url = (
|
||||
reverse("wagtailadmin_pages:delete", args=(self.christmas_page.id,))
|
||||
+ "?"
|
||||
+ urlencode({"next": request_url})
|
||||
)
|
||||
self.assertContains(response, delete_url)
|
||||
self.assertNotContains(response, "data-bulk-action-select-all-checkbox")
|
||||
89
env/lib/python3.10/site-packages/wagtail/admin/tests/pages/test_convert_alias.py
vendored
Normal file
89
env/lib/python3.10/site-packages/wagtail/admin/tests/pages/test_convert_alias.py
vendored
Normal file
@@ -0,0 +1,89 @@
|
||||
from django.contrib.auth.models import Permission
|
||||
from django.test import TestCase
|
||||
from django.urls import reverse
|
||||
|
||||
from wagtail.models import Page, PageLogEntry
|
||||
from wagtail.test.testapp.models import SimplePage
|
||||
from wagtail.test.utils import WagtailTestUtils
|
||||
|
||||
|
||||
class TestConvertAlias(WagtailTestUtils, TestCase):
|
||||
def setUp(self):
|
||||
# Find root page
|
||||
self.root_page = Page.objects.get(id=2)
|
||||
|
||||
# Add child page
|
||||
self.child_page = SimplePage(
|
||||
title="Hello world!", slug="hello-world", content="hello"
|
||||
)
|
||||
self.root_page.add_child(instance=self.child_page)
|
||||
|
||||
# Add alias page
|
||||
self.alias_page = self.child_page.create_alias(update_slug="alias-page")
|
||||
|
||||
# Login
|
||||
self.user = self.login()
|
||||
|
||||
def test_convert_alias(self):
|
||||
response = self.client.get(
|
||||
reverse("wagtailadmin_pages:convert_alias", args=[self.alias_page.id])
|
||||
)
|
||||
self.assertEqual(response.status_code, 200)
|
||||
|
||||
def test_convert_alias_not_alias(self):
|
||||
response = self.client.get(
|
||||
reverse("wagtailadmin_pages:convert_alias", args=[self.child_page.id])
|
||||
)
|
||||
self.assertEqual(response.status_code, 404)
|
||||
|
||||
def test_convert_alias_bad_permission(self):
|
||||
# Remove privileges from user
|
||||
self.user.is_superuser = False
|
||||
self.user.user_permissions.add(
|
||||
Permission.objects.get(
|
||||
content_type__app_label="wagtailadmin", codename="access_admin"
|
||||
)
|
||||
)
|
||||
self.user.save()
|
||||
|
||||
response = self.client.get(
|
||||
reverse("wagtailadmin_pages:convert_alias", args=[self.alias_page.id])
|
||||
)
|
||||
|
||||
# Check that the user received a permission denied response
|
||||
self.assertRedirects(response, "/admin/")
|
||||
|
||||
def test_post_convert_alias(self):
|
||||
response = self.client.post(
|
||||
reverse("wagtailadmin_pages:convert_alias", args=[self.alias_page.id])
|
||||
)
|
||||
|
||||
# User should be redirected to the edit view of the converted page
|
||||
self.assertRedirects(
|
||||
response, reverse("wagtailadmin_pages:edit", args=[self.alias_page.id])
|
||||
)
|
||||
|
||||
# Check the page was converted
|
||||
self.alias_page.refresh_from_db()
|
||||
self.assertIsNone(self.alias_page.alias_of)
|
||||
|
||||
# Check that a revision was created
|
||||
revision = self.alias_page.revisions.get()
|
||||
self.assertEqual(revision.user, self.user)
|
||||
self.assertEqual(self.alias_page.live_revision, revision)
|
||||
|
||||
# Check audit log
|
||||
log = PageLogEntry.objects.get(action="wagtail.convert_alias")
|
||||
self.assertFalse(log.content_changed)
|
||||
self.assertEqual(
|
||||
log.data,
|
||||
{
|
||||
"page": {
|
||||
"id": self.alias_page.id,
|
||||
"title": self.alias_page.get_admin_display_title(),
|
||||
}
|
||||
},
|
||||
)
|
||||
self.assertEqual(log.page, self.alias_page.page_ptr)
|
||||
self.assertEqual(log.revision, revision)
|
||||
self.assertEqual(log.user, self.user)
|
||||
800
env/lib/python3.10/site-packages/wagtail/admin/tests/pages/test_copy_page.py
vendored
Normal file
800
env/lib/python3.10/site-packages/wagtail/admin/tests/pages/test_copy_page.py
vendored
Normal file
@@ -0,0 +1,800 @@
|
||||
from django.contrib.auth.models import Group, Permission
|
||||
from django.http import HttpRequest, HttpResponse
|
||||
from django.test import TestCase
|
||||
from django.urls import reverse
|
||||
|
||||
from wagtail.models import GroupPagePermission, Page
|
||||
from wagtail.test.testapp.models import (
|
||||
CustomCopyFormPage,
|
||||
EventPage,
|
||||
EventPageSpeaker,
|
||||
PageWithExcludedCopyField,
|
||||
SimplePage,
|
||||
)
|
||||
from wagtail.test.utils import WagtailTestUtils
|
||||
|
||||
|
||||
class TestPageCopy(WagtailTestUtils, TestCase):
|
||||
def setUp(self):
|
||||
# Find root page
|
||||
self.root_page = Page.objects.get(id=2)
|
||||
|
||||
# Create a page
|
||||
self.test_page = self.root_page.add_child(
|
||||
instance=SimplePage(
|
||||
title="Hello world!",
|
||||
slug="hello-world",
|
||||
content="hello",
|
||||
live=True,
|
||||
has_unpublished_changes=False,
|
||||
)
|
||||
)
|
||||
|
||||
# Create a couple of child pages
|
||||
self.test_child_page = self.test_page.add_child(
|
||||
instance=SimplePage(
|
||||
title="Child page",
|
||||
slug="child-page",
|
||||
content="hello",
|
||||
live=True,
|
||||
has_unpublished_changes=True,
|
||||
)
|
||||
)
|
||||
|
||||
self.test_unpublished_child_page = self.test_page.add_child(
|
||||
instance=SimplePage(
|
||||
title="Unpublished Child page",
|
||||
slug="unpublished-child-page",
|
||||
content="hello",
|
||||
live=False,
|
||||
has_unpublished_changes=True,
|
||||
)
|
||||
)
|
||||
|
||||
# Login
|
||||
self.user = self.login()
|
||||
|
||||
def test_page_copy(self):
|
||||
response = self.client.get(
|
||||
reverse("wagtailadmin_pages:copy", args=(self.test_page.id,))
|
||||
)
|
||||
|
||||
# Check response
|
||||
self.assertEqual(response.status_code, 200)
|
||||
self.assertTemplateUsed(response, "wagtailadmin/pages/copy.html")
|
||||
|
||||
# Make sure all fields are in the form
|
||||
self.assertContains(response, "New title")
|
||||
self.assertContains(response, "New slug")
|
||||
self.assertContains(response, "New parent page")
|
||||
self.assertContains(response, "Copy subpages")
|
||||
self.assertContains(response, "Publish copies")
|
||||
self.assertContains(response, "Alias")
|
||||
|
||||
def test_page_copy_bad_permissions(self):
|
||||
# Remove privileges from user
|
||||
self.user.is_superuser = False
|
||||
self.user.user_permissions.add(
|
||||
Permission.objects.get(
|
||||
content_type__app_label="wagtailadmin", codename="access_admin"
|
||||
)
|
||||
)
|
||||
self.user.save()
|
||||
|
||||
# Get copy page
|
||||
post_data = {
|
||||
"new_title": "Hello world 2",
|
||||
"new_slug": "hello-world",
|
||||
"new_parent_page": str(self.test_page.id),
|
||||
"copy_subpages": False,
|
||||
"alias": False,
|
||||
}
|
||||
response = self.client.post(
|
||||
reverse("wagtailadmin_pages:copy", args=(self.test_page.id,)), post_data
|
||||
)
|
||||
|
||||
# A user with no page permissions at all should be redirected to the admin home
|
||||
self.assertRedirects(response, reverse("wagtailadmin_home"))
|
||||
|
||||
# A user with page permissions, but not add permission at the destination,
|
||||
# should receive a form validation error
|
||||
publishers = Group.objects.create(name="Publishers")
|
||||
GroupPagePermission.objects.create(
|
||||
group=publishers, page=self.root_page, permission_type="publish"
|
||||
)
|
||||
self.user.groups.add(publishers)
|
||||
self.user.save()
|
||||
|
||||
# Get copy page
|
||||
post_data = {
|
||||
"new_title": "Hello world 2",
|
||||
"new_slug": "hello-world",
|
||||
"new_parent_page": str(self.test_page.id),
|
||||
"copy_subpages": False,
|
||||
"alias": False,
|
||||
}
|
||||
response = self.client.post(
|
||||
reverse("wagtailadmin_pages:copy", args=(self.test_page.id,)), post_data
|
||||
)
|
||||
form = response.context["form"]
|
||||
self.assertFalse(form.is_valid())
|
||||
self.assertIn("new_parent_page", form.errors)
|
||||
|
||||
def test_page_copy_post(self):
|
||||
post_data = {
|
||||
"new_title": "Hello world 2",
|
||||
"new_slug": "hello-world-2",
|
||||
"new_parent_page": str(self.root_page.id),
|
||||
"copy_subpages": False,
|
||||
"publish_copies": False,
|
||||
"alias": False,
|
||||
}
|
||||
response = self.client.post(
|
||||
reverse("wagtailadmin_pages:copy", args=(self.test_page.id,)), post_data
|
||||
)
|
||||
|
||||
# Check that the user was redirected to the parents explore page
|
||||
self.assertRedirects(
|
||||
response, reverse("wagtailadmin_explore", args=(self.root_page.id,))
|
||||
)
|
||||
|
||||
# Get copy
|
||||
page_copy = self.root_page.get_children().filter(slug="hello-world-2").first()
|
||||
|
||||
# Check that the copy exists
|
||||
self.assertIsNotNone(page_copy)
|
||||
|
||||
# Check that the copy is not live
|
||||
self.assertFalse(page_copy.live)
|
||||
self.assertTrue(page_copy.has_unpublished_changes)
|
||||
|
||||
# Check that the owner of the page is set correctly
|
||||
self.assertEqual(page_copy.owner, self.user)
|
||||
|
||||
# Check that the children were not copied
|
||||
self.assertEqual(page_copy.get_children().count(), 0)
|
||||
|
||||
# treebeard should report no consistency problems with the tree
|
||||
self.assertFalse(
|
||||
any(Page.find_problems()), msg="treebeard found consistency problems"
|
||||
)
|
||||
|
||||
def test_page_with_exclude_fields_in_copy(self):
|
||||
original_page = self.test_page.add_child(
|
||||
instance=PageWithExcludedCopyField(
|
||||
title="Page with exclude_fields_in_copy",
|
||||
slug="page-with-exclude-fields-in-copy",
|
||||
content="Copy me",
|
||||
special_field="Don't copy me",
|
||||
live=True,
|
||||
has_unpublished_changes=False,
|
||||
)
|
||||
)
|
||||
post_data = {
|
||||
"new_title": f"{original_page.title} 2",
|
||||
"new_slug": f"{original_page.slug}-2",
|
||||
"new_parent_page": str(self.root_page.id),
|
||||
"copy_subpages": False,
|
||||
"publish_copies": False,
|
||||
"alias": False,
|
||||
}
|
||||
self.client.post(
|
||||
reverse("wagtailadmin_pages:copy", args=(original_page.id,)), post_data
|
||||
)
|
||||
# Get copy
|
||||
page_copy = PageWithExcludedCopyField.objects.get(slug=post_data["new_slug"])
|
||||
self.assertEqual(page_copy.content, original_page.content)
|
||||
self.assertNotEqual(page_copy.special_field, original_page.special_field)
|
||||
self.assertEqual(
|
||||
page_copy.special_field, page_copy._meta.get_field("special_field").default
|
||||
)
|
||||
|
||||
def test_page_copy_post_copy_subpages(self):
|
||||
post_data = {
|
||||
"new_title": "Hello world 2",
|
||||
"new_slug": "hello-world-2",
|
||||
"new_parent_page": str(self.root_page.id),
|
||||
"copy_subpages": True,
|
||||
"publish_copies": False,
|
||||
"alias": False,
|
||||
}
|
||||
response = self.client.post(
|
||||
reverse("wagtailadmin_pages:copy", args=(self.test_page.id,)), post_data
|
||||
)
|
||||
|
||||
# Check that the user was redirected to the parents explore page
|
||||
self.assertRedirects(
|
||||
response, reverse("wagtailadmin_explore", args=(self.root_page.id,))
|
||||
)
|
||||
|
||||
# Get copy
|
||||
page_copy = self.root_page.get_children().filter(slug="hello-world-2").first()
|
||||
|
||||
# Check that the copy exists
|
||||
self.assertIsNotNone(page_copy)
|
||||
|
||||
# Check that the copy is not live
|
||||
self.assertFalse(page_copy.live)
|
||||
self.assertTrue(page_copy.has_unpublished_changes)
|
||||
|
||||
# Check that the owner of the page is set correctly
|
||||
self.assertEqual(page_copy.owner, self.user)
|
||||
|
||||
# Check that the children were copied
|
||||
self.assertEqual(page_copy.get_children().count(), 2)
|
||||
|
||||
# Check the child pages
|
||||
# Neither of them should be live
|
||||
child_copy = page_copy.get_children().filter(slug="child-page").first()
|
||||
self.assertIsNotNone(child_copy)
|
||||
self.assertFalse(child_copy.live)
|
||||
self.assertTrue(child_copy.has_unpublished_changes)
|
||||
|
||||
unpublished_child_copy = (
|
||||
page_copy.get_children().filter(slug="unpublished-child-page").first()
|
||||
)
|
||||
self.assertIsNotNone(unpublished_child_copy)
|
||||
self.assertFalse(unpublished_child_copy.live)
|
||||
self.assertTrue(unpublished_child_copy.has_unpublished_changes)
|
||||
|
||||
# treebeard should report no consistency problems with the tree
|
||||
self.assertFalse(
|
||||
any(Page.find_problems()), msg="treebeard found consistency problems"
|
||||
)
|
||||
|
||||
def test_page_copy_post_copy_subpages_publish_copies(self):
|
||||
post_data = {
|
||||
"new_title": "Hello world 2",
|
||||
"new_slug": "hello-world-2",
|
||||
"new_parent_page": str(self.root_page.id),
|
||||
"copy_subpages": True,
|
||||
"publish_copies": True,
|
||||
"alias": False,
|
||||
}
|
||||
response = self.client.post(
|
||||
reverse("wagtailadmin_pages:copy", args=(self.test_page.id,)), post_data
|
||||
)
|
||||
|
||||
# Check that the user was redirected to the parents explore page
|
||||
self.assertRedirects(
|
||||
response, reverse("wagtailadmin_explore", args=(self.root_page.id,))
|
||||
)
|
||||
|
||||
# Get copy
|
||||
page_copy = self.root_page.get_children().filter(slug="hello-world-2").first()
|
||||
|
||||
# Check that the copy exists
|
||||
self.assertIsNotNone(page_copy)
|
||||
|
||||
# Check that the copy is live
|
||||
self.assertTrue(page_copy.live)
|
||||
self.assertFalse(page_copy.has_unpublished_changes)
|
||||
|
||||
# Check that the owner of the page is set correctly
|
||||
self.assertEqual(page_copy.owner, self.user)
|
||||
|
||||
# Check that the children were copied
|
||||
self.assertEqual(page_copy.get_children().count(), 2)
|
||||
|
||||
# Check the child pages
|
||||
# The child_copy should be live but the unpublished_child_copy shouldn't
|
||||
child_copy = page_copy.get_children().filter(slug="child-page").first()
|
||||
self.assertIsNotNone(child_copy)
|
||||
self.assertTrue(child_copy.live)
|
||||
self.assertTrue(child_copy.has_unpublished_changes)
|
||||
|
||||
unpublished_child_copy = (
|
||||
page_copy.get_children().filter(slug="unpublished-child-page").first()
|
||||
)
|
||||
self.assertIsNotNone(unpublished_child_copy)
|
||||
self.assertFalse(unpublished_child_copy.live)
|
||||
self.assertTrue(unpublished_child_copy.has_unpublished_changes)
|
||||
|
||||
# treebeard should report no consistency problems with the tree
|
||||
self.assertFalse(
|
||||
any(Page.find_problems()), msg="treebeard found consistency problems"
|
||||
)
|
||||
|
||||
def test_page_copy_post_new_parent(self):
|
||||
post_data = {
|
||||
"new_title": "Hello world 2",
|
||||
"new_slug": "hello-world-2",
|
||||
"new_parent_page": str(self.test_child_page.id),
|
||||
"copy_subpages": False,
|
||||
"publish_copies": False,
|
||||
"alias": False,
|
||||
}
|
||||
response = self.client.post(
|
||||
reverse("wagtailadmin_pages:copy", args=(self.test_page.id,)), post_data
|
||||
)
|
||||
|
||||
# Check that the user was redirected to the new parents explore page
|
||||
self.assertRedirects(
|
||||
response, reverse("wagtailadmin_explore", args=(self.test_child_page.id,))
|
||||
)
|
||||
|
||||
# Check that the page was copied to the correct place
|
||||
self.assertTrue(
|
||||
Page.objects.filter(slug="hello-world-2").first().get_parent(),
|
||||
msg=self.test_child_page,
|
||||
)
|
||||
|
||||
# treebeard should report no consistency problems with the tree
|
||||
self.assertFalse(
|
||||
any(Page.find_problems()), msg="treebeard found consistency problems"
|
||||
)
|
||||
|
||||
def test_page_copy_post_existing_slug_within_same_parent_page(self):
|
||||
# This tests the existing slug checking on page copy when not changing the parent page
|
||||
|
||||
# Attempt to copy the page but forget to change the slug
|
||||
post_data = {
|
||||
"new_title": "Hello world 2",
|
||||
"new_slug": "hello-world",
|
||||
"new_parent_page": str(self.root_page.id),
|
||||
"copy_subpages": False,
|
||||
"alias": False,
|
||||
}
|
||||
response = self.client.post(
|
||||
reverse("wagtailadmin_pages:copy", args=(self.test_page.id,)), post_data
|
||||
)
|
||||
|
||||
# Should not be redirected (as the save should fail)
|
||||
self.assertEqual(response.status_code, 200)
|
||||
|
||||
# Check that a form error was raised
|
||||
self.assertFormError(
|
||||
response.context["form"],
|
||||
"new_slug",
|
||||
'This slug is already in use within the context of its parent page "Welcome to your new Wagtail site!"',
|
||||
)
|
||||
|
||||
def test_page_copy_post_and_subpages_to_same_tree_branch(self):
|
||||
# This tests that a page cannot be copied into itself when copying subpages
|
||||
post_data = {
|
||||
"new_title": "Hello world 2",
|
||||
"new_slug": "hello-world",
|
||||
"new_parent_page": str(self.test_child_page.id),
|
||||
"copy_subpages": True,
|
||||
"alias": False,
|
||||
}
|
||||
response = self.client.post(
|
||||
reverse("wagtailadmin_pages:copy", args=(self.test_page.id,)), post_data
|
||||
)
|
||||
|
||||
# Should not be redirected (as the save should fail)
|
||||
self.assertEqual(response.status_code, 200)
|
||||
|
||||
# Check that a form error was raised
|
||||
self.assertFormError(
|
||||
response.context["form"],
|
||||
"new_parent_page",
|
||||
"You cannot copy a page into itself when copying subpages",
|
||||
)
|
||||
|
||||
def test_page_copy_post_existing_slug_to_another_parent_page(self):
|
||||
# This tests the existing slug checking on page copy when changing the parent page
|
||||
|
||||
# Attempt to copy the page and changed the parent page
|
||||
post_data = {
|
||||
"new_title": "Hello world 2",
|
||||
"new_slug": "hello-world",
|
||||
"new_parent_page": str(self.test_child_page.id),
|
||||
"copy_subpages": False,
|
||||
"alias": False,
|
||||
}
|
||||
response = self.client.post(
|
||||
reverse("wagtailadmin_pages:copy", args=(self.test_page.id,)), post_data
|
||||
)
|
||||
|
||||
# Check that the user was redirected to the parents explore page
|
||||
self.assertRedirects(
|
||||
response, reverse("wagtailadmin_explore", args=(self.test_child_page.id,))
|
||||
)
|
||||
|
||||
def test_page_copy_post_invalid_slug(self):
|
||||
# Attempt to copy the page but set an invalid slug string
|
||||
post_data = {
|
||||
"new_title": "Hello world 2",
|
||||
"new_slug": "hello world!",
|
||||
"new_parent_page": str(self.root_page.id),
|
||||
"copy_subpages": False,
|
||||
"alias": False,
|
||||
}
|
||||
response = self.client.post(
|
||||
reverse("wagtailadmin_pages:copy", args=(self.test_page.id,)), post_data
|
||||
)
|
||||
|
||||
# Should not be redirected (as the save should fail)
|
||||
self.assertEqual(response.status_code, 200)
|
||||
|
||||
# Check that a form error was raised
|
||||
self.assertFormError(
|
||||
response.context["form"],
|
||||
"new_slug",
|
||||
"Enter a valid “slug” consisting of Unicode letters, numbers, underscores, or hyphens.",
|
||||
)
|
||||
|
||||
def test_page_copy_post_valid_unicode_slug(self):
|
||||
post_data = {
|
||||
"new_title": "Hello wɜːld",
|
||||
"new_slug": "hello-wɜːld",
|
||||
"new_parent_page": str(self.test_page.id),
|
||||
"copy_subpages": False,
|
||||
"alias": False,
|
||||
}
|
||||
response = self.client.post(
|
||||
reverse("wagtailadmin_pages:copy", args=(self.test_page.id,)), post_data
|
||||
)
|
||||
|
||||
# Check response
|
||||
self.assertRedirects(
|
||||
response, reverse("wagtailadmin_explore", args=(self.test_page.id,))
|
||||
)
|
||||
|
||||
# Get copy
|
||||
page_copy = (
|
||||
self.test_page.get_children().filter(slug=post_data["new_slug"]).first()
|
||||
)
|
||||
|
||||
# Check that the copy exists with the good slug
|
||||
self.assertIsNotNone(page_copy)
|
||||
self.assertEqual(page_copy.slug, post_data["new_slug"])
|
||||
|
||||
def test_page_copy_no_publish_permission(self):
|
||||
# Turn user into an editor who can add pages but not publish them
|
||||
self.user.is_superuser = False
|
||||
self.user.groups.add(
|
||||
Group.objects.get(name="Editors"),
|
||||
)
|
||||
self.user.save()
|
||||
|
||||
# Get copy page
|
||||
response = self.client.get(
|
||||
reverse("wagtailadmin_pages:copy", args=(self.test_page.id,))
|
||||
)
|
||||
|
||||
# The user should have access to the copy page
|
||||
self.assertEqual(response.status_code, 200)
|
||||
self.assertTemplateUsed(response, "wagtailadmin/pages/copy.html")
|
||||
|
||||
# Make sure the "publish copies" field is hidden
|
||||
self.assertNotContains(response, "Publish copies")
|
||||
|
||||
def test_page_copy_no_publish_permission_post_copy_subpages_publish_copies(self):
|
||||
# This tests that unprivileged users cannot publish copied pages even if they hack their browser
|
||||
|
||||
# Turn user into an editor who can add pages but not publish them
|
||||
self.user.is_superuser = False
|
||||
self.user.groups.add(
|
||||
Group.objects.get(name="Editors"),
|
||||
)
|
||||
self.user.save()
|
||||
|
||||
# Post
|
||||
post_data = {
|
||||
"new_title": "Hello world 2",
|
||||
"new_slug": "hello-world-2",
|
||||
"new_parent_page": str(self.root_page.id),
|
||||
"copy_subpages": True,
|
||||
"publish_copies": True,
|
||||
"alias": False,
|
||||
}
|
||||
response = self.client.post(
|
||||
reverse("wagtailadmin_pages:copy", args=(self.test_page.id,)), post_data
|
||||
)
|
||||
|
||||
# Check that the user was redirected to the parents explore page
|
||||
self.assertRedirects(
|
||||
response, reverse("wagtailadmin_explore", args=(self.root_page.id,))
|
||||
)
|
||||
|
||||
# Get copy
|
||||
page_copy = self.root_page.get_children().filter(slug="hello-world-2").first()
|
||||
|
||||
# Check that the copy exists
|
||||
self.assertIsNotNone(page_copy)
|
||||
|
||||
# Check that the copy is not live
|
||||
self.assertFalse(page_copy.live)
|
||||
|
||||
# Check that the owner of the page is set correctly
|
||||
self.assertEqual(page_copy.owner, self.user)
|
||||
|
||||
# Check that the children were copied
|
||||
self.assertEqual(page_copy.get_children().count(), 2)
|
||||
|
||||
# Check the child pages
|
||||
# Neither of them should be live
|
||||
child_copy = page_copy.get_children().filter(slug="child-page").first()
|
||||
self.assertIsNotNone(child_copy)
|
||||
self.assertFalse(child_copy.live)
|
||||
|
||||
unpublished_child_copy = (
|
||||
page_copy.get_children().filter(slug="unpublished-child-page").first()
|
||||
)
|
||||
self.assertIsNotNone(unpublished_child_copy)
|
||||
self.assertFalse(unpublished_child_copy.live)
|
||||
|
||||
# treebeard should report no consistency problems with the tree
|
||||
self.assertFalse(
|
||||
any(Page.find_problems()), msg="treebeard found consistency problems"
|
||||
)
|
||||
|
||||
def test_before_copy_page_hook(self):
|
||||
def hook_func(request, page):
|
||||
self.assertIsInstance(request, HttpRequest)
|
||||
self.assertIsInstance(page.specific, SimplePage)
|
||||
|
||||
return HttpResponse("Overridden!")
|
||||
|
||||
with self.register_hook("before_copy_page", hook_func):
|
||||
response = self.client.get(
|
||||
reverse("wagtailadmin_pages:copy", args=(self.test_page.id,))
|
||||
)
|
||||
|
||||
self.assertEqual(response.status_code, 200)
|
||||
self.assertEqual(response.content, b"Overridden!")
|
||||
|
||||
def test_before_copy_page_hook_post(self):
|
||||
def hook_func(request, page):
|
||||
self.assertIsInstance(request, HttpRequest)
|
||||
self.assertIsInstance(page.specific, SimplePage)
|
||||
|
||||
return HttpResponse("Overridden!")
|
||||
|
||||
with self.register_hook("before_copy_page", hook_func):
|
||||
post_data = {
|
||||
"new_title": "Hello world 2",
|
||||
"new_slug": "hello-world-2",
|
||||
"new_parent_page": str(self.root_page.id),
|
||||
"copy_subpages": False,
|
||||
"publish_copies": False,
|
||||
"alias": False,
|
||||
}
|
||||
response = self.client.post(
|
||||
reverse("wagtailadmin_pages:copy", args=(self.test_page.id,)), post_data
|
||||
)
|
||||
|
||||
self.assertEqual(response.status_code, 200)
|
||||
self.assertEqual(response.content, b"Overridden!")
|
||||
|
||||
# page should not be copied
|
||||
self.assertFalse(Page.objects.filter(title="Hello world 2").exists())
|
||||
|
||||
def test_after_copy_page_hook(self):
|
||||
def hook_func(request, page, new_page):
|
||||
self.assertIsInstance(request, HttpRequest)
|
||||
self.assertIsInstance(page.specific, SimplePage)
|
||||
self.assertIsInstance(new_page.specific, SimplePage)
|
||||
|
||||
return HttpResponse("Overridden!")
|
||||
|
||||
with self.register_hook("after_copy_page", hook_func):
|
||||
post_data = {
|
||||
"new_title": "Hello world 2",
|
||||
"new_slug": "hello-world-2",
|
||||
"new_parent_page": str(self.root_page.id),
|
||||
"copy_subpages": False,
|
||||
"publish_copies": False,
|
||||
"alias": False,
|
||||
}
|
||||
response = self.client.post(
|
||||
reverse("wagtailadmin_pages:copy", args=(self.test_page.id,)), post_data
|
||||
)
|
||||
|
||||
self.assertEqual(response.status_code, 200)
|
||||
self.assertEqual(response.content, b"Overridden!")
|
||||
|
||||
# page should be copied
|
||||
self.assertTrue(Page.objects.filter(title="Hello world 2").exists())
|
||||
|
||||
def test_page_copy_alias_post(self):
|
||||
post_data = {
|
||||
"new_title": "Hello world 2",
|
||||
"new_slug": "hello-world-2",
|
||||
"new_parent_page": str(self.root_page.id),
|
||||
"copy_subpages": False,
|
||||
"publish_copies": False,
|
||||
"alias": True,
|
||||
}
|
||||
response = self.client.post(
|
||||
reverse("wagtailadmin_pages:copy", args=(self.test_page.id,)), post_data
|
||||
)
|
||||
|
||||
# Check that the user was redirected to the parents explore page
|
||||
self.assertRedirects(
|
||||
response, reverse("wagtailadmin_explore", args=(self.root_page.id,))
|
||||
)
|
||||
|
||||
# Get copy
|
||||
page_copy = self.root_page.get_children().get(slug="hello-world-2")
|
||||
|
||||
# Check the copy is an alias of the original
|
||||
self.assertEqual(page_copy.alias_of, self.test_page.page_ptr)
|
||||
|
||||
# Check that the copy is live
|
||||
# Note: publish_copies is ignored. Alias pages always keep the same state as their original
|
||||
self.assertTrue(page_copy.live)
|
||||
self.assertFalse(page_copy.has_unpublished_changes)
|
||||
|
||||
# Check that the owner of the page is set correctly
|
||||
self.assertEqual(page_copy.owner, self.user)
|
||||
|
||||
# Check that the children were not copied
|
||||
self.assertEqual(page_copy.get_children().count(), 0)
|
||||
|
||||
# treebeard should report no consistency problems with the tree
|
||||
self.assertFalse(
|
||||
any(Page.find_problems()), msg="treebeard found consistency problems"
|
||||
)
|
||||
|
||||
def test_page_copy_alias_post_copy_subpages(self):
|
||||
post_data = {
|
||||
"new_title": "Hello world 2",
|
||||
"new_slug": "hello-world-2",
|
||||
"new_parent_page": str(self.root_page.id),
|
||||
"copy_subpages": True,
|
||||
"publish_copies": False,
|
||||
"alias": True,
|
||||
}
|
||||
response = self.client.post(
|
||||
reverse("wagtailadmin_pages:copy", args=(self.test_page.id,)), post_data
|
||||
)
|
||||
|
||||
# Check that the user was redirected to the parents explore page
|
||||
self.assertRedirects(
|
||||
response, reverse("wagtailadmin_explore", args=(self.root_page.id,))
|
||||
)
|
||||
|
||||
# Get copy
|
||||
page_copy = self.root_page.get_children().get(slug="hello-world-2")
|
||||
|
||||
# Check the copy is an alias of the original
|
||||
self.assertEqual(page_copy.alias_of, self.test_page.page_ptr)
|
||||
|
||||
# Check that the copy is live
|
||||
# Note: publish_copies is ignored. Alias pages always keep the same state as their original
|
||||
self.assertTrue(page_copy.live)
|
||||
self.assertFalse(page_copy.has_unpublished_changes)
|
||||
|
||||
# Check that the owner of the page is set correctly
|
||||
self.assertEqual(page_copy.owner, self.user)
|
||||
|
||||
# Check that the children were copied
|
||||
self.assertEqual(page_copy.get_children().count(), 2)
|
||||
|
||||
# Check the child pages
|
||||
# Neither of them should be live
|
||||
child_copy = page_copy.get_children().filter(slug="child-page").first()
|
||||
self.assertIsNotNone(child_copy)
|
||||
self.assertEqual(child_copy.alias_of, self.test_child_page.page_ptr)
|
||||
self.assertTrue(child_copy.live)
|
||||
self.assertFalse(child_copy.has_unpublished_changes)
|
||||
|
||||
unpublished_child_copy = (
|
||||
page_copy.get_children().filter(slug="unpublished-child-page").first()
|
||||
)
|
||||
self.assertIsNotNone(unpublished_child_copy)
|
||||
self.assertEqual(
|
||||
unpublished_child_copy.alias_of, self.test_unpublished_child_page.page_ptr
|
||||
)
|
||||
self.assertFalse(unpublished_child_copy.live)
|
||||
self.assertTrue(unpublished_child_copy.has_unpublished_changes)
|
||||
|
||||
# treebeard should report no consistency problems with the tree
|
||||
self.assertFalse(
|
||||
any(Page.find_problems()), msg="treebeard found consistency problems"
|
||||
)
|
||||
|
||||
def test_page_copy_alias_post_without_source_publish_permission(self):
|
||||
# Check for issue #7293 - If the user has permission to publish at a destination, but not the source.
|
||||
# Wagtail would crash on attempt to copy
|
||||
|
||||
# Create a new section
|
||||
self.destination_page = self.root_page.add_child(
|
||||
instance=SimplePage(
|
||||
title="Destination page",
|
||||
slug="destination-page",
|
||||
content="hello",
|
||||
live=True,
|
||||
has_unpublished_changes=False,
|
||||
)
|
||||
)
|
||||
|
||||
# Make user a moderator and make it so they can only publish at the destination page
|
||||
self.user.is_superuser = False
|
||||
self.user.groups.add(Group.objects.get(name="Moderators"))
|
||||
self.user.save()
|
||||
GroupPagePermission.objects.filter(permission__codename="publish_page").update(
|
||||
page=self.destination_page
|
||||
)
|
||||
|
||||
post_data = {
|
||||
"new_title": self.test_child_page.title,
|
||||
"new_slug": self.test_child_page.slug,
|
||||
"new_parent_page": str(self.destination_page.id),
|
||||
"copy_subpages": False,
|
||||
"publish_copies": False,
|
||||
"alias": False,
|
||||
}
|
||||
response = self.client.post(
|
||||
reverse("wagtailadmin_pages:copy", args=[self.test_child_page.id]),
|
||||
post_data,
|
||||
)
|
||||
|
||||
# We only need to check that it didn't crash
|
||||
self.assertEqual(response.status_code, 302)
|
||||
|
||||
def test_copy_page_with_unique_uuids_in_orderables(self):
|
||||
"""
|
||||
Test that a page with orderables can be copied and the translation
|
||||
keys are updated.
|
||||
"""
|
||||
event_page = EventPage(
|
||||
title="Moon Landing",
|
||||
location="the moon",
|
||||
audience="public",
|
||||
cost="free on TV",
|
||||
date_from="1969-07-20",
|
||||
)
|
||||
self.root_page.add_child(instance=event_page)
|
||||
|
||||
event_page.speakers.add(
|
||||
EventPageSpeaker(
|
||||
first_name="Neil",
|
||||
last_name="Armstrong",
|
||||
)
|
||||
)
|
||||
# ensure there's a revision (which should capture the new speaker orderables)
|
||||
# before copying the page
|
||||
event_page.save_revision().publish()
|
||||
|
||||
post_data = {
|
||||
"new_title": "New Moon landing",
|
||||
"new_slug": "moon-landing-redux",
|
||||
"new_parent_page": str(self.root_page.id),
|
||||
"copy_subpages": False,
|
||||
"publish_copies": False,
|
||||
"alias": False,
|
||||
}
|
||||
self.client.post(
|
||||
reverse("wagtailadmin_pages:copy", args=[event_page.id]), post_data
|
||||
)
|
||||
new_page = EventPage.objects.last()
|
||||
|
||||
# Hack: get the page instance from the edit form which assembles it from the
|
||||
# latest revision. While we could do new_page.get_latest_revision().as_object()
|
||||
# this follow the edit view closer and should it change the test is less
|
||||
# prone to continue working because we're skipping some step
|
||||
response = self.client.get(
|
||||
reverse("wagtailadmin_pages:edit", args=[new_page.id])
|
||||
)
|
||||
new_page_on_edit_form = response.context["form"].instance
|
||||
|
||||
# publish the page, similar to EditView.publish_action()
|
||||
new_page_on_edit_form.save_revision().publish()
|
||||
|
||||
self.assertNotEqual(
|
||||
event_page.speakers.first().translation_key,
|
||||
new_page.speakers.first().translation_key,
|
||||
)
|
||||
|
||||
def test_page_copy_with_custom_copy_form(self):
|
||||
custom_copy_form_page = self.root_page.add_child(
|
||||
instance=CustomCopyFormPage(
|
||||
title="Hello world!",
|
||||
slug="copy-form",
|
||||
live=True,
|
||||
has_unpublished_changes=False,
|
||||
)
|
||||
)
|
||||
|
||||
response = self.client.get(
|
||||
reverse("wagtailadmin_pages:copy", args=(custom_copy_form_page.id,))
|
||||
)
|
||||
# Check response
|
||||
self.assertEqual(response.status_code, 200)
|
||||
|
||||
# Check if slug is hello-world-2
|
||||
self.assertContains(response, "copy-form-2")
|
||||
1977
env/lib/python3.10/site-packages/wagtail/admin/tests/pages/test_create_page.py
vendored
Normal file
1977
env/lib/python3.10/site-packages/wagtail/admin/tests/pages/test_create_page.py
vendored
Normal file
File diff suppressed because it is too large
Load Diff
37
env/lib/python3.10/site-packages/wagtail/admin/tests/pages/test_custom_listing.py
vendored
Normal file
37
env/lib/python3.10/site-packages/wagtail/admin/tests/pages/test_custom_listing.py
vendored
Normal file
@@ -0,0 +1,37 @@
|
||||
from django.test import TestCase
|
||||
|
||||
from wagtail.test.utils import WagtailTestUtils
|
||||
from wagtail.test.utils.template_tests import AdminTemplateTestUtils
|
||||
|
||||
|
||||
class TestCustomListing(AdminTemplateTestUtils, WagtailTestUtils, TestCase):
|
||||
fixtures = ["test.json"]
|
||||
|
||||
def test_get(self):
|
||||
self.login()
|
||||
response = self.client.get("/admin/event_pages/")
|
||||
self.assertEqual(response.status_code, 200)
|
||||
self.assertTemplateUsed(response, "wagtailadmin/pages/index.html")
|
||||
self.assertContains(response, "Event pages")
|
||||
self.assertContains(response, "Christmas")
|
||||
self.assertContains(response, "Saint Patrick")
|
||||
self.assertNotContains(response, "Welcome to the Wagtail test site!")
|
||||
self.assertBreadcrumbsItemsRendered(
|
||||
[{"url": "", "label": "Event pages"}],
|
||||
response.content,
|
||||
)
|
||||
soup = self.get_soup(response.content)
|
||||
breadcrumbs_icon = soup.select_one(".w-breadcrumbs__icon")
|
||||
self.assertIsNotNone(breadcrumbs_icon)
|
||||
use = breadcrumbs_icon.select_one("use")
|
||||
self.assertIsNotNone(use)
|
||||
self.assertEqual(use["href"], "#icon-calendar")
|
||||
|
||||
def test_filter(self):
|
||||
self.login()
|
||||
response = self.client.get("/admin/event_pages/", {"audience": "private"})
|
||||
self.assertEqual(response.status_code, 200)
|
||||
self.assertTemplateUsed(response, "wagtailadmin/pages/index.html")
|
||||
self.assertContains(response, "Event pages")
|
||||
self.assertNotContains(response, "Christmas")
|
||||
self.assertContains(response, "Saint Patrick")
|
||||
366
env/lib/python3.10/site-packages/wagtail/admin/tests/pages/test_delete_page.py
vendored
Normal file
366
env/lib/python3.10/site-packages/wagtail/admin/tests/pages/test_delete_page.py
vendored
Normal file
@@ -0,0 +1,366 @@
|
||||
from unittest import mock
|
||||
|
||||
from django.contrib.auth.models import Permission
|
||||
from django.db.models.signals import post_delete, pre_delete
|
||||
from django.http import HttpRequest, HttpResponse
|
||||
from django.test import TestCase, override_settings
|
||||
from django.urls import reverse
|
||||
|
||||
from wagtail.models import Page
|
||||
from wagtail.signals import page_unpublished
|
||||
from wagtail.test.testapp.models import SimplePage, StandardChild, StandardIndex
|
||||
from wagtail.test.utils import WagtailTestUtils
|
||||
|
||||
|
||||
class TestPageDelete(WagtailTestUtils, TestCase):
|
||||
def setUp(self):
|
||||
# Find root page
|
||||
self.root_page = Page.objects.get(id=2)
|
||||
|
||||
# Add child page
|
||||
self.child_page = SimplePage(
|
||||
title="Hello world!", slug="hello-world", content="hello"
|
||||
)
|
||||
self.root_page.add_child(instance=self.child_page)
|
||||
|
||||
# Add a page with child pages of its own
|
||||
self.child_index = StandardIndex(title="Hello index", slug="hello-index")
|
||||
self.root_page.add_child(instance=self.child_index)
|
||||
self.grandchild_page = StandardChild(title="Hello Kitty", slug="hello-kitty")
|
||||
self.child_index.add_child(instance=self.grandchild_page)
|
||||
|
||||
# Login
|
||||
self.user = self.login()
|
||||
|
||||
def test_page_delete(self):
|
||||
response = self.client.get(
|
||||
reverse("wagtailadmin_pages:delete", args=(self.child_page.id,))
|
||||
)
|
||||
self.assertEqual(response.status_code, 200)
|
||||
# deletion should not actually happen on GET
|
||||
self.assertTrue(SimplePage.objects.filter(id=self.child_page.id).exists())
|
||||
|
||||
@override_settings(WAGTAILADMIN_UNSAFE_PAGE_DELETION_LIMIT=10)
|
||||
def test_confirm_delete_scenario_1(self):
|
||||
# If the number of pages to be deleted are less than
|
||||
# WAGTAILADMIN_UNSAFE_PAGE_DELETION_LIMIT then don't need
|
||||
# for confirmation
|
||||
child_1 = SimplePage(title="child 1", slug="child-1", content="hello")
|
||||
self.child_page.add_child(instance=child_1)
|
||||
child_2 = SimplePage(title="child 2", slug="child-2", content="hello")
|
||||
self.child_page.add_child(instance=child_2)
|
||||
response = self.client.get(
|
||||
reverse("wagtailadmin_pages:delete", args=(self.child_page.id,))
|
||||
)
|
||||
self.assertEqual(response.status_code, 200)
|
||||
self.assertNotContains(response, '<input type="text" name="confirm_site_name"')
|
||||
# deletion should not actually happen on GET
|
||||
self.assertTrue(SimplePage.objects.filter(id=self.child_page.id).exists())
|
||||
|
||||
# And admin should be able to delete page without any confirmation
|
||||
self.client.post(
|
||||
reverse("wagtailadmin_pages:delete", args=(self.child_page.id,))
|
||||
)
|
||||
# Check that page is deleted
|
||||
self.assertFalse(SimplePage.objects.filter(id=self.child_page.id).exists())
|
||||
|
||||
@override_settings(WAGTAILADMIN_UNSAFE_PAGE_DELETION_LIMIT=3)
|
||||
@override_settings(WAGTAIL_SITE_NAME="mysite")
|
||||
def test_confirm_delete_scenario_2(self):
|
||||
# If the number of pages to be deleted are greater than or equal to
|
||||
# WAGTAILADMIN_UNSAFE_PAGE_DELETION_LIMIT then show input box
|
||||
# to input wagtail_site_name.
|
||||
child_1 = SimplePage(title="child 1", slug="child-1", content="hello")
|
||||
self.child_page.add_child(instance=child_1)
|
||||
child_2 = SimplePage(title="child 2", slug="child-2", content="hello")
|
||||
self.child_page.add_child(instance=child_2)
|
||||
response = self.client.get(
|
||||
reverse("wagtailadmin_pages:delete", args=(self.child_page.id,))
|
||||
)
|
||||
self.assertEqual(response.status_code, 200)
|
||||
self.assertContains(response, "This action will delete total <b>3</b> pages.")
|
||||
self.assertContains(response, "Please type <b>mysite</b> to confirm.")
|
||||
self.assertContains(response, '<input type="text" name="confirm_site_name"')
|
||||
# deletion should not actually happen on GET
|
||||
self.assertTrue(SimplePage.objects.filter(id=self.child_page.id).exists())
|
||||
|
||||
@override_settings(WAGTAILADMIN_UNSAFE_PAGE_DELETION_LIMIT=3)
|
||||
@override_settings(WAGTAIL_SITE_NAME="mysite")
|
||||
def test_confirm_delete_scenario_3(self):
|
||||
# If admin entered the incorrect site name and submit
|
||||
# the form, then site should not be deleted and same
|
||||
# form should be displayed again.
|
||||
child_1 = SimplePage(title="child 1", slug="child-1", content="hello")
|
||||
self.child_page.add_child(instance=child_1)
|
||||
child_2 = SimplePage(title="child 2", slug="child-2", content="hello")
|
||||
self.child_page.add_child(instance=child_2)
|
||||
response = self.client.post(
|
||||
reverse("wagtailadmin_pages:delete", args=(self.child_page.id,)),
|
||||
data={"confirm_site_name": "random"},
|
||||
)
|
||||
self.assertEqual(response.status_code, 200)
|
||||
# One error messages should be returned
|
||||
messages = [m.message for m in response.context["messages"]]
|
||||
self.assertEqual(len(messages), 1)
|
||||
self.assertContains(response, "This action will delete total <b>3</b> pages.")
|
||||
self.assertContains(response, "Please type <b>mysite</b> to confirm.")
|
||||
self.assertContains(response, '<input type="text" name="confirm_site_name"')
|
||||
# Site should not be deleted
|
||||
self.assertTrue(SimplePage.objects.filter(id=self.child_page.id).exists())
|
||||
|
||||
@override_settings(WAGTAILADMIN_UNSAFE_PAGE_DELETION_LIMIT=3)
|
||||
@override_settings(WAGTAIL_SITE_NAME="mysite")
|
||||
def test_confirm_delete_scenario_4(self):
|
||||
# If admin entered the correct site name and submit the form
|
||||
# then the site should be deleted
|
||||
child_1 = SimplePage(title="child 1", slug="child-1", content="hello")
|
||||
self.child_page.add_child(instance=child_1)
|
||||
child_2 = SimplePage(title="child 2", slug="child-2", content="hello")
|
||||
self.child_page.add_child(instance=child_2)
|
||||
response = self.client.post(
|
||||
reverse("wagtailadmin_pages:delete", args=(self.child_page.id,)),
|
||||
data={"confirm_site_name": "mysite"},
|
||||
)
|
||||
# Should be redirected to explorer page
|
||||
self.assertRedirects(
|
||||
response, reverse("wagtailadmin_explore", args=(self.root_page.id,))
|
||||
)
|
||||
# Check that the page is deleted
|
||||
self.assertFalse(SimplePage.objects.filter(id=self.child_page.id).exists())
|
||||
# Check that the subpage is also deleted
|
||||
self.assertFalse(SimplePage.objects.filter(id=child_1.id).exists())
|
||||
self.assertFalse(SimplePage.objects.filter(id=child_2.id).exists())
|
||||
|
||||
def test_page_delete_specific_admin_title(self):
|
||||
response = self.client.get(
|
||||
reverse("wagtailadmin_pages:delete", args=(self.child_page.id,))
|
||||
)
|
||||
self.assertEqual(response.status_code, 200)
|
||||
|
||||
# The admin_display_title specific to ChildPage is shown on the delete confirmation page.
|
||||
self.assertContains(response, self.child_page.get_admin_display_title())
|
||||
|
||||
def test_page_delete_bad_permissions(self):
|
||||
# Remove privileges from user
|
||||
self.user.is_superuser = False
|
||||
self.user.user_permissions.add(
|
||||
Permission.objects.get(
|
||||
content_type__app_label="wagtailadmin", codename="access_admin"
|
||||
)
|
||||
)
|
||||
self.user.save()
|
||||
|
||||
# Get delete page
|
||||
response = self.client.get(
|
||||
reverse("wagtailadmin_pages:delete", args=(self.child_page.id,))
|
||||
)
|
||||
|
||||
# Check that the user received a 302 redirect response
|
||||
self.assertEqual(response.status_code, 302)
|
||||
|
||||
# Check that the deletion has not happened
|
||||
self.assertTrue(SimplePage.objects.filter(id=self.child_page.id).exists())
|
||||
|
||||
def test_page_delete_post(self):
|
||||
# Connect a mock signal handler to page_unpublished signal
|
||||
mock_handler = mock.MagicMock()
|
||||
page_unpublished.connect(mock_handler)
|
||||
|
||||
try:
|
||||
# Post
|
||||
response = self.client.post(
|
||||
reverse("wagtailadmin_pages:delete", args=(self.child_page.id,))
|
||||
)
|
||||
|
||||
# Should be redirected to explorer page
|
||||
self.assertRedirects(
|
||||
response, reverse("wagtailadmin_explore", args=(self.root_page.id,))
|
||||
)
|
||||
|
||||
# treebeard should report no consistency problems with the tree
|
||||
self.assertFalse(
|
||||
any(Page.find_problems()), msg="treebeard found consistency problems"
|
||||
)
|
||||
|
||||
# Check that the page is gone
|
||||
self.assertEqual(
|
||||
Page.objects.filter(
|
||||
path__startswith=self.root_page.path, slug="hello-world"
|
||||
).count(),
|
||||
0,
|
||||
)
|
||||
|
||||
# Check that the page_unpublished signal was fired
|
||||
self.assertEqual(mock_handler.call_count, 1)
|
||||
mock_call = mock_handler.mock_calls[0][2]
|
||||
|
||||
self.assertEqual(mock_call["sender"], self.child_page.specific_class)
|
||||
self.assertEqual(mock_call["instance"], self.child_page)
|
||||
self.assertIsInstance(mock_call["instance"], self.child_page.specific_class)
|
||||
finally:
|
||||
page_unpublished.disconnect(mock_handler)
|
||||
|
||||
def test_page_delete_notlive_post(self):
|
||||
# Same as above, but this makes sure the page_unpublished signal is not fired
|
||||
# when if the page is not live when it is deleted
|
||||
|
||||
# Unpublish the page
|
||||
self.child_page.live = False
|
||||
self.child_page.save()
|
||||
|
||||
# Connect a mock signal handler to page_unpublished signal
|
||||
mock_handler = mock.MagicMock()
|
||||
page_unpublished.connect(mock_handler)
|
||||
|
||||
try:
|
||||
# Post
|
||||
response = self.client.post(
|
||||
reverse("wagtailadmin_pages:delete", args=(self.child_page.id,))
|
||||
)
|
||||
|
||||
# Should be redirected to explorer page
|
||||
self.assertRedirects(
|
||||
response, reverse("wagtailadmin_explore", args=(self.root_page.id,))
|
||||
)
|
||||
|
||||
# treebeard should report no consistency problems with the tree
|
||||
self.assertFalse(
|
||||
any(Page.find_problems()), msg="treebeard found consistency problems"
|
||||
)
|
||||
|
||||
# Check that the page is gone
|
||||
self.assertEqual(
|
||||
Page.objects.filter(
|
||||
path__startswith=self.root_page.path, slug="hello-world"
|
||||
).count(),
|
||||
0,
|
||||
)
|
||||
|
||||
# Check that the page_unpublished signal was not fired
|
||||
self.assertEqual(mock_handler.call_count, 0)
|
||||
finally:
|
||||
page_unpublished.disconnect(mock_handler)
|
||||
|
||||
def test_subpage_deletion(self):
|
||||
# Connect mock signal handlers to page_unpublished, pre_delete and post_delete signals
|
||||
unpublish_signals_received = []
|
||||
pre_delete_signals_received = []
|
||||
post_delete_signals_received = []
|
||||
|
||||
def page_unpublished_handler(sender, instance, **kwargs):
|
||||
unpublish_signals_received.append((sender, instance.pk))
|
||||
|
||||
def pre_delete_handler(sender, instance, **kwargs):
|
||||
pre_delete_signals_received.append((sender, instance.pk))
|
||||
|
||||
def post_delete_handler(sender, instance, **kwargs):
|
||||
post_delete_signals_received.append((sender, instance.pk))
|
||||
|
||||
page_unpublished.connect(page_unpublished_handler)
|
||||
pre_delete.connect(pre_delete_handler)
|
||||
post_delete.connect(post_delete_handler)
|
||||
|
||||
try:
|
||||
# Post
|
||||
response = self.client.post(
|
||||
reverse("wagtailadmin_pages:delete", args=(self.child_index.id,))
|
||||
)
|
||||
|
||||
# Should be redirected to explorer page
|
||||
self.assertRedirects(
|
||||
response, reverse("wagtailadmin_explore", args=(self.root_page.id,))
|
||||
)
|
||||
|
||||
# treebeard should report no consistency problems with the tree
|
||||
self.assertFalse(
|
||||
any(Page.find_problems()), msg="treebeard found consistency problems"
|
||||
)
|
||||
|
||||
# Check that the page is gone
|
||||
self.assertFalse(
|
||||
StandardIndex.objects.filter(id=self.child_index.id).exists()
|
||||
)
|
||||
self.assertFalse(Page.objects.filter(id=self.child_index.id).exists())
|
||||
|
||||
# Check that the subpage is also gone
|
||||
self.assertFalse(
|
||||
StandardChild.objects.filter(id=self.grandchild_page.id).exists()
|
||||
)
|
||||
self.assertFalse(Page.objects.filter(id=self.grandchild_page.id).exists())
|
||||
|
||||
# Check that the signals were fired for both pages
|
||||
self.assertIn(
|
||||
(StandardIndex, self.child_index.id), unpublish_signals_received
|
||||
)
|
||||
self.assertIn(
|
||||
(StandardChild, self.grandchild_page.id), unpublish_signals_received
|
||||
)
|
||||
|
||||
self.assertIn(
|
||||
(StandardIndex, self.child_index.id), pre_delete_signals_received
|
||||
)
|
||||
self.assertIn(
|
||||
(StandardChild, self.grandchild_page.id), pre_delete_signals_received
|
||||
)
|
||||
|
||||
self.assertIn(
|
||||
(StandardIndex, self.child_index.id), post_delete_signals_received
|
||||
)
|
||||
self.assertIn(
|
||||
(StandardChild, self.grandchild_page.id), post_delete_signals_received
|
||||
)
|
||||
finally:
|
||||
page_unpublished.disconnect(page_unpublished_handler)
|
||||
pre_delete.disconnect(pre_delete_handler)
|
||||
post_delete.disconnect(post_delete_handler)
|
||||
|
||||
def test_before_delete_page_hook(self):
|
||||
def hook_func(request, page):
|
||||
self.assertIsInstance(request, HttpRequest)
|
||||
self.assertEqual(page.id, self.child_page.id)
|
||||
|
||||
return HttpResponse("Overridden!")
|
||||
|
||||
with self.register_hook("before_delete_page", hook_func):
|
||||
response = self.client.get(
|
||||
reverse("wagtailadmin_pages:delete", args=(self.child_page.id,))
|
||||
)
|
||||
|
||||
self.assertEqual(response.status_code, 200)
|
||||
self.assertEqual(response.content, b"Overridden!")
|
||||
|
||||
def test_before_delete_page_hook_post(self):
|
||||
def hook_func(request, page):
|
||||
self.assertIsInstance(request, HttpRequest)
|
||||
self.assertEqual(page.id, self.child_page.id)
|
||||
|
||||
return HttpResponse("Overridden!")
|
||||
|
||||
with self.register_hook("before_delete_page", hook_func):
|
||||
response = self.client.post(
|
||||
reverse("wagtailadmin_pages:delete", args=(self.child_page.id,))
|
||||
)
|
||||
|
||||
self.assertEqual(response.status_code, 200)
|
||||
self.assertEqual(response.content, b"Overridden!")
|
||||
|
||||
# page should not be deleted
|
||||
self.assertTrue(Page.objects.filter(id=self.child_page.id).exists())
|
||||
|
||||
def test_after_delete_page_hook(self):
|
||||
def hook_func(request, page):
|
||||
self.assertIsInstance(request, HttpRequest)
|
||||
self.assertEqual(page.id, self.child_page.id)
|
||||
|
||||
return HttpResponse("Overridden!")
|
||||
|
||||
with self.register_hook("after_delete_page", hook_func):
|
||||
response = self.client.post(
|
||||
reverse("wagtailadmin_pages:delete", args=(self.child_page.id,))
|
||||
)
|
||||
|
||||
self.assertEqual(response.status_code, 200)
|
||||
self.assertEqual(response.content, b"Overridden!")
|
||||
|
||||
# page should be deleted
|
||||
self.assertFalse(Page.objects.filter(id=self.child_page.id).exists())
|
||||
3925
env/lib/python3.10/site-packages/wagtail/admin/tests/pages/test_edit_page.py
vendored
Normal file
3925
env/lib/python3.10/site-packages/wagtail/admin/tests/pages/test_edit_page.py
vendored
Normal file
File diff suppressed because it is too large
Load Diff
1288
env/lib/python3.10/site-packages/wagtail/admin/tests/pages/test_explorer_view.py
vendored
Normal file
1288
env/lib/python3.10/site-packages/wagtail/admin/tests/pages/test_explorer_view.py
vendored
Normal file
File diff suppressed because it is too large
Load Diff
264
env/lib/python3.10/site-packages/wagtail/admin/tests/pages/test_move_page.py
vendored
Normal file
264
env/lib/python3.10/site-packages/wagtail/admin/tests/pages/test_move_page.py
vendored
Normal file
@@ -0,0 +1,264 @@
|
||||
from unittest import mock
|
||||
|
||||
from django.contrib.auth import get_user_model
|
||||
from django.contrib.auth.models import Permission
|
||||
from django.contrib.messages import constants as message_constants
|
||||
from django.http import HttpRequest, HttpResponse
|
||||
from django.test import TestCase
|
||||
from django.urls import reverse
|
||||
|
||||
from wagtail.models import Page
|
||||
from wagtail.signals import post_page_move, pre_page_move
|
||||
from wagtail.test.testapp.models import BusinessSubIndex, SimplePage
|
||||
from wagtail.test.utils import WagtailTestUtils
|
||||
|
||||
|
||||
class TestPageMove(WagtailTestUtils, TestCase):
|
||||
fixtures = ["test.json"]
|
||||
|
||||
@classmethod
|
||||
def setUpTestData(cls):
|
||||
# Find root page
|
||||
cls.root_page = Page.objects.get(id=2)
|
||||
|
||||
# Create three sections
|
||||
cls.section_a = SimplePage(title="Section A", slug="section-a", content="hello")
|
||||
cls.root_page.add_child(instance=cls.section_a)
|
||||
|
||||
cls.section_b = SimplePage(title="Section B", slug="section-b", content="hello")
|
||||
cls.root_page.add_child(instance=cls.section_b)
|
||||
|
||||
cls.section_c = SimplePage(title="Section C", slug="section-c", content="hello")
|
||||
cls.root_page.add_child(instance=cls.section_c)
|
||||
|
||||
# Add test page A into section A
|
||||
cls.test_page_a = SimplePage(
|
||||
title="Hello world!", slug="hello-world", content="hello"
|
||||
)
|
||||
cls.section_a.add_child(instance=cls.test_page_a)
|
||||
|
||||
# Add test page B into section C
|
||||
cls.test_page_b = SimplePage(
|
||||
title="Hello world!", slug="hello-world", content="hello"
|
||||
)
|
||||
cls.section_c.add_child(instance=cls.test_page_b)
|
||||
|
||||
# Add unpublished page to the root with a child page
|
||||
cls.unpublished_page = SimplePage(
|
||||
title="Unpublished", slug="unpublished", content="hello"
|
||||
)
|
||||
sub_page = SimplePage(title="Sub Page", slug="sub-page", content="child")
|
||||
cls.root_page.add_child(instance=cls.unpublished_page)
|
||||
cls.unpublished_page.add_child(instance=sub_page)
|
||||
|
||||
# unpublish pages last (used to validate the edit only permission)
|
||||
cls.unpublished_page.unpublish()
|
||||
sub_page.unpublish()
|
||||
|
||||
def setUp(self):
|
||||
# Login
|
||||
self.user = self.login()
|
||||
|
||||
def test_page_move(self):
|
||||
response = self.client.get(
|
||||
reverse("wagtailadmin_pages:move", args=(self.test_page_a.id,))
|
||||
)
|
||||
self.assertEqual(response.status_code, 200)
|
||||
self.assertContains(response, self.section_a.title)
|
||||
|
||||
def test_page_move_bad_permissions(self):
|
||||
# Remove privileges from user
|
||||
self.user.is_superuser = False
|
||||
self.user.user_permissions.add(
|
||||
Permission.objects.get(
|
||||
content_type__app_label="wagtailadmin", codename="access_admin"
|
||||
)
|
||||
)
|
||||
self.user.save()
|
||||
|
||||
# Get move page
|
||||
response = self.client.get(
|
||||
reverse("wagtailadmin_pages:move", args=(self.test_page_a.id,))
|
||||
)
|
||||
|
||||
# Check that the user received a 302 redirected response
|
||||
self.assertEqual(response.status_code, 302)
|
||||
|
||||
def test_user_without_bulk_delete_permission_can_move(self):
|
||||
# to verify that a user without bulk delete permission is able to move a page with a child page
|
||||
|
||||
self.client.logout()
|
||||
user = get_user_model().objects.get(email="siteeditor@example.com")
|
||||
self.login(user)
|
||||
|
||||
# ensure the bulk_delete is not applicable to this user
|
||||
can_bulk_delete = self.test_page_b.permissions_for_user(user).can_delete()
|
||||
self.assertFalse(can_bulk_delete)
|
||||
|
||||
response = self.client.get(
|
||||
reverse("wagtailadmin_pages:move", args=(self.unpublished_page.id,))
|
||||
)
|
||||
|
||||
self.assertEqual(response.status_code, 200)
|
||||
|
||||
def test_page_move_confirm(self):
|
||||
response = self.client.get(
|
||||
reverse(
|
||||
"wagtailadmin_pages:move_confirm",
|
||||
args=(self.test_page_a.id, self.section_b.id),
|
||||
)
|
||||
)
|
||||
self.assertEqual(response.status_code, 200)
|
||||
|
||||
response = self.client.get(
|
||||
reverse(
|
||||
"wagtailadmin_pages:move_confirm",
|
||||
args=(self.test_page_b.id, self.section_a.id),
|
||||
)
|
||||
)
|
||||
# Duplicate slugs triggers a redirect with an error message.
|
||||
self.assertEqual(response.status_code, 302)
|
||||
|
||||
response = self.client.get(reverse("wagtailadmin_home"))
|
||||
messages = list(response.context["messages"])
|
||||
self.assertEqual(len(messages), 1)
|
||||
self.assertEqual(messages[0].level, message_constants.ERROR)
|
||||
# Slug should be in error message.
|
||||
self.assertIn(self.test_page_b.slug, messages[0].message)
|
||||
|
||||
def test_move_triggers_signals(self):
|
||||
# Connect a mock signal handler to pre_page_move and post_page_move signals
|
||||
pre_moved_handler = mock.MagicMock()
|
||||
post_moved_handler = mock.MagicMock()
|
||||
|
||||
pre_page_move.connect(pre_moved_handler)
|
||||
post_page_move.connect(post_moved_handler)
|
||||
|
||||
# Post to view to move page
|
||||
try:
|
||||
self.client.post(
|
||||
reverse(
|
||||
"wagtailadmin_pages:move_confirm",
|
||||
args=(self.test_page_a.id, self.section_b.id),
|
||||
)
|
||||
)
|
||||
finally:
|
||||
# Disconnect mock handler to prevent cross-test pollution
|
||||
pre_page_move.disconnect(pre_moved_handler)
|
||||
post_page_move.disconnect(post_moved_handler)
|
||||
|
||||
# parent_page_before returns the non-specific page type, and that's OK
|
||||
nonspecific_section_a = Page.objects.get(pk=self.section_a.pk)
|
||||
|
||||
# Check that the pre_page_move signal was fired
|
||||
self.assertEqual(pre_moved_handler.call_count, 1)
|
||||
pre_moved_handler.assert_called_with(
|
||||
signal=mock.ANY,
|
||||
sender=self.test_page_a.specific_class,
|
||||
instance=self.test_page_a,
|
||||
parent_page_before=nonspecific_section_a,
|
||||
parent_page_after=self.section_b,
|
||||
url_path_before="/home/section-a/hello-world/",
|
||||
url_path_after="/home/section-b/hello-world/",
|
||||
)
|
||||
|
||||
# Check that the post_page_move signal was fired
|
||||
self.assertEqual(post_moved_handler.call_count, 1)
|
||||
post_moved_handler.assert_called_with(
|
||||
signal=mock.ANY,
|
||||
sender=self.test_page_a.specific_class,
|
||||
# during the move operation, we reloaded the page as a non-specific instance
|
||||
instance=Page.objects.get(pk=self.test_page_a.pk),
|
||||
parent_page_before=nonspecific_section_a,
|
||||
parent_page_after=self.section_b,
|
||||
url_path_before="/home/section-a/hello-world/",
|
||||
url_path_after="/home/section-b/hello-world/",
|
||||
)
|
||||
|
||||
def test_before_move_page_hook(self):
|
||||
def hook_func(request, page, destination):
|
||||
self.assertIsInstance(request, HttpRequest)
|
||||
self.assertIsInstance(page.specific, SimplePage)
|
||||
self.assertIsInstance(destination.specific, SimplePage)
|
||||
|
||||
return HttpResponse("Overridden!")
|
||||
|
||||
with self.register_hook("before_move_page", hook_func):
|
||||
response = self.client.get(
|
||||
reverse(
|
||||
"wagtailadmin_pages:move_confirm",
|
||||
args=(self.test_page_a.id, self.section_b.id),
|
||||
)
|
||||
)
|
||||
|
||||
self.assertEqual(response.status_code, 200)
|
||||
self.assertEqual(response.content, b"Overridden!")
|
||||
|
||||
def test_before_move_page_hook_post(self):
|
||||
def hook_func(request, page, destination):
|
||||
self.assertIsInstance(request, HttpRequest)
|
||||
self.assertIsInstance(page.specific, SimplePage)
|
||||
self.assertIsInstance(destination.specific, SimplePage)
|
||||
|
||||
return HttpResponse("Overridden!")
|
||||
|
||||
with self.register_hook("before_move_page", hook_func):
|
||||
response = self.client.post(
|
||||
reverse(
|
||||
"wagtailadmin_pages:move_confirm",
|
||||
args=(self.test_page_a.id, self.section_b.id),
|
||||
)
|
||||
)
|
||||
|
||||
self.assertEqual(response.status_code, 200)
|
||||
self.assertEqual(response.content, b"Overridden!")
|
||||
|
||||
# page should not be moved
|
||||
self.assertEqual(
|
||||
Page.objects.get(id=self.test_page_a.id).get_parent().id, self.section_a.id
|
||||
)
|
||||
|
||||
def test_after_move_page_hook(self):
|
||||
def hook_func(request, page):
|
||||
self.assertIsInstance(request, HttpRequest)
|
||||
self.assertIsInstance(page.specific, SimplePage)
|
||||
|
||||
return HttpResponse("Overridden!")
|
||||
|
||||
with self.register_hook("after_move_page", hook_func):
|
||||
response = self.client.post(
|
||||
reverse(
|
||||
"wagtailadmin_pages:move_confirm",
|
||||
args=(self.test_page_a.id, self.section_b.id),
|
||||
)
|
||||
)
|
||||
|
||||
self.assertEqual(response.status_code, 200)
|
||||
self.assertEqual(response.content, b"Overridden!")
|
||||
|
||||
# page should be moved
|
||||
self.assertEqual(
|
||||
Page.objects.get(id=self.test_page_a.id).get_parent().id, self.section_b.id
|
||||
)
|
||||
|
||||
def test_page_move_after_parent_page_types_changes_to_different_parent_model(self):
|
||||
# Test for issue #10348
|
||||
# While BusinessSubIndex cannot be created under a SimplePage, we can
|
||||
# still create it under a SimplePage invoking django-treebeard's add_child
|
||||
# which works great for our purposes.
|
||||
self.assertFalse(BusinessSubIndex.can_exist_under(self.section_a))
|
||||
page = self.section_a.add_child(
|
||||
instance=BusinessSubIndex(
|
||||
title="Business Sub Index",
|
||||
slug="business-sub-index",
|
||||
live=True,
|
||||
has_unpublished_changes=False,
|
||||
)
|
||||
)
|
||||
|
||||
response = self.client.get(reverse("wagtailadmin_pages:move", args=(page.id,)))
|
||||
self.assertEqual(response.status_code, 200)
|
||||
|
||||
form = response.context["move_form"]
|
||||
self.assertEqual(form.fields["new_parent_page"].initial.pk, self.section_a.pk)
|
||||
self.assertNotContains(response, self.section_a.title)
|
||||
345
env/lib/python3.10/site-packages/wagtail/admin/tests/pages/test_page_locking.py
vendored
Normal file
345
env/lib/python3.10/site-packages/wagtail/admin/tests/pages/test_page_locking.py
vendored
Normal file
@@ -0,0 +1,345 @@
|
||||
from django.contrib.auth.models import Group, Permission
|
||||
from django.test import TestCase
|
||||
from django.urls import reverse
|
||||
from django.utils import timezone
|
||||
from django.utils.html import escape
|
||||
|
||||
from wagtail.models import Page
|
||||
from wagtail.test.testapp.models import SimplePage
|
||||
from wagtail.test.utils import WagtailTestUtils
|
||||
|
||||
|
||||
class TestLocking(WagtailTestUtils, TestCase):
|
||||
def setUp(self):
|
||||
# Find root page
|
||||
self.root_page = Page.objects.get(id=2)
|
||||
|
||||
# Login
|
||||
self.user = self.login()
|
||||
|
||||
# Create a page and submit it for moderation
|
||||
self.child_page = SimplePage(
|
||||
title="Hello world!",
|
||||
slug="hello-world",
|
||||
content="hello",
|
||||
live=False,
|
||||
)
|
||||
self.root_page.add_child(instance=self.child_page)
|
||||
|
||||
def test_lock_post(self):
|
||||
response = self.client.post(
|
||||
reverse("wagtailadmin_pages:lock", args=(self.child_page.id,))
|
||||
)
|
||||
|
||||
# Check response
|
||||
self.assertRedirects(
|
||||
response, reverse("wagtailadmin_explore", args=(self.root_page.id,))
|
||||
)
|
||||
|
||||
# Check that the page is locked
|
||||
page = Page.objects.get(id=self.child_page.id)
|
||||
self.assertTrue(page.locked)
|
||||
self.assertEqual(page.locked_by, self.user)
|
||||
self.assertIsNotNone(page.locked_at)
|
||||
|
||||
def test_lock_get(self):
|
||||
response = self.client.get(
|
||||
reverse("wagtailadmin_pages:lock", args=(self.child_page.id,))
|
||||
)
|
||||
|
||||
# Check response
|
||||
self.assertEqual(response.status_code, 405)
|
||||
|
||||
# Check that the page is still unlocked
|
||||
page = Page.objects.get(id=self.child_page.id)
|
||||
self.assertFalse(page.locked)
|
||||
self.assertIsNone(page.locked_by)
|
||||
self.assertIsNone(page.locked_at)
|
||||
|
||||
def test_lock_post_already_locked(self):
|
||||
# Lock the page
|
||||
self.child_page.locked = True
|
||||
self.child_page.locked_by = self.user
|
||||
self.child_page.locked_at = timezone.now()
|
||||
self.child_page.save()
|
||||
|
||||
response = self.client.post(
|
||||
reverse("wagtailadmin_pages:lock", args=(self.child_page.id,))
|
||||
)
|
||||
|
||||
# Check response
|
||||
self.assertRedirects(
|
||||
response, reverse("wagtailadmin_explore", args=(self.root_page.id,))
|
||||
)
|
||||
|
||||
# Check that the page is still locked
|
||||
page = Page.objects.get(id=self.child_page.id)
|
||||
self.assertTrue(page.locked)
|
||||
self.assertEqual(page.locked_by, self.user)
|
||||
self.assertIsNotNone(page.locked_at)
|
||||
|
||||
def test_lock_post_with_good_redirect(self):
|
||||
response = self.client.post(
|
||||
reverse("wagtailadmin_pages:lock", args=(self.child_page.id,)),
|
||||
{"next": reverse("wagtailadmin_pages:edit", args=(self.child_page.id,))},
|
||||
)
|
||||
|
||||
# Check response
|
||||
self.assertRedirects(
|
||||
response, reverse("wagtailadmin_pages:edit", args=(self.child_page.id,))
|
||||
)
|
||||
|
||||
# Check that the page is locked
|
||||
page = Page.objects.get(id=self.child_page.id)
|
||||
self.assertTrue(page.locked)
|
||||
self.assertEqual(page.locked_by, self.user)
|
||||
self.assertIsNotNone(page.locked_at)
|
||||
|
||||
def test_lock_post_with_bad_redirect(self):
|
||||
response = self.client.post(
|
||||
reverse("wagtailadmin_pages:lock", args=(self.child_page.id,)),
|
||||
{"next": "http://www.google.co.uk"},
|
||||
)
|
||||
|
||||
# Check response
|
||||
self.assertRedirects(
|
||||
response, reverse("wagtailadmin_explore", args=(self.root_page.id,))
|
||||
)
|
||||
|
||||
# Check that the page is locked
|
||||
page = Page.objects.get(id=self.child_page.id)
|
||||
self.assertTrue(page.locked)
|
||||
self.assertEqual(page.locked_by, self.user)
|
||||
self.assertIsNotNone(page.locked_at)
|
||||
|
||||
def test_lock_post_bad_page(self):
|
||||
response = self.client.post(reverse("wagtailadmin_pages:lock", args=(9999,)))
|
||||
|
||||
# Check response
|
||||
self.assertEqual(response.status_code, 404)
|
||||
|
||||
# Check that the page is still unlocked
|
||||
page = Page.objects.get(id=self.child_page.id)
|
||||
self.assertFalse(page.locked)
|
||||
self.assertIsNone(page.locked_by)
|
||||
self.assertIsNone(page.locked_at)
|
||||
|
||||
def test_lock_post_bad_permissions(self):
|
||||
# Remove privileges from user
|
||||
self.user.is_superuser = False
|
||||
self.user.user_permissions.add(
|
||||
Permission.objects.get(
|
||||
content_type__app_label="wagtailadmin", codename="access_admin"
|
||||
)
|
||||
)
|
||||
self.user.save()
|
||||
|
||||
response = self.client.post(
|
||||
reverse("wagtailadmin_pages:lock", args=(self.child_page.id,))
|
||||
)
|
||||
|
||||
# Check response
|
||||
self.assertEqual(response.status_code, 302)
|
||||
|
||||
# Check that the page is still unlocked
|
||||
page = Page.objects.get(id=self.child_page.id)
|
||||
self.assertFalse(page.locked)
|
||||
self.assertIsNone(page.locked_by)
|
||||
self.assertIsNone(page.locked_at)
|
||||
|
||||
def test_locked_pages_dashboard_panel(self):
|
||||
self.child_page.locked = True
|
||||
self.child_page.locked_by = self.user
|
||||
self.child_page.locked_at = timezone.now()
|
||||
self.child_page.save()
|
||||
response = self.client.get(reverse("wagtailadmin_home"))
|
||||
self.assertContains(response, "Your locked pages")
|
||||
# check that Unlock button is present
|
||||
self.assertContains(response, "Unlock")
|
||||
|
||||
def test_unlock_post(self):
|
||||
# Lock the page
|
||||
self.child_page.locked = True
|
||||
self.child_page.locked_by = self.user
|
||||
self.child_page.locked_at = timezone.now()
|
||||
self.child_page.save()
|
||||
|
||||
response = self.client.post(
|
||||
reverse("wagtailadmin_pages:unlock", args=(self.child_page.id,))
|
||||
)
|
||||
|
||||
# Check response
|
||||
self.assertRedirects(
|
||||
response, reverse("wagtailadmin_explore", args=(self.root_page.id,))
|
||||
)
|
||||
|
||||
# Check that the page is unlocked
|
||||
page = Page.objects.get(id=self.child_page.id)
|
||||
self.assertFalse(page.locked)
|
||||
self.assertIsNone(page.locked_by)
|
||||
self.assertIsNone(page.locked_at)
|
||||
|
||||
def test_unlock_get(self):
|
||||
# Lock the page
|
||||
self.child_page.locked = True
|
||||
self.child_page.locked_by = self.user
|
||||
self.child_page.locked_at = timezone.now()
|
||||
self.child_page.save()
|
||||
|
||||
response = self.client.get(
|
||||
reverse("wagtailadmin_pages:unlock", args=(self.child_page.id,))
|
||||
)
|
||||
|
||||
# Check response
|
||||
self.assertEqual(response.status_code, 405)
|
||||
|
||||
# Check that the page is still locked
|
||||
page = Page.objects.get(id=self.child_page.id)
|
||||
self.assertTrue(page.locked)
|
||||
self.assertEqual(page.locked_by, self.user)
|
||||
self.assertIsNotNone(page.locked_at)
|
||||
|
||||
def test_unlock_post_already_unlocked(self):
|
||||
response = self.client.post(
|
||||
reverse("wagtailadmin_pages:unlock", args=(self.child_page.id,))
|
||||
)
|
||||
|
||||
# Check response
|
||||
self.assertRedirects(
|
||||
response, reverse("wagtailadmin_explore", args=(self.root_page.id,))
|
||||
)
|
||||
|
||||
# Check that the page is still unlocked
|
||||
page = Page.objects.get(id=self.child_page.id)
|
||||
self.assertFalse(page.locked)
|
||||
self.assertIsNone(page.locked_by)
|
||||
self.assertIsNone(page.locked_at)
|
||||
|
||||
def test_unlock_post_with_good_redirect(self):
|
||||
# Lock the page
|
||||
self.child_page.locked = True
|
||||
self.child_page.locked_by = self.user
|
||||
self.child_page.locked_at = timezone.now()
|
||||
self.child_page.save()
|
||||
|
||||
response = self.client.post(
|
||||
reverse("wagtailadmin_pages:unlock", args=(self.child_page.id,)),
|
||||
{"next": reverse("wagtailadmin_pages:edit", args=(self.child_page.id,))},
|
||||
follow=True,
|
||||
)
|
||||
|
||||
# Check response
|
||||
self.assertRedirects(
|
||||
response, reverse("wagtailadmin_pages:edit", args=(self.child_page.id,))
|
||||
)
|
||||
|
||||
# Should show unlocked message
|
||||
self.assertContains(
|
||||
response, escape("Page 'Hello world! (simple page)' is now unlocked.")
|
||||
)
|
||||
|
||||
# Message shouldn't be wrapped in a tuple
|
||||
self.assertNotContains(
|
||||
response,
|
||||
escape(("Page 'Hello world! (simple page)' is now unlocked.",)),
|
||||
)
|
||||
|
||||
# Check that the page is unlocked
|
||||
page = Page.objects.get(id=self.child_page.id)
|
||||
self.assertFalse(page.locked)
|
||||
self.assertIsNone(page.locked_by)
|
||||
self.assertIsNone(page.locked_at)
|
||||
|
||||
def test_unlock_post_with_bad_redirect(self):
|
||||
# Lock the page
|
||||
self.child_page.locked = True
|
||||
self.child_page.locked_by = self.user
|
||||
self.child_page.locked_at = timezone.now()
|
||||
self.child_page.save()
|
||||
|
||||
response = self.client.post(
|
||||
reverse("wagtailadmin_pages:unlock", args=(self.child_page.id,)),
|
||||
{"next": "http://www.google.co.uk"},
|
||||
)
|
||||
|
||||
# Check response
|
||||
self.assertRedirects(
|
||||
response, reverse("wagtailadmin_explore", args=(self.root_page.id,))
|
||||
)
|
||||
|
||||
# Check that the page is unlocked
|
||||
page = Page.objects.get(id=self.child_page.id)
|
||||
self.assertFalse(page.locked)
|
||||
self.assertIsNone(page.locked_by)
|
||||
self.assertIsNone(page.locked_at)
|
||||
|
||||
def test_unlock_post_bad_page(self):
|
||||
# Lock the page
|
||||
self.child_page.locked = True
|
||||
self.child_page.locked_by = self.user
|
||||
self.child_page.locked_at = timezone.now()
|
||||
self.child_page.save()
|
||||
|
||||
response = self.client.post(reverse("wagtailadmin_pages:unlock", args=(9999,)))
|
||||
|
||||
# Check response
|
||||
self.assertEqual(response.status_code, 404)
|
||||
|
||||
# Check that the page is still locked
|
||||
page = Page.objects.get(id=self.child_page.id)
|
||||
self.assertTrue(page.locked)
|
||||
self.assertEqual(page.locked_by, self.user)
|
||||
self.assertIsNotNone(page.locked_at)
|
||||
|
||||
def test_unlock_post_bad_permissions(self):
|
||||
# Remove privileges from user
|
||||
self.user.is_superuser = False
|
||||
self.user.groups.add(Group.objects.get(name="Editors"))
|
||||
self.user.save()
|
||||
|
||||
# Lock the page
|
||||
self.child_page.locked = True
|
||||
self.child_page.locked_at = timezone.now()
|
||||
self.child_page.save()
|
||||
|
||||
response = self.client.post(
|
||||
reverse("wagtailadmin_pages:unlock", args=(self.child_page.id,))
|
||||
)
|
||||
|
||||
# Check response
|
||||
self.assertEqual(response.status_code, 302)
|
||||
|
||||
# Check that the page is still locked
|
||||
page = Page.objects.get(id=self.child_page.id)
|
||||
self.assertTrue(page.locked)
|
||||
self.assertIsNotNone(page.locked_at)
|
||||
|
||||
def test_unlock_post_own_page_with_bad_permissions(self):
|
||||
# Unlike the previous test, the user can unlock pages that they have locked
|
||||
|
||||
# Remove privileges from user
|
||||
self.user.is_superuser = False
|
||||
self.user.groups.add(Group.objects.get(name="Editors"))
|
||||
self.user.save()
|
||||
|
||||
# Lock the page
|
||||
self.child_page.locked = True
|
||||
self.child_page.locked_by = self.user
|
||||
self.child_page.locked_at = timezone.now()
|
||||
self.child_page.save()
|
||||
|
||||
response = self.client.post(
|
||||
reverse("wagtailadmin_pages:unlock", args=(self.child_page.id,)),
|
||||
{"next": reverse("wagtailadmin_pages:edit", args=(self.child_page.id,))},
|
||||
)
|
||||
|
||||
# Check response
|
||||
self.assertRedirects(
|
||||
response, reverse("wagtailadmin_pages:edit", args=(self.child_page.id,))
|
||||
)
|
||||
|
||||
# Check that the page is still locked
|
||||
page = Page.objects.get(id=self.child_page.id)
|
||||
self.assertFalse(page.locked)
|
||||
self.assertIsNone(page.locked_by)
|
||||
self.assertIsNone(page.locked_at)
|
||||
329
env/lib/python3.10/site-packages/wagtail/admin/tests/pages/test_page_search.py
vendored
Normal file
329
env/lib/python3.10/site-packages/wagtail/admin/tests/pages/test_page_search.py
vendored
Normal file
@@ -0,0 +1,329 @@
|
||||
from io import StringIO
|
||||
|
||||
from django.contrib.auth.models import Permission
|
||||
from django.core import management
|
||||
from django.test import TransactionTestCase
|
||||
from django.urls import reverse
|
||||
from django.utils.http import urlencode
|
||||
|
||||
from wagtail.models import Page
|
||||
from wagtail.test.testapp.models import EventIndex, SimplePage, SingleEventPage
|
||||
from wagtail.test.utils import WagtailTestUtils
|
||||
from wagtail.test.utils.timestamps import local_datetime
|
||||
|
||||
|
||||
class TestPageSearch(WagtailTestUtils, TransactionTestCase):
|
||||
fixtures = ["test_empty.json"]
|
||||
|
||||
def setUp(self):
|
||||
super().setUp()
|
||||
management.call_command(
|
||||
"update_index",
|
||||
backend_name="default",
|
||||
stdout=StringIO(),
|
||||
chunk_size=50,
|
||||
)
|
||||
self.user = self.login()
|
||||
|
||||
def get(self, params=None, url_name="wagtailadmin_pages:search", **extra):
|
||||
return self.client.get(reverse(url_name), params or {}, **extra)
|
||||
|
||||
def test_view(self):
|
||||
response = self.get()
|
||||
self.assertTemplateUsed(response, "wagtailadmin/pages/search.html")
|
||||
self.assertEqual(response.status_code, 200)
|
||||
|
||||
def test_search(self):
|
||||
# Find root page
|
||||
root_page = Page.objects.get(id=2)
|
||||
|
||||
# Create a page
|
||||
new_page = root_page.add_child(
|
||||
instance=SimplePage(
|
||||
title="Hello from Cauldron Lake",
|
||||
slug="bright-falls",
|
||||
content="It's not a lake, it's an ocean",
|
||||
live=True,
|
||||
has_unpublished_changes=False,
|
||||
)
|
||||
)
|
||||
|
||||
response = self.get({"q": "Hello"})
|
||||
self.assertEqual(response.status_code, 200)
|
||||
self.assertTemplateUsed(response, "wagtailadmin/pages/search.html")
|
||||
self.assertEqual(response.context["query_string"], "Hello")
|
||||
next_url = urlencode({"next": reverse("wagtailadmin_pages:search")})
|
||||
expected_new_page_copy_url = (
|
||||
reverse("wagtailadmin_pages:copy", args=(new_page.pk,)) + f"?{next_url}"
|
||||
)
|
||||
self.assertContains(response, f'href="{expected_new_page_copy_url}"')
|
||||
|
||||
def test_search_searchable_fields(self):
|
||||
# Find root page
|
||||
root_page = Page.objects.get(id=2)
|
||||
|
||||
# Create a page
|
||||
root_page.add_child(
|
||||
instance=SimplePage(
|
||||
title="Greetings!",
|
||||
slug="hello",
|
||||
content="good morning",
|
||||
live=True,
|
||||
has_unpublished_changes=False,
|
||||
)
|
||||
)
|
||||
|
||||
# Confirm the slug is not being searched
|
||||
response = self.get({"q": "hello"})
|
||||
self.assertNotContains(response, "There is one matching page")
|
||||
|
||||
# Confirm the title is being searched
|
||||
response = self.get({"q": "greetings"})
|
||||
self.assertContains(response, "There is one matching page")
|
||||
|
||||
def test_ajax(self):
|
||||
# Find root page
|
||||
root_page = Page.objects.get(id=2)
|
||||
|
||||
# Create a page
|
||||
new_page = root_page.add_child(
|
||||
instance=SimplePage(
|
||||
title="Hello from Cauldron Lake",
|
||||
slug="bright-falls",
|
||||
content="It's not a lake, it's an ocean",
|
||||
live=True,
|
||||
has_unpublished_changes=False,
|
||||
)
|
||||
)
|
||||
|
||||
response = self.get(
|
||||
{"q": "Hello"}, url_name="wagtailadmin_pages:search_results"
|
||||
)
|
||||
self.assertEqual(response.status_code, 200)
|
||||
self.assertTemplateNotUsed(response, "wagtailadmin/pages/search.html")
|
||||
self.assertTemplateUsed(response, "wagtailadmin/pages/search_results.html")
|
||||
self.assertEqual(response.context["query_string"], "Hello")
|
||||
next_url = urlencode({"next": reverse("wagtailadmin_pages:search")})
|
||||
expected_new_page_copy_url = (
|
||||
reverse("wagtailadmin_pages:copy", args=(new_page.pk,)) + f"?{next_url}"
|
||||
)
|
||||
self.assertContains(response, f'href="{expected_new_page_copy_url}"')
|
||||
|
||||
def test_pagination(self):
|
||||
# page numbers in range should be accepted
|
||||
response = self.get({"q": "Hello", "p": 1})
|
||||
self.assertEqual(response.status_code, 200)
|
||||
self.assertTemplateUsed(response, "wagtailadmin/pages/search.html")
|
||||
# page numbers out of range should return 404
|
||||
response = self.get({"q": "Hello", "p": 9999})
|
||||
self.assertEqual(response.status_code, 404)
|
||||
|
||||
def test_root_can_appear_in_search_results(self):
|
||||
response = self.get({"q": "root"})
|
||||
self.assertEqual(response.status_code, 200)
|
||||
# 'pages' list in the response should contain root
|
||||
results = response.context["pages"]
|
||||
self.assertTrue(any(r.slug == "root" for r in results))
|
||||
|
||||
def test_search_uses_admin_display_title_from_specific_class(self):
|
||||
# SingleEventPage has a custom get_admin_display_title method; explorer should
|
||||
# show the custom title rather than the basic database one
|
||||
root_page = Page.objects.get(id=2)
|
||||
new_event = SingleEventPage(
|
||||
title="Lunar event",
|
||||
location="the moon",
|
||||
audience="public",
|
||||
cost="free",
|
||||
date_from="2001-01-01",
|
||||
latest_revision_created_at=local_datetime(2016, 1, 1),
|
||||
)
|
||||
root_page.add_child(instance=new_event)
|
||||
response = self.get({"q": "lunar"})
|
||||
self.assertContains(response, "Lunar event (single event)")
|
||||
|
||||
def test_search_no_perms(self):
|
||||
self.user.is_superuser = False
|
||||
self.user.user_permissions.add(
|
||||
Permission.objects.get(
|
||||
content_type__app_label="wagtailadmin", codename="access_admin"
|
||||
)
|
||||
)
|
||||
self.user.save()
|
||||
self.assertRedirects(self.get(), "/admin/")
|
||||
|
||||
def test_search_order_by_title(self):
|
||||
root_page = Page.objects.get(id=2)
|
||||
new_event = SingleEventPage(
|
||||
title="Lunar event",
|
||||
location="the moon",
|
||||
audience="public",
|
||||
cost="free",
|
||||
date_from="2001-01-01",
|
||||
latest_revision_created_at=local_datetime(2016, 1, 1),
|
||||
)
|
||||
root_page.add_child(instance=new_event)
|
||||
|
||||
new_event_2 = SingleEventPage(
|
||||
title="A Lunar event",
|
||||
location="the moon",
|
||||
audience="public",
|
||||
cost="free",
|
||||
date_from="2001-01-01",
|
||||
latest_revision_created_at=local_datetime(2016, 1, 1),
|
||||
)
|
||||
root_page.add_child(instance=new_event_2)
|
||||
|
||||
response = self.get({"q": "Lunar", "ordering": "title"})
|
||||
page_ids = [page.id for page in response.context["pages"]]
|
||||
self.assertEqual(page_ids, [new_event_2.id, new_event.id])
|
||||
|
||||
response = self.get({"q": "Lunar", "ordering": "-title"})
|
||||
page_ids = [page.id for page in response.context["pages"]]
|
||||
self.assertEqual(page_ids, [new_event.id, new_event_2.id])
|
||||
|
||||
def test_search_order_by_updated(self):
|
||||
root_page = Page.objects.get(id=2)
|
||||
new_event = SingleEventPage(
|
||||
title="Lunar event",
|
||||
location="the moon",
|
||||
audience="public",
|
||||
cost="free",
|
||||
date_from="2001-01-01",
|
||||
latest_revision_created_at=local_datetime(2016, 1, 1),
|
||||
)
|
||||
root_page.add_child(instance=new_event)
|
||||
|
||||
new_event_2 = SingleEventPage(
|
||||
title="Lunar event 2",
|
||||
location="the moon",
|
||||
audience="public",
|
||||
cost="free",
|
||||
date_from="2001-01-01",
|
||||
latest_revision_created_at=local_datetime(2015, 1, 1),
|
||||
)
|
||||
root_page.add_child(instance=new_event_2)
|
||||
|
||||
response = self.get({"q": "Lunar", "ordering": "latest_revision_created_at"})
|
||||
page_ids = [page.id for page in response.context["pages"]]
|
||||
self.assertEqual(page_ids, [new_event_2.id, new_event.id])
|
||||
|
||||
response = self.get({"q": "Lunar", "ordering": "-latest_revision_created_at"})
|
||||
page_ids = [page.id for page in response.context["pages"]]
|
||||
self.assertEqual(page_ids, [new_event.id, new_event_2.id])
|
||||
|
||||
def test_search_order_by_status(self):
|
||||
root_page = Page.objects.get(id=2)
|
||||
live_event = SingleEventPage(
|
||||
title="Lunar event",
|
||||
location="the moon",
|
||||
audience="public",
|
||||
cost="free",
|
||||
date_from="2001-01-01",
|
||||
latest_revision_created_at=local_datetime(2016, 1, 1),
|
||||
live=True,
|
||||
)
|
||||
root_page.add_child(instance=live_event)
|
||||
|
||||
draft_event = SingleEventPage(
|
||||
title="Lunar event",
|
||||
location="the moon",
|
||||
audience="public",
|
||||
cost="free",
|
||||
date_from="2001-01-01",
|
||||
latest_revision_created_at=local_datetime(2016, 1, 1),
|
||||
live=False,
|
||||
)
|
||||
root_page.add_child(instance=draft_event)
|
||||
|
||||
response = self.get({"q": "Lunar", "ordering": "live"})
|
||||
page_ids = [page.id for page in response.context["pages"]]
|
||||
self.assertEqual(page_ids, [draft_event.id, live_event.id])
|
||||
|
||||
response = self.get({"q": "Lunar", "ordering": "-live"})
|
||||
page_ids = [page.id for page in response.context["pages"]]
|
||||
self.assertEqual(page_ids, [live_event.id, draft_event.id])
|
||||
|
||||
def test_search_filter_content_type(self):
|
||||
# Correct content_type
|
||||
response = self.get({"content_type": "demosite.standardpage"})
|
||||
self.assertEqual(response.status_code, 200)
|
||||
|
||||
# Incorrect content_type
|
||||
response = self.get({"content_type": "demosite.standardpage.error"})
|
||||
self.assertEqual(response.status_code, 404)
|
||||
|
||||
def test_empty_search_renders_content_type_facets(self):
|
||||
root_page = Page.objects.get(id=2)
|
||||
event_index = EventIndex(
|
||||
title="ALL THE EVENTS",
|
||||
intro="It's just a nod to the canon",
|
||||
)
|
||||
root_page.add_child(instance=event_index)
|
||||
|
||||
params = [{"q": ""}, {}]
|
||||
url = reverse("wagtailadmin_pages:search")
|
||||
for param in params:
|
||||
with self.subTest(param=param):
|
||||
response = self.get(param)
|
||||
self.assertEqual(response.status_code, 200)
|
||||
self.assertTemplateUsed(response, "wagtailadmin/pages/search.html")
|
||||
self.assertEqual(response.context["query_string"], "")
|
||||
|
||||
self.assertContains(response, "Page types")
|
||||
self.assertContains(response, "All (3)")
|
||||
# The test fixture contains the root page and the welcome page
|
||||
# with the base page type
|
||||
self.assertContains(response, "Page (2)")
|
||||
|
||||
self.assertContains(response, "ALL THE EVENTS")
|
||||
|
||||
self.assertContains(response, "Event index (1)")
|
||||
self.assertContains(
|
||||
response,
|
||||
f"{url}?q=&content_type=tests.eventindex",
|
||||
)
|
||||
|
||||
def test_empty_search_with_content_type_filter(self):
|
||||
root_page = Page.objects.get(id=2)
|
||||
event_index = EventIndex(
|
||||
title="ALL THE EVENTS",
|
||||
intro="It's just a nod to the canon",
|
||||
)
|
||||
new_event = SingleEventPage(
|
||||
title="Lunar event",
|
||||
location="the moon",
|
||||
audience="public",
|
||||
cost="free",
|
||||
date_from="2001-01-01",
|
||||
latest_revision_created_at=local_datetime(2016, 1, 1),
|
||||
)
|
||||
root_page.add_child(instance=event_index)
|
||||
root_page.add_child(instance=new_event)
|
||||
|
||||
params = [
|
||||
{"q": "", "content_type": "tests.singleeventpage"},
|
||||
{"content_type": "tests.singleeventpage"},
|
||||
]
|
||||
url = reverse("wagtailadmin_pages:search")
|
||||
for param in params:
|
||||
with self.subTest(param=param):
|
||||
response = self.get(param)
|
||||
self.assertEqual(response.status_code, 200)
|
||||
self.assertTemplateUsed(response, "wagtailadmin/pages/search.html")
|
||||
self.assertEqual(response.context["query_string"], "")
|
||||
|
||||
self.assertContains(response, "Page types")
|
||||
self.assertContains(response, "All (4)")
|
||||
# The test fixture contains the root page and the welcome page
|
||||
# with the base page type
|
||||
self.assertContains(response, "Page (2)")
|
||||
self.assertContains(response, "Single event page (1)")
|
||||
|
||||
self.assertContains(response, "Lunar event")
|
||||
self.assertNotContains(response, "ALL THE EVENTS")
|
||||
|
||||
self.assertContains(response, "Event index (1)")
|
||||
self.assertContains(
|
||||
response,
|
||||
f"{url}?q=&content_type=tests.eventindex",
|
||||
)
|
||||
122
env/lib/python3.10/site-packages/wagtail/admin/tests/pages/test_page_usage.py
vendored
Normal file
122
env/lib/python3.10/site-packages/wagtail/admin/tests/pages/test_page_usage.py
vendored
Normal file
@@ -0,0 +1,122 @@
|
||||
from django.test import TestCase
|
||||
from django.urls import reverse
|
||||
|
||||
from wagtail.models import Page
|
||||
from wagtail.test.testapp.models import (
|
||||
FormPageWithRedirect,
|
||||
PageChooserModel,
|
||||
SimplePage,
|
||||
)
|
||||
from wagtail.test.utils import WagtailTestUtils
|
||||
from wagtail.test.utils.template_tests import AdminTemplateTestUtils
|
||||
|
||||
|
||||
class TestPageUsage(AdminTemplateTestUtils, WagtailTestUtils, TestCase):
|
||||
# We don't show the "Home" breadcrumb item in page views
|
||||
base_breadcrumb_items = []
|
||||
|
||||
def setUp(self):
|
||||
self.user = self.login()
|
||||
self.root_page = Page.objects.get(id=2)
|
||||
|
||||
page = SimplePage(
|
||||
title="Hello world!",
|
||||
slug="hello-world",
|
||||
content="hello",
|
||||
)
|
||||
self.root_page.add_child(instance=page)
|
||||
page.save_revision().publish()
|
||||
self.page = SimplePage.objects.get(id=page.id)
|
||||
|
||||
def test_simple(self):
|
||||
usage_url = reverse("wagtailadmin_pages:usage", args=(self.page.id,))
|
||||
response = self.client.get(usage_url)
|
||||
|
||||
self.assertEqual(response.status_code, 200)
|
||||
self.assertTemplateUsed(response, "wagtailadmin/generic/listing.html")
|
||||
self.assertContains(response, "Usage")
|
||||
self.assertContains(response, "Hello world!")
|
||||
|
||||
items = [
|
||||
{
|
||||
"url": reverse("wagtailadmin_explore_root"),
|
||||
"label": "Root",
|
||||
},
|
||||
{
|
||||
"url": reverse("wagtailadmin_explore", args=(self.root_page.id,)),
|
||||
"label": "Welcome to your new Wagtail site!",
|
||||
},
|
||||
{
|
||||
"url": reverse("wagtailadmin_explore", args=(self.page.id,)),
|
||||
"label": "Hello world! (simple page)",
|
||||
},
|
||||
{
|
||||
"url": "",
|
||||
"label": "Usage",
|
||||
"sublabel": "Hello world! (simple page)",
|
||||
},
|
||||
]
|
||||
self.assertBreadcrumbsItemsRendered(items, response.content)
|
||||
|
||||
# There should be exactly one edit link, rendered as a header button
|
||||
edit_url = reverse("wagtailadmin_pages:edit", args=(self.page.id,))
|
||||
soup = self.get_soup(response.content)
|
||||
edit_links = soup.select(f"a[href='{edit_url}']")
|
||||
self.assertEqual(len(edit_links), 1)
|
||||
edit_link = edit_links[0]
|
||||
classes = edit_link.attrs.get("class")
|
||||
self.assertIn("w-header-button", classes)
|
||||
self.assertIn("button", classes)
|
||||
|
||||
def test_has_private_usage(self):
|
||||
PageChooserModel.objects.create(page=self.page)
|
||||
usage_url = reverse("wagtailadmin_pages:usage", args=(self.page.id,))
|
||||
response = self.client.get(usage_url)
|
||||
|
||||
self.assertEqual(response.status_code, 200)
|
||||
self.assertTemplateUsed(response, "wagtailadmin/generic/listing.html")
|
||||
self.assertContains(response, "Usage")
|
||||
self.assertContains(response, "Hello world!")
|
||||
|
||||
self.assertContains(response, "(Private page chooser model)")
|
||||
self.assertContains(response, "<td>Page chooser model</td>", html=True)
|
||||
|
||||
def test_has_editable_usage(self):
|
||||
form_page = FormPageWithRedirect(
|
||||
title="Contact us",
|
||||
slug="contact-us",
|
||||
to_address="to@email.com",
|
||||
from_address="from@email.com",
|
||||
subject="The subject",
|
||||
thank_you_redirect_page=self.page,
|
||||
)
|
||||
|
||||
form_page = self.root_page.add_child(instance=form_page)
|
||||
|
||||
usage_url = reverse("wagtailadmin_pages:usage", args=(self.page.id,))
|
||||
response = self.client.get(usage_url)
|
||||
|
||||
self.assertEqual(response.status_code, 200)
|
||||
self.assertTemplateUsed(response, "wagtailadmin/generic/listing.html")
|
||||
self.assertContains(response, "Usage")
|
||||
self.assertContains(response, "Hello world!")
|
||||
|
||||
self.assertContains(response, "Contact us")
|
||||
self.assertContains(
|
||||
response, reverse("wagtailadmin_pages:edit", args=(form_page.id,))
|
||||
)
|
||||
self.assertContains(response, "Thank you redirect page")
|
||||
self.assertContains(response, "<td>Form page with redirect</td>", html=True)
|
||||
|
||||
def test_pagination(self):
|
||||
for _ in range(50):
|
||||
PageChooserModel.objects.create(page=self.page)
|
||||
|
||||
usage_url = reverse("wagtailadmin_pages:usage", args=(self.page.id,))
|
||||
response = self.client.get(f"{usage_url}?p=2")
|
||||
|
||||
self.assertEqual(response.status_code, 200)
|
||||
self.assertTemplateUsed(response, "wagtailadmin/generic/listing.html")
|
||||
self.assertContains(response, "Page 2 of 3.")
|
||||
self.assertContains(response, f"{usage_url}?p=1")
|
||||
self.assertContains(response, f"{usage_url}?p=3")
|
||||
163
env/lib/python3.10/site-packages/wagtail/admin/tests/pages/test_parent_page_chooser_view.py
vendored
Normal file
163
env/lib/python3.10/site-packages/wagtail/admin/tests/pages/test_parent_page_chooser_view.py
vendored
Normal file
@@ -0,0 +1,163 @@
|
||||
from unittest import mock
|
||||
|
||||
from django.contrib.auth.models import Group, Permission
|
||||
from django.test import TestCase
|
||||
from django.urls import reverse
|
||||
|
||||
from wagtail.models import GroupPagePermission, Page
|
||||
from wagtail.test.testapp.models import BusinessIndex, EventIndex, EventPage, SimplePage
|
||||
from wagtail.test.utils import WagtailTestUtils
|
||||
from wagtail.test.utils.template_tests import AdminTemplateTestUtils
|
||||
|
||||
|
||||
class TestParentPageChooserView(AdminTemplateTestUtils, WagtailTestUtils, TestCase):
|
||||
fixtures = ["test.json"]
|
||||
|
||||
def setUp(self):
|
||||
super().setUp()
|
||||
self.user = self.login()
|
||||
self.view_url = reverse("event_pages:choose_parent")
|
||||
|
||||
def test_get_page_parent_chooser(self):
|
||||
response = self.client.get(self.view_url)
|
||||
self.assertEqual(response.status_code, 200)
|
||||
self.assertTemplateUsed(response, "wagtailadmin/pages/choose_parent.html")
|
||||
self.assertBreadcrumbsItemsRendered(
|
||||
[
|
||||
{"url": reverse("event_pages:index"), "label": "Event pages"},
|
||||
{"url": "", "label": "Choose parent", "sublabel": "Event page"},
|
||||
],
|
||||
response.content,
|
||||
)
|
||||
|
||||
def test_parent_chooser_redirect(self):
|
||||
parent_page = Page.objects.first()
|
||||
form_data = {
|
||||
"parent_page": parent_page.pk,
|
||||
}
|
||||
|
||||
response = self.client.post(self.view_url, form_data)
|
||||
self.assertRedirects(
|
||||
response,
|
||||
reverse(
|
||||
"wagtailadmin_pages:add", args=("tests", "eventpage", parent_page.pk)
|
||||
),
|
||||
)
|
||||
|
||||
# Test another parent to make sure everything is working as intended
|
||||
another_parent = parent_page.get_first_child()
|
||||
form_data["parent_page"] = another_parent.pk
|
||||
|
||||
response = self.client.post(self.view_url, form_data)
|
||||
self.assertRedirects(
|
||||
response,
|
||||
reverse(
|
||||
"wagtailadmin_pages:add", args=("tests", "eventpage", another_parent.pk)
|
||||
),
|
||||
)
|
||||
|
||||
def test_no_parent_selected(self):
|
||||
error_html = """<p class="error-message">This field is required.</p>"""
|
||||
|
||||
response = self.client.post(self.view_url)
|
||||
self.assertEqual(response.status_code, 200)
|
||||
self.assertContains(response, error_html, html=True)
|
||||
|
||||
def test_user_no_add_subpage_permission(self):
|
||||
parent_page = Page.objects.first()
|
||||
test_group = Group.objects.create(name="test_group")
|
||||
test_group.permissions.add(Permission.objects.get(codename="access_admin"))
|
||||
|
||||
page_with_add_permission = Page(title="Page not to be selected")
|
||||
page_with_no_permission = Page(title="Page to be selected")
|
||||
parent_page.add_child(instance=page_with_add_permission)
|
||||
parent_page.add_child(instance=page_with_no_permission)
|
||||
|
||||
GroupPagePermission.objects.create(
|
||||
group=test_group,
|
||||
page=page_with_add_permission,
|
||||
permission_type="add",
|
||||
)
|
||||
form_data = {
|
||||
"parent_page": page_with_no_permission.pk,
|
||||
}
|
||||
|
||||
self.user.is_superuser = False
|
||||
self.user.groups.add(test_group)
|
||||
self.user.save()
|
||||
|
||||
response = self.client.post(self.view_url, form_data)
|
||||
self.assertEqual(response.status_code, 200)
|
||||
self.assertContains(
|
||||
response,
|
||||
" You do not have permission to create a page under "%s". "
|
||||
% page_with_no_permission.get_admin_display_title(),
|
||||
)
|
||||
|
||||
form_data["parent_page"] = page_with_add_permission.pk
|
||||
response = self.client.post(self.view_url, form_data)
|
||||
self.assertRedirects(
|
||||
response,
|
||||
reverse(
|
||||
"wagtailadmin_pages:add",
|
||||
args=("tests", "eventpage", page_with_add_permission.pk),
|
||||
),
|
||||
)
|
||||
|
||||
def test_choosing_parent_with_unsupported_subpage_type(self):
|
||||
parent_page = Page.objects.first()
|
||||
page_with_limited_subtypes = BusinessIndex(title="EventPage unsupported")
|
||||
parent_page.add_child(instance=page_with_limited_subtypes)
|
||||
form_data = {
|
||||
"parent_page": page_with_limited_subtypes.pk,
|
||||
}
|
||||
|
||||
response = self.client.post(self.view_url, form_data)
|
||||
self.assertEqual(response.status_code, 200)
|
||||
self.assertContains(
|
||||
response,
|
||||
"You cannot create a page of type "Event page" under "%s"."
|
||||
% page_with_limited_subtypes.get_admin_display_title(),
|
||||
)
|
||||
|
||||
def test_skip_if_only_one_valid_parent(self):
|
||||
self.assertEqual(EventIndex.objects.count(), 1)
|
||||
|
||||
with mock.patch.object(EventPage, "allowed_parent_page_models") as mock_method:
|
||||
mock_method.return_value = [EventIndex]
|
||||
self.assertEqual(EventPage.allowed_parent_page_models(), [EventIndex])
|
||||
response = self.client.get(self.view_url)
|
||||
|
||||
self.assertRedirects(
|
||||
response,
|
||||
reverse(
|
||||
"wagtailadmin_pages:add",
|
||||
args=("tests", "eventpage", EventIndex.objects.first().pk),
|
||||
),
|
||||
)
|
||||
|
||||
def test_skip_if_user_only_has_permission_for_one_parent(self):
|
||||
test_group = Group.objects.create(name="test_group")
|
||||
test_group.permissions.add(Permission.objects.get(codename="access_admin"))
|
||||
|
||||
self.user.is_superuser = False
|
||||
self.user.groups.add(test_group)
|
||||
self.user.save()
|
||||
|
||||
# Only grant the user permission to add pages under one leaf page
|
||||
parent_page = SimplePage.objects.filter(numchild=0).first()
|
||||
GroupPagePermission.objects.create(
|
||||
group=test_group,
|
||||
page=parent_page,
|
||||
permission_type="add",
|
||||
)
|
||||
|
||||
# Should redirect to the add view with the only valid parent page
|
||||
response = self.client.get(self.view_url)
|
||||
self.assertRedirects(
|
||||
response,
|
||||
reverse(
|
||||
"wagtailadmin_pages:add",
|
||||
args=("tests", "eventpage", parent_page.pk),
|
||||
),
|
||||
)
|
||||
653
env/lib/python3.10/site-packages/wagtail/admin/tests/pages/test_preview.py
vendored
Normal file
653
env/lib/python3.10/site-packages/wagtail/admin/tests/pages/test_preview.py
vendored
Normal file
@@ -0,0 +1,653 @@
|
||||
import datetime
|
||||
from functools import wraps
|
||||
|
||||
from django.test import TestCase
|
||||
from django.urls import reverse
|
||||
from django.utils import timezone
|
||||
from freezegun import freeze_time
|
||||
|
||||
from wagtail.admin.views.pages.preview import PreviewOnEdit
|
||||
from wagtail.models import Page
|
||||
from wagtail.test.testapp.models import (
|
||||
EventCategory,
|
||||
MultiPreviewModesPage,
|
||||
SimplePage,
|
||||
StreamPage,
|
||||
)
|
||||
from wagtail.test.utils import WagtailTestUtils
|
||||
|
||||
|
||||
class TestIssue2599(WagtailTestUtils, TestCase):
|
||||
"""
|
||||
When previewing a page on creation, we need to assign it a path value consistent with its
|
||||
(future) position in the tree. The naive way of doing this is to give it an index number
|
||||
one more than numchild - however, index numbers are not reassigned on page deletion, so
|
||||
this can result in a path that collides with an existing page (which is invalid).
|
||||
"""
|
||||
|
||||
def test_issue_2599(self):
|
||||
homepage = Page.objects.get(id=2)
|
||||
|
||||
child1 = Page(title="child1")
|
||||
homepage.add_child(instance=child1)
|
||||
child2 = Page(title="child2")
|
||||
homepage.add_child(instance=child2)
|
||||
|
||||
child1.delete()
|
||||
|
||||
self.login()
|
||||
post_data = {
|
||||
"title": "New page!",
|
||||
"content": "Some content",
|
||||
"slug": "hello-world",
|
||||
"action-submit": "Submit",
|
||||
}
|
||||
preview_url = reverse(
|
||||
"wagtailadmin_pages:preview_on_add",
|
||||
args=("tests", "simplepage", homepage.id),
|
||||
)
|
||||
response = self.client.post(preview_url, post_data)
|
||||
|
||||
# Check the JSON response
|
||||
self.assertEqual(response.status_code, 200)
|
||||
self.assertJSONEqual(
|
||||
response.content.decode(),
|
||||
{"is_valid": True, "is_available": True},
|
||||
)
|
||||
|
||||
response = self.client.get(preview_url)
|
||||
|
||||
# Check the HTML response
|
||||
self.assertEqual(response.status_code, 200)
|
||||
self.assertTemplateUsed(response, "tests/simple_page.html")
|
||||
self.assertContains(response, "New page!")
|
||||
|
||||
# Check that the treebeard attributes were set correctly on the page object
|
||||
self.assertEqual(response.context["self"].depth, homepage.depth + 1)
|
||||
self.assertTrue(response.context["self"].path.startswith(homepage.path))
|
||||
self.assertEqual(response.context["self"].get_parent(), homepage)
|
||||
|
||||
|
||||
def clear_edit_handler(page_cls):
|
||||
def decorator(fn):
|
||||
@wraps(fn)
|
||||
def decorated(*args, **kwargs):
|
||||
# Clear any old panel definitions generated
|
||||
page_cls.get_edit_handler.cache_clear()
|
||||
try:
|
||||
fn(*args, **kwargs)
|
||||
finally:
|
||||
# Clear the bad panel definition generated just now
|
||||
page_cls.get_edit_handler.cache_clear()
|
||||
|
||||
return decorated
|
||||
|
||||
return decorator
|
||||
|
||||
|
||||
class TestPreview(WagtailTestUtils, TestCase):
|
||||
fixtures = ["test.json"]
|
||||
|
||||
def setUp(self):
|
||||
self.meetings_category = EventCategory.objects.create(name="Meetings")
|
||||
self.parties_category = EventCategory.objects.create(name="Parties")
|
||||
self.holidays_category = EventCategory.objects.create(name="Holidays")
|
||||
|
||||
self.home_page = Page.objects.get(url_path="/home/")
|
||||
self.event_page = Page.objects.get(url_path="/home/events/christmas/")
|
||||
|
||||
self.user = self.login()
|
||||
|
||||
self.post_data = {
|
||||
"title": "Beach party",
|
||||
"slug": "beach-party",
|
||||
"body": """{"entityMap": {},"blocks": [
|
||||
{"inlineStyleRanges": [], "text": "party on wayne", "depth": 0, "type": "unstyled", "key": "00000", "entityRanges": []}
|
||||
]}""",
|
||||
"date_from": "2017-08-01",
|
||||
"audience": "public",
|
||||
"location": "the beach",
|
||||
"cost": "six squid",
|
||||
"carousel_items-TOTAL_FORMS": 0,
|
||||
"carousel_items-INITIAL_FORMS": 0,
|
||||
"carousel_items-MIN_NUM_FORMS": 0,
|
||||
"carousel_items-MAX_NUM_FORMS": 0,
|
||||
"speakers-TOTAL_FORMS": 0,
|
||||
"speakers-INITIAL_FORMS": 0,
|
||||
"speakers-MIN_NUM_FORMS": 0,
|
||||
"speakers-MAX_NUM_FORMS": 0,
|
||||
"related_links-TOTAL_FORMS": 0,
|
||||
"related_links-INITIAL_FORMS": 0,
|
||||
"related_links-MIN_NUM_FORMS": 0,
|
||||
"related_links-MAX_NUM_FORMS": 0,
|
||||
"head_counts-TOTAL_FORMS": 0,
|
||||
"head_counts-INITIAL_FORMS": 0,
|
||||
"head_counts-MIN_NUM_FORMS": 0,
|
||||
"head_counts-MAX_NUM_FORMS": 0,
|
||||
"categories": [self.parties_category.id, self.holidays_category.id],
|
||||
"comments-TOTAL_FORMS": 0,
|
||||
"comments-INITIAL_FORMS": 0,
|
||||
"comments-MIN_NUM_FORMS": 0,
|
||||
"comments-MAX_NUM_FORMS": 1000,
|
||||
}
|
||||
|
||||
def test_preview_on_create_with_no_session_data(self):
|
||||
preview_url = reverse(
|
||||
"wagtailadmin_pages:preview_on_add",
|
||||
args=("tests", "eventpage", self.home_page.id),
|
||||
)
|
||||
|
||||
preview_session_key = "wagtail-preview-tests-eventpage-{}".format(
|
||||
self.home_page.id
|
||||
)
|
||||
self.assertNotIn(preview_session_key, self.client.session)
|
||||
|
||||
response = self.client.get(preview_url)
|
||||
|
||||
# The preview should be unavailable
|
||||
self.assertEqual(response.status_code, 200)
|
||||
self.assertTemplateUsed(response, "wagtailadmin/generic/preview_error.html")
|
||||
self.assertContains(
|
||||
response,
|
||||
"<title>Preview not available - Wagtail</title>",
|
||||
html=True,
|
||||
)
|
||||
self.assertContains(
|
||||
response,
|
||||
'<h1 class="preview-error__title">Preview not available</h1>',
|
||||
html=True,
|
||||
)
|
||||
|
||||
def test_preview_on_create_with_invalid_data(self):
|
||||
preview_url = reverse(
|
||||
"wagtailadmin_pages:preview_on_add",
|
||||
args=("tests", "eventpage", self.home_page.id),
|
||||
)
|
||||
|
||||
preview_session_key = "wagtail-preview-tests-eventpage-{}".format(
|
||||
self.home_page.id
|
||||
)
|
||||
self.assertNotIn(preview_session_key, self.client.session)
|
||||
|
||||
response = self.client.post(preview_url, {**self.post_data, "title": ""})
|
||||
|
||||
# Check the JSON response
|
||||
self.assertEqual(response.status_code, 200)
|
||||
self.assertJSONEqual(
|
||||
response.content.decode(),
|
||||
{"is_valid": False, "is_available": False},
|
||||
)
|
||||
|
||||
# The invalid data should not be saved in the session
|
||||
self.assertNotIn(preview_session_key, self.client.session)
|
||||
|
||||
response = self.client.get(preview_url)
|
||||
|
||||
# The preview should still be unavailable
|
||||
self.assertEqual(response.status_code, 200)
|
||||
self.assertTemplateUsed(response, "wagtailadmin/generic/preview_error.html")
|
||||
self.assertContains(
|
||||
response,
|
||||
"<title>Preview not available - Wagtail</title>",
|
||||
html=True,
|
||||
)
|
||||
self.assertContains(
|
||||
response,
|
||||
'<h1 class="preview-error__title">Preview not available</h1>',
|
||||
html=True,
|
||||
)
|
||||
|
||||
def test_preview_on_create_with_m2m_field(self):
|
||||
preview_url = reverse(
|
||||
"wagtailadmin_pages:preview_on_add",
|
||||
args=("tests", "eventpage", self.home_page.id),
|
||||
)
|
||||
response = self.client.post(preview_url, self.post_data)
|
||||
|
||||
# Check the JSON response
|
||||
self.assertEqual(response.status_code, 200)
|
||||
self.assertJSONEqual(
|
||||
response.content.decode(),
|
||||
{"is_valid": True, "is_available": True},
|
||||
)
|
||||
|
||||
# Check the user can refresh the preview
|
||||
preview_session_key = "wagtail-preview-tests-eventpage-{}".format(
|
||||
self.home_page.id
|
||||
)
|
||||
self.assertIn(preview_session_key, self.client.session)
|
||||
|
||||
response = self.client.get(preview_url)
|
||||
|
||||
# Check the HTML response
|
||||
self.assertEqual(response.status_code, 200)
|
||||
self.assertTemplateUsed(response, "tests/event_page.html")
|
||||
self.assertContains(response, "Beach party")
|
||||
self.assertContains(response, "<li>Parties</li>")
|
||||
self.assertContains(response, "<li>Holidays</li>")
|
||||
|
||||
def test_preview_on_edit_with_m2m_field(self):
|
||||
preview_url = reverse(
|
||||
"wagtailadmin_pages:preview_on_edit", args=(self.event_page.id,)
|
||||
)
|
||||
response = self.client.post(preview_url, self.post_data)
|
||||
|
||||
# Check the JSON response
|
||||
self.assertEqual(response.status_code, 200)
|
||||
self.assertJSONEqual(
|
||||
response.content.decode(),
|
||||
{"is_valid": True, "is_available": True},
|
||||
)
|
||||
|
||||
# Check the user can refresh the preview
|
||||
preview_session_key = f"wagtail-preview-{self.event_page.id}"
|
||||
self.assertIn(preview_session_key, self.client.session)
|
||||
|
||||
response = self.client.get(preview_url)
|
||||
|
||||
# Check the HTML response
|
||||
self.assertEqual(response.status_code, 200)
|
||||
self.assertTemplateUsed(response, "tests/event_page.html")
|
||||
self.assertContains(response, "Beach party")
|
||||
self.assertContains(response, "<li>Parties</li>")
|
||||
self.assertContains(response, "<li>Holidays</li>")
|
||||
|
||||
def test_preview_on_edit_with_valid_then_invalid_data(self):
|
||||
preview_url = reverse(
|
||||
"wagtailadmin_pages:preview_on_edit", args=(self.event_page.id,)
|
||||
)
|
||||
response = self.client.post(preview_url, self.post_data)
|
||||
|
||||
# Check the JSON response
|
||||
self.assertEqual(response.status_code, 200)
|
||||
self.assertJSONEqual(
|
||||
response.content.decode(),
|
||||
{"is_valid": True, "is_available": True},
|
||||
)
|
||||
|
||||
# Send an invalid update request
|
||||
response = self.client.post(preview_url, {**self.post_data, "title": ""})
|
||||
self.assertEqual(response.status_code, 200)
|
||||
self.assertJSONEqual(
|
||||
response.content.decode(),
|
||||
{"is_valid": False, "is_available": True},
|
||||
)
|
||||
|
||||
# Check the user can still see the preview with the last valid data
|
||||
preview_session_key = f"wagtail-preview-{self.event_page.id}"
|
||||
self.assertIn(preview_session_key, self.client.session)
|
||||
|
||||
response = self.client.get(preview_url)
|
||||
|
||||
# Check the HTML response
|
||||
self.assertEqual(response.status_code, 200)
|
||||
self.assertTemplateUsed(response, "tests/event_page.html")
|
||||
self.assertContains(response, "Beach party")
|
||||
self.assertContains(response, "<li>Parties</li>")
|
||||
self.assertContains(response, "<li>Holidays</li>")
|
||||
|
||||
def test_preview_on_edit_expiry(self):
|
||||
initial_datetime = timezone.now()
|
||||
expiry_datetime = initial_datetime + datetime.timedelta(
|
||||
seconds=PreviewOnEdit.preview_expiration_timeout + 1
|
||||
)
|
||||
|
||||
with freeze_time(initial_datetime) as frozen_datetime:
|
||||
preview_url = reverse(
|
||||
"wagtailadmin_pages:preview_on_edit", args=(self.event_page.id,)
|
||||
)
|
||||
response = self.client.post(preview_url, self.post_data)
|
||||
|
||||
# Check the JSON response
|
||||
self.assertEqual(response.status_code, 200)
|
||||
|
||||
response = self.client.get(preview_url)
|
||||
|
||||
# Check the HTML response
|
||||
self.assertEqual(response.status_code, 200)
|
||||
|
||||
frozen_datetime.move_to(expiry_datetime)
|
||||
|
||||
preview_url = reverse(
|
||||
"wagtailadmin_pages:preview_on_edit", args=(self.home_page.id,)
|
||||
)
|
||||
response = self.client.post(preview_url, self.post_data)
|
||||
self.assertEqual(response.status_code, 200)
|
||||
response = self.client.get(preview_url)
|
||||
self.assertEqual(response.status_code, 200)
|
||||
|
||||
def test_preview_on_create_clear_preview_data(self):
|
||||
preview_session_key = "wagtail-preview-tests-eventpage-{}".format(
|
||||
self.home_page.id
|
||||
)
|
||||
|
||||
# Set a fake preview session data for the page
|
||||
self.client.session[preview_session_key] = "test data"
|
||||
|
||||
preview_url = reverse(
|
||||
"wagtailadmin_pages:preview_on_add",
|
||||
args=("tests", "eventpage", self.home_page.id),
|
||||
)
|
||||
response = self.client.delete(preview_url)
|
||||
self.assertEqual(response.status_code, 200)
|
||||
self.assertJSONEqual(
|
||||
response.content.decode(),
|
||||
{"success": True},
|
||||
)
|
||||
|
||||
# The data should no longer exist in the session
|
||||
self.assertNotIn(preview_session_key, self.client.session)
|
||||
|
||||
response = self.client.get(preview_url)
|
||||
|
||||
# The preview should be unavailable
|
||||
self.assertEqual(response.status_code, 200)
|
||||
self.assertTemplateUsed(response, "wagtailadmin/generic/preview_error.html")
|
||||
self.assertContains(
|
||||
response,
|
||||
"<title>Preview not available - Wagtail</title>",
|
||||
html=True,
|
||||
)
|
||||
self.assertContains(
|
||||
response,
|
||||
'<h1 class="preview-error__title">Preview not available</h1>',
|
||||
html=True,
|
||||
)
|
||||
|
||||
def test_preview_on_edit_clear_preview_data(self):
|
||||
preview_session_key = f"wagtail-preview-{self.event_page.id}"
|
||||
|
||||
# Set a fake preview session data for the page
|
||||
self.client.session[preview_session_key] = "test data"
|
||||
|
||||
preview_url = reverse(
|
||||
"wagtailadmin_pages:preview_on_edit", args=(self.event_page.id,)
|
||||
)
|
||||
response = self.client.delete(preview_url)
|
||||
self.assertEqual(response.status_code, 200)
|
||||
self.assertJSONEqual(
|
||||
response.content.decode(),
|
||||
{"success": True},
|
||||
)
|
||||
|
||||
# The data should no longer exist in the session
|
||||
self.assertNotIn(preview_session_key, self.client.session)
|
||||
|
||||
response = self.client.get(preview_url)
|
||||
|
||||
# The preview should be unavailable
|
||||
self.assertEqual(response.status_code, 200)
|
||||
self.assertTemplateUsed(response, "wagtailadmin/generic/preview_error.html")
|
||||
self.assertContains(
|
||||
response,
|
||||
"<title>Preview not available - Wagtail</title>",
|
||||
html=True,
|
||||
)
|
||||
self.assertContains(
|
||||
response,
|
||||
'<h1 class="preview-error__title">Preview not available</h1>',
|
||||
html=True,
|
||||
)
|
||||
|
||||
def test_preview_modes(self):
|
||||
preview_url = reverse(
|
||||
"wagtailadmin_pages:preview_on_add",
|
||||
args=("tests", "multipreviewmodespage", self.home_page.id),
|
||||
)
|
||||
|
||||
response = self.client.post(preview_url, data={"title": "Test", "slug": "test"})
|
||||
self.assertEqual(response.status_code, 200)
|
||||
self.assertJSONEqual(
|
||||
response.content.decode(),
|
||||
{"is_valid": True, "is_available": True},
|
||||
)
|
||||
|
||||
cases = [
|
||||
("", "tests/simple_page_alt.html"),
|
||||
("?mode=original", "tests/simple_page.html"),
|
||||
("?mode=alt%231", "tests/simple_page_alt.html"),
|
||||
]
|
||||
|
||||
for params, template in cases:
|
||||
with self.subTest(params=params, template=template):
|
||||
response = self.client.get(preview_url + params)
|
||||
self.assertEqual(response.status_code, 200)
|
||||
self.assertTemplateUsed(response, template)
|
||||
|
||||
|
||||
class TestEnablePreview(WagtailTestUtils, TestCase):
|
||||
def setUp(self):
|
||||
self.root_page = Page.objects.get(id=2)
|
||||
self.user = self.login()
|
||||
|
||||
# SimplePage only has one preview mode
|
||||
self.single = SimplePage(title="Single preview mode", content="foo")
|
||||
# MultiPreviewModesPage has two preview modes
|
||||
self.multiple = MultiPreviewModesPage(title="Multiple preview modes")
|
||||
|
||||
self.root_page.add_child(instance=self.single)
|
||||
self.root_page.add_child(instance=self.multiple)
|
||||
|
||||
def get_url_on_add(self, name, page):
|
||||
model_name = type(page)._meta.model_name
|
||||
return reverse(
|
||||
f"wagtailadmin_pages:{name}",
|
||||
args=("tests", model_name, self.root_page.id),
|
||||
)
|
||||
|
||||
def get_url_on_edit(self, name, page):
|
||||
return reverse(f"wagtailadmin_pages:{name}", args=(page.id,))
|
||||
|
||||
def test_show_preview_panel_on_create_with_single_mode(self):
|
||||
create_url = self.get_url_on_add("add", self.single)
|
||||
preview_url = self.get_url_on_add("preview_on_add", self.single)
|
||||
new_tab_url = preview_url + "?mode="
|
||||
response = self.client.get(create_url)
|
||||
|
||||
self.assertEqual(response.status_code, 200)
|
||||
|
||||
# Should show the preview panel
|
||||
self.assertContains(response, 'data-side-panel="preview"')
|
||||
self.assertContains(response, 'data-action="%s"' % preview_url)
|
||||
|
||||
# Should have the preview side panel toggle button
|
||||
soup = self.get_soup(response.content)
|
||||
toggle_button = soup.find("button", {"data-side-panel-toggle": "preview"})
|
||||
self.assertIsNotNone(toggle_button)
|
||||
self.assertEqual("w-tooltip w-kbd", toggle_button["data-controller"])
|
||||
self.assertEqual("mod+p", toggle_button["data-w-kbd-key-value"])
|
||||
|
||||
# Should show the iframe
|
||||
self.assertContains(
|
||||
response,
|
||||
'<iframe id="preview-iframe" loading="lazy" title="Preview" class="preview-panel__iframe" data-preview-iframe aria-describedby="preview-panel-error-banner">',
|
||||
)
|
||||
|
||||
# Should show the new tab button with the default mode set
|
||||
self.assertContains(response, f'href="{new_tab_url}" target="_blank"')
|
||||
|
||||
# Should not show the preview mode selection
|
||||
self.assertNotContains(
|
||||
response,
|
||||
'<select id="id_preview_mode" name="preview_mode" class="preview-panel__mode-select" data-preview-mode-select>',
|
||||
)
|
||||
|
||||
def test_show_preview_panel_on_create_with_multiple_modes(self):
|
||||
create_url = self.get_url_on_add("add", self.multiple)
|
||||
preview_url = self.get_url_on_add("preview_on_add", self.multiple)
|
||||
new_tab_url = preview_url + "?mode=alt%231"
|
||||
response = self.client.get(create_url)
|
||||
|
||||
self.assertEqual(response.status_code, 200)
|
||||
|
||||
# Should show the preview panel
|
||||
self.assertContains(response, 'data-side-panel-toggle="preview"')
|
||||
self.assertContains(response, 'data-side-panel="preview"')
|
||||
self.assertContains(response, 'data-action="%s"' % preview_url)
|
||||
|
||||
# Should show the iframe
|
||||
self.assertContains(
|
||||
response,
|
||||
'<iframe id="preview-iframe" loading="lazy" title="Preview" class="preview-panel__iframe" data-preview-iframe aria-describedby="preview-panel-error-banner">',
|
||||
)
|
||||
|
||||
# Should show the new tab button with the default mode set and correctly quoted
|
||||
self.assertContains(response, f'href="{new_tab_url}" target="_blank"')
|
||||
|
||||
# should show the preview mode selection
|
||||
self.assertContains(
|
||||
response,
|
||||
'<select id="id_preview_mode" name="preview_mode" class="preview-panel__mode-select" data-preview-mode-select>',
|
||||
)
|
||||
self.assertContains(response, '<option value="original">Original</option>')
|
||||
|
||||
# Should respect the default_preview_mode
|
||||
self.assertContains(
|
||||
response, '<option value="alt#1" selected>Alternate</option>'
|
||||
)
|
||||
|
||||
def test_show_preview_panel_on_edit_with_single_mode(self):
|
||||
edit_url = self.get_url_on_edit("edit", self.single)
|
||||
preview_url = self.get_url_on_edit("preview_on_edit", self.single)
|
||||
new_tab_url = preview_url + "?mode="
|
||||
response = self.client.get(edit_url)
|
||||
|
||||
self.assertEqual(response.status_code, 200)
|
||||
|
||||
# Should show the preview panel
|
||||
self.assertContains(response, 'data-side-panel-toggle="preview"')
|
||||
self.assertContains(response, 'data-side-panel="preview"')
|
||||
self.assertContains(response, 'data-action="%s"' % preview_url)
|
||||
|
||||
# Should show the iframe
|
||||
self.assertContains(
|
||||
response,
|
||||
'<iframe id="preview-iframe" loading="lazy" title="Preview" class="preview-panel__iframe" data-preview-iframe aria-describedby="preview-panel-error-banner">',
|
||||
)
|
||||
|
||||
# Should show the new tab button with the default mode set
|
||||
self.assertContains(response, f'href="{new_tab_url}" target="_blank"')
|
||||
|
||||
# Should not show the preview mode selection
|
||||
self.assertNotContains(
|
||||
response,
|
||||
'<select id="id_preview_mode" name="preview_mode" class="preview-panel__mode-select" data-preview-mode-select>',
|
||||
)
|
||||
|
||||
def test_show_preview_panel_on_edit_with_multiple_modes(self):
|
||||
edit_url = self.get_url_on_edit("edit", self.multiple)
|
||||
preview_url = self.get_url_on_edit("preview_on_edit", self.multiple)
|
||||
new_tab_url = preview_url + "?mode=alt%231"
|
||||
response = self.client.get(edit_url)
|
||||
|
||||
self.assertEqual(response.status_code, 200)
|
||||
|
||||
# Should show the preview panel
|
||||
self.assertContains(response, 'data-side-panel-toggle="preview"')
|
||||
self.assertContains(response, 'data-side-panel="preview"')
|
||||
self.assertContains(response, 'data-action="%s"' % preview_url)
|
||||
|
||||
# Should show the iframe
|
||||
self.assertContains(
|
||||
response,
|
||||
'<iframe id="preview-iframe" loading="lazy" title="Preview" class="preview-panel__iframe" data-preview-iframe aria-describedby="preview-panel-error-banner">',
|
||||
)
|
||||
|
||||
# Should show the new tab button with the default mode set and correctly quoted
|
||||
self.assertContains(response, f'href="{new_tab_url}" target="_blank"')
|
||||
|
||||
# should show the preview mode selection
|
||||
self.assertContains(
|
||||
response,
|
||||
'<select id="id_preview_mode" name="preview_mode" class="preview-panel__mode-select" data-preview-mode-select>',
|
||||
)
|
||||
self.assertContains(response, '<option value="original">Original</option>')
|
||||
|
||||
# Should respect the default_preview_mode
|
||||
self.assertContains(
|
||||
response, '<option value="alt#1" selected>Alternate</option>'
|
||||
)
|
||||
|
||||
def test_show_preview_on_revisions_list(self):
|
||||
latest_revision = self.single.save_revision(log_action=True)
|
||||
history_url = self.get_url_on_edit("history", self.single)
|
||||
preview_url = reverse(
|
||||
"wagtailadmin_pages:revisions_view",
|
||||
args=(self.single.id, latest_revision.id),
|
||||
)
|
||||
|
||||
response = self.client.get(history_url)
|
||||
soup = self.get_soup(response.content)
|
||||
|
||||
preview_link = soup.find("a", {"href": preview_url})
|
||||
self.assertEqual(len(preview_link), 1)
|
||||
self.assertEqual("Preview", preview_link.text)
|
||||
|
||||
|
||||
class TestDisablePreviewButton(WagtailTestUtils, TestCase):
|
||||
"""
|
||||
Test that preview button can be disabled by setting preview_modes to an empty list
|
||||
"""
|
||||
|
||||
def setUp(self):
|
||||
# Find root page
|
||||
self.root_page = Page.objects.get(id=2)
|
||||
|
||||
# Login
|
||||
self.user = self.login()
|
||||
|
||||
def test_disable_preview_on_create(self):
|
||||
# StreamPage has preview_modes = []
|
||||
response = self.client.get(
|
||||
reverse(
|
||||
"wagtailadmin_pages:add",
|
||||
args=("tests", "streampage", self.root_page.id),
|
||||
)
|
||||
)
|
||||
self.assertEqual(response.status_code, 200)
|
||||
|
||||
preview_url = reverse(
|
||||
"wagtailadmin_pages:preview_on_add",
|
||||
args=("tests", "streampage", self.root_page.id),
|
||||
)
|
||||
self.assertNotContains(response, 'data-side-panel-toggle="preview"')
|
||||
self.assertNotContains(response, 'data-side-panel="preview"')
|
||||
self.assertNotContains(response, 'data-action="%s"' % preview_url)
|
||||
|
||||
def test_disable_preview_on_edit(self):
|
||||
stream_page = StreamPage(title="stream page", body=[("text", "hello")])
|
||||
self.root_page.add_child(instance=stream_page)
|
||||
|
||||
# StreamPage has preview_modes = []
|
||||
response = self.client.get(
|
||||
reverse("wagtailadmin_pages:edit", args=(stream_page.id,))
|
||||
)
|
||||
self.assertEqual(response.status_code, 200)
|
||||
|
||||
preview_url = reverse(
|
||||
"wagtailadmin_pages:preview_on_edit", args=(stream_page.id,)
|
||||
)
|
||||
self.assertNotContains(response, 'data-side-panel-toggle="preview"')
|
||||
self.assertNotContains(response, 'data-side-panel="preview"')
|
||||
self.assertNotContains(response, 'data-action="%s"' % preview_url)
|
||||
|
||||
def test_disable_preview_on_revisions_list(self):
|
||||
stream_page = StreamPage(title="stream page", body=[("text", "hello")])
|
||||
self.root_page.add_child(instance=stream_page)
|
||||
latest_revision = stream_page.save_revision(log_action=True)
|
||||
|
||||
# StreamPage has preview_modes = []
|
||||
response = self.client.get(
|
||||
reverse("wagtailadmin_pages:history", args=(stream_page.id,))
|
||||
)
|
||||
preview_url = reverse(
|
||||
"wagtailadmin_pages:revisions_view",
|
||||
args=(stream_page.id, latest_revision.id),
|
||||
)
|
||||
|
||||
self.assertNotContains(response, preview_url)
|
||||
|
||||
soup = self.get_soup(response.content)
|
||||
|
||||
preview_link = soup.find("a", {"href": preview_url})
|
||||
self.assertIsNone(preview_link)
|
||||
142
env/lib/python3.10/site-packages/wagtail/admin/tests/pages/test_reorder_page.py
vendored
Normal file
142
env/lib/python3.10/site-packages/wagtail/admin/tests/pages/test_reorder_page.py
vendored
Normal file
@@ -0,0 +1,142 @@
|
||||
from django.test import TestCase
|
||||
from django.urls import reverse
|
||||
|
||||
from wagtail.models import Page
|
||||
from wagtail.test.testapp.models import BusinessChild, BusinessIndex, SimplePage
|
||||
from wagtail.test.utils import WagtailTestUtils
|
||||
|
||||
|
||||
class TestPageReorder(WagtailTestUtils, TestCase):
|
||||
fixtures = ["test.json"]
|
||||
|
||||
def __init__(self, methodName: str = ...) -> None:
|
||||
super().__init__(methodName)
|
||||
|
||||
def setUp(self):
|
||||
# Find root page
|
||||
self.root_page = Page.objects.get(id=2)
|
||||
|
||||
# root
|
||||
# |- simple_index (SimplePage)
|
||||
# | |- simple_child_1 (SimplePage)
|
||||
# | |- simple_child_2 (SimplePage)
|
||||
# | |- simple_child_3 (SimplePage)
|
||||
|
||||
self.index_page = SimplePage(title="Simple", slug="simple", content="hello")
|
||||
self.root_page.add_child(instance=self.index_page)
|
||||
|
||||
self.child_1 = SimplePage(
|
||||
title="Child 1 of SimplePage", slug="child-1", content="hello"
|
||||
)
|
||||
self.index_page.add_child(instance=self.child_1)
|
||||
self.child_2 = SimplePage(
|
||||
title="Child 2 of SimplePage", slug="child-2", content="hello"
|
||||
)
|
||||
self.index_page.add_child(instance=self.child_2)
|
||||
self.child_3 = SimplePage(
|
||||
title="Child 3 of SimplePage", slug="child-3", content="hello"
|
||||
)
|
||||
self.index_page.add_child(instance=self.child_3)
|
||||
|
||||
# Login
|
||||
self.user = self.login()
|
||||
|
||||
def test_page_set_page_position_get_request_with_simple_page(self):
|
||||
"""
|
||||
Test that GET requests to set_page_position view don't alter the page order.
|
||||
"""
|
||||
response = self.client.get(
|
||||
reverse("wagtailadmin_pages:set_page_position", args=(self.child_1.id,))
|
||||
)
|
||||
self.assertEqual(response.status_code, 200)
|
||||
|
||||
# Ensure page order does not change:
|
||||
child_slugs = self.index_page.get_children().values_list("slug", flat=True)
|
||||
self.assertListEqual(list(child_slugs), ["child-1", "child-2", "child-3"])
|
||||
|
||||
def test_page_set_page_position_without_position_argument_moves_it_to_the_end(self):
|
||||
response = self.client.post(
|
||||
reverse("wagtailadmin_pages:set_page_position", args=(self.child_1.id,))
|
||||
)
|
||||
self.assertEqual(response.status_code, 200)
|
||||
|
||||
# check if child_1 is the last child page:
|
||||
child_slugs = self.index_page.get_children().values_list("slug", flat=True)
|
||||
self.assertListEqual(list(child_slugs), ["child-2", "child-3", "child-1"])
|
||||
|
||||
def test_page_move_page_position_up(self):
|
||||
"""Moves child 3 to the first position."""
|
||||
response = self.client.post(
|
||||
reverse("wagtailadmin_pages:set_page_position", args=(self.child_3.id,))
|
||||
+ "?position=0"
|
||||
)
|
||||
self.assertEqual(response.status_code, 200)
|
||||
# check if child_3 is the first child page:
|
||||
child_slugs = self.index_page.get_children().values_list("slug", flat=True)
|
||||
self.assertListEqual(list(child_slugs), ["child-3", "child-1", "child-2"])
|
||||
|
||||
def test_page_move_page_position_down(self):
|
||||
"""
|
||||
Moves child 3 to the first position."""
|
||||
response = self.client.post(
|
||||
reverse("wagtailadmin_pages:set_page_position", args=(self.child_1.id,))
|
||||
+ "?position=1"
|
||||
)
|
||||
self.assertEqual(response.status_code, 200)
|
||||
# check if child_1 is the second child page:
|
||||
child_slugs = self.index_page.get_children().values_list("slug", flat=True)
|
||||
self.assertListEqual(list(child_slugs), ["child-2", "child-1", "child-3"])
|
||||
|
||||
def test_page_move_page_position_to_the_same_position(self):
|
||||
"""
|
||||
Moves child 3 to the first position."""
|
||||
response = self.client.post(
|
||||
reverse("wagtailadmin_pages:set_page_position", args=(self.child_1.id,))
|
||||
+ "?position=0"
|
||||
)
|
||||
self.assertEqual(response.status_code, 200)
|
||||
# Ensure page order does not change:
|
||||
child_slugs = self.index_page.get_children().values_list("slug", flat=True)
|
||||
self.assertListEqual(list(child_slugs), ["child-1", "child-2", "child-3"])
|
||||
|
||||
def test_page_set_page_position_with_invalid_target_position(self):
|
||||
response = self.client.post(
|
||||
reverse("wagtailadmin_pages:set_page_position", args=(self.child_3.id,))
|
||||
+ "?position=99"
|
||||
)
|
||||
self.assertEqual(response.status_code, 200)
|
||||
|
||||
# Ensure page order does not change:
|
||||
child_slugs = self.index_page.get_children().values_list("slug", flat=True)
|
||||
self.assertListEqual(list(child_slugs), ["child-1", "child-2", "child-3"])
|
||||
|
||||
|
||||
class TestPageReorderWithParentPageRestrictions(TestPageReorder):
|
||||
"""
|
||||
This testCase is the same as the TestPageReorder class above, but with a different
|
||||
page type: BusinessChild has a parent_page_types restriction.
|
||||
This ensures that this restriction doesn't affect the ability to reorder pages.
|
||||
"""
|
||||
|
||||
def setUp(self):
|
||||
# Find root page
|
||||
self.root_page = Page.objects.get(id=2)
|
||||
|
||||
# root
|
||||
# |- index_page (BusinessIndex)
|
||||
# | |- child_1 (BusinessChild)
|
||||
# | |- child_2 (BusinessChild)
|
||||
# | |- child_3 (BusinessChild)
|
||||
|
||||
self.index_page = BusinessIndex(title="Simple", slug="simple")
|
||||
self.root_page.add_child(instance=self.index_page)
|
||||
|
||||
self.child_1 = BusinessChild(title="Child 1 of BusinessIndex", slug="child-1")
|
||||
self.index_page.add_child(instance=self.child_1)
|
||||
self.child_2 = BusinessChild(title="Child 2 of BusinessIndex", slug="child-2")
|
||||
self.index_page.add_child(instance=self.child_2)
|
||||
self.child_3 = BusinessChild(title="Child 3 of BusinessIndex", slug="child-3")
|
||||
self.index_page.add_child(instance=self.child_3)
|
||||
|
||||
# Login
|
||||
self.user = self.login()
|
||||
648
env/lib/python3.10/site-packages/wagtail/admin/tests/pages/test_revisions.py
vendored
Normal file
648
env/lib/python3.10/site-packages/wagtail/admin/tests/pages/test_revisions.py
vendored
Normal file
@@ -0,0 +1,648 @@
|
||||
from django.conf import settings
|
||||
from django.contrib.auth import get_user_model
|
||||
from django.contrib.auth.models import Group, Permission
|
||||
from django.test import TestCase
|
||||
from django.urls import reverse
|
||||
from freezegun import freeze_time
|
||||
|
||||
from wagtail.admin.staticfiles import versioned_static
|
||||
from wagtail.models import Page
|
||||
from wagtail.test.testapp.models import (
|
||||
DefaultStreamPage,
|
||||
EventPage,
|
||||
FormClassAdditionalFieldPage,
|
||||
SecretPage,
|
||||
)
|
||||
from wagtail.test.utils import WagtailTestUtils
|
||||
from wagtail.test.utils.timestamps import local_datetime
|
||||
|
||||
|
||||
class TestRevisions(WagtailTestUtils, TestCase):
|
||||
fixtures = ["test.json"]
|
||||
|
||||
def setUp(self):
|
||||
self.christmas_event = EventPage.objects.get(url_path="/home/events/christmas/")
|
||||
self.christmas_event.title = "Last Christmas"
|
||||
self.christmas_event.date_from = "2013-12-25"
|
||||
self.christmas_event.body = (
|
||||
"<p>Last Christmas I gave you my heart, "
|
||||
"but the very next day you gave it away</p>"
|
||||
)
|
||||
self.last_christmas_revision = self.christmas_event.save_revision()
|
||||
self.last_christmas_revision.created_at = local_datetime(2013, 12, 25)
|
||||
self.last_christmas_revision.save()
|
||||
|
||||
self.christmas_event.title = "This Christmas"
|
||||
self.christmas_event.date_from = "2014-12-25"
|
||||
self.christmas_event.body = (
|
||||
"<p>This year, to save me from tears, "
|
||||
"I'll give it to someone special</p>"
|
||||
)
|
||||
self.this_christmas_revision = self.christmas_event.save_revision()
|
||||
self.this_christmas_revision.created_at = local_datetime(2014, 12, 25)
|
||||
self.this_christmas_revision.save()
|
||||
|
||||
self.login()
|
||||
|
||||
def test_get_revisions_index(self):
|
||||
response = self.client.get(
|
||||
reverse(
|
||||
"wagtailadmin_pages:revisions_index", args=(self.christmas_event.id,)
|
||||
)
|
||||
)
|
||||
history_url = reverse(
|
||||
"wagtailadmin_pages:history", args=(self.christmas_event.id,)
|
||||
)
|
||||
self.assertRedirects(response, history_url)
|
||||
|
||||
def request_preview_revision(self):
|
||||
last_christmas_preview_url = reverse(
|
||||
"wagtailadmin_pages:revisions_view",
|
||||
args=(self.christmas_event.id, self.last_christmas_revision.id),
|
||||
)
|
||||
return self.client.get(last_christmas_preview_url)
|
||||
|
||||
def test_preview_revision(self):
|
||||
response = self.request_preview_revision()
|
||||
|
||||
self.assertEqual(response.status_code, 200)
|
||||
self.assertContains(response, "Last Christmas I gave you my heart")
|
||||
|
||||
# Should show edit link in the userbar
|
||||
# https://github.com/wagtail/wagtail/issues/10002
|
||||
self.assertContains(response, "Edit this page")
|
||||
self.assertContains(
|
||||
response,
|
||||
reverse("wagtailadmin_pages:edit", args=(self.christmas_event.id,)),
|
||||
)
|
||||
|
||||
def test_preview_revision_with_no_page_permissions_redirects_to_admin(self):
|
||||
admin_only_user = self.create_user(
|
||||
username="admin_only", email="admin_only@email.com", password="password"
|
||||
)
|
||||
admin_only_user.user_permissions.add(
|
||||
Permission.objects.get_by_natural_key(
|
||||
codename="access_admin", app_label="wagtailadmin", model="admin"
|
||||
)
|
||||
)
|
||||
|
||||
self.login(user=admin_only_user)
|
||||
response = self.request_preview_revision()
|
||||
|
||||
self.assertEqual(response.status_code, 302)
|
||||
self.assertEqual(response["Location"], reverse("wagtailadmin_home"))
|
||||
|
||||
def test_preview_revision_forbidden_without_permission(self):
|
||||
# Alter the editors group so it has no permissions for Christmas page.
|
||||
st_patricks = Page.objects.get(slug="saint-patrick")
|
||||
editors_group = Group.objects.get(name="Site-wide editors")
|
||||
editors_group.page_permissions.update(page_id=st_patricks.id)
|
||||
|
||||
editor = get_user_model().objects.get(email="siteeditor@example.com")
|
||||
|
||||
self.login(editor)
|
||||
response = self.request_preview_revision()
|
||||
|
||||
self.assertEqual(response.status_code, 302)
|
||||
|
||||
def test_revert_revision(self):
|
||||
last_christmas_preview_url = reverse(
|
||||
"wagtailadmin_pages:revisions_revert",
|
||||
args=(self.christmas_event.id, self.last_christmas_revision.id),
|
||||
)
|
||||
response = self.client.get(last_christmas_preview_url)
|
||||
self.assertEqual(response.status_code, 200)
|
||||
|
||||
self.assertContains(response, "Editing Event page")
|
||||
self.assertContains(response, "You are viewing a previous version of this page")
|
||||
|
||||
# Form should show the content of the revision, not the current draft
|
||||
self.assertContains(response, "Last Christmas I gave you my heart")
|
||||
|
||||
# Form should include a hidden 'revision' field
|
||||
revision_field = (
|
||||
"""<input type="hidden" name="revision" value="%d" />"""
|
||||
% self.last_christmas_revision.id
|
||||
)
|
||||
self.assertContains(response, revision_field)
|
||||
|
||||
# Buttons should be relabelled
|
||||
self.assertContains(response, "Replace current draft")
|
||||
self.assertContains(response, "Publish this version")
|
||||
|
||||
@freeze_time("2014-12-20 12:00:00")
|
||||
def test_scheduled_revision(self):
|
||||
if settings.USE_TZ:
|
||||
# 12:00 UTC
|
||||
self.christmas_event.go_live_at = "2014-12-26T12:00:00.000Z"
|
||||
else:
|
||||
# 12:00 in no specific timezone
|
||||
self.christmas_event.go_live_at = "2014-12-26T12:00:00"
|
||||
this_christmas_revision = self.christmas_event.save_revision(log_action=True)
|
||||
this_christmas_revision.publish(log_action=True)
|
||||
this_christmas_unschedule_url = reverse(
|
||||
"wagtailadmin_pages:revisions_unschedule",
|
||||
args=(self.christmas_event.id, this_christmas_revision.id),
|
||||
)
|
||||
response = self.client.get(
|
||||
reverse("wagtailadmin_pages:history", args=(self.christmas_event.id,))
|
||||
)
|
||||
self.assertEqual(response.status_code, 200)
|
||||
|
||||
if settings.USE_TZ:
|
||||
# the default timezone is "Asia/Tokyo", so we expect UTC +9
|
||||
expected_date_string = "Dec. 26, 2014, 9 p.m."
|
||||
else:
|
||||
expected_date_string = "Dec. 26, 2014, noon"
|
||||
|
||||
self.assertContains(
|
||||
response, f"Page scheduled for publishing at {expected_date_string}"
|
||||
)
|
||||
self.assertContains(response, this_christmas_unschedule_url)
|
||||
|
||||
|
||||
class TestStreamRevisions(WagtailTestUtils, TestCase):
|
||||
def setUp(self):
|
||||
self.root_page = Page.objects.get(id=2)
|
||||
|
||||
self.test_page = DefaultStreamPage(
|
||||
title="A DefaultStreamPage",
|
||||
slug="a-defaultstreampage",
|
||||
)
|
||||
self.root_page.add_child(instance=self.test_page)
|
||||
|
||||
self.test_page.title = "An Updated DefaultStreamPage"
|
||||
self.first_revision = self.test_page.save_revision()
|
||||
self.first_revision.created_at = local_datetime(2022, 5, 10)
|
||||
self.first_revision.save()
|
||||
|
||||
self.login()
|
||||
|
||||
def test_revert_revision(self):
|
||||
test_page_revert_url = reverse(
|
||||
"wagtailadmin_pages:revisions_revert",
|
||||
args=(self.test_page.id, self.first_revision.id),
|
||||
)
|
||||
response = self.client.get(test_page_revert_url)
|
||||
self.assertEqual(response.status_code, 200)
|
||||
|
||||
html = response.content.decode()
|
||||
blocks_js = versioned_static("wagtailadmin/js/telepath/blocks.js")
|
||||
streamfield_css = versioned_static("wagtailadmin/css/panels/streamfield.css")
|
||||
|
||||
# The media files for StreamField should be included in the HTML
|
||||
self.assertTagInHTML(f'<script src="{blocks_js}"></script>', html)
|
||||
self.assertTagInHTML(
|
||||
f'<link href="{streamfield_css}" media="all" rel="stylesheet">',
|
||||
html,
|
||||
allow_extra_attrs=True, # Django 4.1 removes the type="text/css" attribute
|
||||
)
|
||||
|
||||
|
||||
class TestCompareRevisions(WagtailTestUtils, TestCase):
|
||||
# Actual tests for the comparison classes can be found in test_compare.py
|
||||
|
||||
fixtures = ["test.json"]
|
||||
|
||||
def setUp(self):
|
||||
self.christmas_event = EventPage.objects.get(url_path="/home/events/christmas/")
|
||||
self.christmas_event.title = "Last Christmas"
|
||||
self.christmas_event.date_from = "2013-12-25"
|
||||
self.christmas_event.body = (
|
||||
"<p>Last Christmas I gave you my heart, "
|
||||
"but the very next day you gave it away</p>"
|
||||
)
|
||||
self.last_christmas_revision = self.christmas_event.save_revision()
|
||||
self.last_christmas_revision.created_at = local_datetime(2013, 12, 25)
|
||||
self.last_christmas_revision.save()
|
||||
|
||||
self.christmas_event.title = "This Christmas"
|
||||
self.christmas_event.date_from = "2014-12-25"
|
||||
self.christmas_event.body = (
|
||||
"<p>This year, to save me from tears, "
|
||||
"I'll give it to someone special</p>"
|
||||
)
|
||||
self.this_christmas_revision = self.christmas_event.save_revision()
|
||||
self.this_christmas_revision.created_at = local_datetime(2014, 12, 25)
|
||||
self.this_christmas_revision.save()
|
||||
|
||||
self.login()
|
||||
|
||||
def test_compare_revisions(self):
|
||||
compare_url = reverse(
|
||||
"wagtailadmin_pages:revisions_compare",
|
||||
args=(
|
||||
self.christmas_event.id,
|
||||
self.last_christmas_revision.id,
|
||||
self.this_christmas_revision.id,
|
||||
),
|
||||
)
|
||||
response = self.client.get(compare_url)
|
||||
self.assertEqual(response.status_code, 200)
|
||||
|
||||
self.assertContains(
|
||||
response,
|
||||
'<span class="deletion">Last Christmas I gave you my heart, but the very next day you gave it away</span><span class="addition">This year, to save me from tears, I'll give it to someone special</span>',
|
||||
html=True,
|
||||
)
|
||||
|
||||
def test_compare_revisions_earliest(self):
|
||||
compare_url = reverse(
|
||||
"wagtailadmin_pages:revisions_compare",
|
||||
args=(self.christmas_event.id, "earliest", self.this_christmas_revision.id),
|
||||
)
|
||||
response = self.client.get(compare_url)
|
||||
self.assertEqual(response.status_code, 200)
|
||||
|
||||
self.assertContains(
|
||||
response,
|
||||
'<span class="deletion">Last Christmas I gave you my heart, but the very next day you gave it away</span><span class="addition">This year, to save me from tears, I'll give it to someone special</span>',
|
||||
html=True,
|
||||
)
|
||||
|
||||
def test_compare_revisions_latest(self):
|
||||
compare_url = reverse(
|
||||
"wagtailadmin_pages:revisions_compare",
|
||||
args=(self.christmas_event.id, self.last_christmas_revision.id, "latest"),
|
||||
)
|
||||
response = self.client.get(compare_url)
|
||||
self.assertEqual(response.status_code, 200)
|
||||
|
||||
self.assertContains(
|
||||
response,
|
||||
'<span class="deletion">Last Christmas I gave you my heart, but the very next day you gave it away</span><span class="addition">This year, to save me from tears, I'll give it to someone special</span>',
|
||||
html=True,
|
||||
)
|
||||
|
||||
def test_compare_revisions_live(self):
|
||||
# Mess with the live version, bypassing revisions
|
||||
self.christmas_event.body = (
|
||||
"<p>This year, to save me from tears, " "I'll just feed it to the dog</p>"
|
||||
)
|
||||
self.christmas_event.save(update_fields=["body"])
|
||||
|
||||
compare_url = reverse(
|
||||
"wagtailadmin_pages:revisions_compare",
|
||||
args=(self.christmas_event.id, self.last_christmas_revision.id, "live"),
|
||||
)
|
||||
response = self.client.get(compare_url)
|
||||
self.assertEqual(response.status_code, 200)
|
||||
|
||||
self.assertContains(
|
||||
response,
|
||||
'<span class="deletion">Last Christmas I gave you my heart, but the very next day you gave it away</span><span class="addition">This year, to save me from tears, I'll just feed it to the dog</span>',
|
||||
html=True,
|
||||
)
|
||||
|
||||
|
||||
class TestCompareRevisionsWithPerUserEditHandlers(WagtailTestUtils, TestCase):
|
||||
fixtures = ["test.json"]
|
||||
|
||||
def setUp(self):
|
||||
self.home = Page.objects.get(url_path="/home/")
|
||||
self.secret_page = SecretPage(
|
||||
title="Secret page",
|
||||
boring_data="InnocentCorp is the leading supplier of door hinges",
|
||||
secret_data="for flying saucers",
|
||||
)
|
||||
self.home.add_child(instance=self.secret_page)
|
||||
self.old_revision = self.secret_page.save_revision()
|
||||
self.secret_page.boring_data = (
|
||||
"InnocentCorp is the leading supplier of rubber sprockets"
|
||||
)
|
||||
self.secret_page.secret_data = "for fake moon landings"
|
||||
self.new_revision = self.secret_page.save_revision()
|
||||
self.compare_url = reverse(
|
||||
"wagtailadmin_pages:revisions_compare",
|
||||
args=(self.secret_page.id, self.old_revision.id, self.new_revision.id),
|
||||
)
|
||||
|
||||
def test_comparison_as_superuser(self):
|
||||
self.login()
|
||||
response = self.client.get(self.compare_url)
|
||||
self.assertEqual(response.status_code, 200)
|
||||
|
||||
self.assertContains(
|
||||
response,
|
||||
'InnocentCorp is the leading supplier of <span class="deletion">door hinges</span><span class="addition">rubber sprockets</span>',
|
||||
html=True,
|
||||
)
|
||||
self.assertContains(
|
||||
response,
|
||||
'for <span class="deletion">flying saucers</span><span class="addition">fake moon landings</span>',
|
||||
html=True,
|
||||
)
|
||||
|
||||
def test_comparison_as_ordinary_user(self):
|
||||
user = self.create_user(username="editor", password="password")
|
||||
user.groups.add(Group.objects.get(name="Site-wide editors"))
|
||||
self.login(username="editor", password="password")
|
||||
|
||||
response = self.client.get(self.compare_url)
|
||||
self.assertEqual(response.status_code, 200)
|
||||
|
||||
self.assertContains(
|
||||
response,
|
||||
'InnocentCorp is the leading supplier of <span class="deletion">door hinges</span><span class="addition">rubber sprockets</span>',
|
||||
html=True,
|
||||
)
|
||||
self.assertNotContains(
|
||||
response,
|
||||
"moon landings",
|
||||
)
|
||||
|
||||
|
||||
class TestCompareRevisionsWithNonModelField(WagtailTestUtils, TestCase):
|
||||
"""
|
||||
Tests if form fields defined in the base_form_class will not be included.
|
||||
in revisions view as they are not actually on the model.
|
||||
Flagged in issue #3737
|
||||
Note: Actual tests for comparison classes can be found in test_compare.py
|
||||
"""
|
||||
|
||||
fixtures = ["test.json"]
|
||||
# FormClassAdditionalFieldPage
|
||||
|
||||
def setUp(self):
|
||||
# Find root page
|
||||
self.root_page = Page.objects.get(id=2)
|
||||
|
||||
# Add child page of class with base_form_class override
|
||||
# non model field is 'code'
|
||||
self.test_page = FormClassAdditionalFieldPage(
|
||||
title="A Statement",
|
||||
slug="a-statement",
|
||||
location="Early Morning Cafe, Mainland, NZ",
|
||||
body="<p>hello</p>",
|
||||
)
|
||||
self.root_page.add_child(instance=self.test_page)
|
||||
|
||||
# add new revision
|
||||
self.test_page.title = "Statement"
|
||||
self.test_page.location = "Victory Monument, Bangkok"
|
||||
self.test_page.body = "<p>I would like very much to go into the forrest.</p>"
|
||||
self.test_page_revision = self.test_page.save_revision()
|
||||
self.test_page_revision.created_at = local_datetime(2017, 10, 15)
|
||||
self.test_page_revision.save()
|
||||
|
||||
# add another new revision
|
||||
self.test_page.title = "True Statement"
|
||||
self.test_page.location = "Victory Monument, Bangkok"
|
||||
self.test_page.body = "<p>I would like very much to go into the forest.</p>"
|
||||
self.test_page_revision_new = self.test_page.save_revision()
|
||||
self.test_page_revision_new.created_at = local_datetime(2017, 10, 16)
|
||||
self.test_page_revision_new.save()
|
||||
|
||||
self.login()
|
||||
|
||||
def test_base_form_class_used(self):
|
||||
"""First ensure that the non-model field is appearing in edit."""
|
||||
edit_url = reverse(
|
||||
"wagtailadmin_pages:add",
|
||||
args=("tests", "formclassadditionalfieldpage", self.test_page.id),
|
||||
)
|
||||
response = self.client.get(edit_url)
|
||||
self.assertContains(
|
||||
response,
|
||||
'<input type="text" name="code" aria-describedby="panel-child-content-child-code-helptext" required id="id_code" maxlength="5" />',
|
||||
html=True,
|
||||
)
|
||||
|
||||
def test_compare_revisions(self):
|
||||
"""Confirm that the non-model field is not shown in revision."""
|
||||
compare_url = reverse(
|
||||
"wagtailadmin_pages:revisions_compare",
|
||||
args=(
|
||||
self.test_page.id,
|
||||
self.test_page_revision.id,
|
||||
self.test_page_revision_new.id,
|
||||
),
|
||||
)
|
||||
response = self.client.get(compare_url)
|
||||
self.assertContains(
|
||||
response,
|
||||
'<span class="deletion">forrest.</span><span class="addition">forest.</span>',
|
||||
)
|
||||
# should not contain the field defined in the formclass used
|
||||
self.assertNotContains(response, "<h2>Code:</h2>")
|
||||
|
||||
|
||||
class TestRevisionsUnschedule(WagtailTestUtils, TestCase):
|
||||
fixtures = ["test.json"]
|
||||
|
||||
def setUp(self):
|
||||
self.christmas_event = EventPage.objects.get(url_path="/home/events/christmas/")
|
||||
self.christmas_event.title = "Last Christmas"
|
||||
self.christmas_event.date_from = "2013-12-25"
|
||||
self.christmas_event.body = (
|
||||
"<p>Last Christmas I gave you my heart, "
|
||||
"but the very next day you gave it away</p>"
|
||||
)
|
||||
self.last_christmas_revision = self.christmas_event.save_revision()
|
||||
self.last_christmas_revision.created_at = local_datetime(2013, 12, 25)
|
||||
self.last_christmas_revision.save()
|
||||
self.last_christmas_revision.publish()
|
||||
|
||||
self.christmas_event.title = "This Christmas"
|
||||
self.christmas_event.date_from = "2014-12-25"
|
||||
self.christmas_event.body = (
|
||||
"<p>This year, to save me from tears, "
|
||||
"I'll give it to someone special</p>"
|
||||
)
|
||||
self.this_christmas_revision = self.christmas_event.save_revision()
|
||||
self.this_christmas_revision.created_at = local_datetime(2014, 12, 24)
|
||||
self.this_christmas_revision.save()
|
||||
|
||||
self.this_christmas_revision.approved_go_live_at = local_datetime(2014, 12, 25)
|
||||
self.this_christmas_revision.save()
|
||||
|
||||
self.user = self.login()
|
||||
|
||||
def test_unschedule_view(self):
|
||||
"""
|
||||
This tests that the unschedule view responds with a confirm page
|
||||
"""
|
||||
response = self.client.get(
|
||||
reverse(
|
||||
"wagtailadmin_pages:revisions_unschedule",
|
||||
args=(self.christmas_event.id, self.this_christmas_revision.id),
|
||||
)
|
||||
)
|
||||
self.assertEqual(response.status_code, 200)
|
||||
self.assertTemplateUsed(
|
||||
response, "wagtailadmin/shared/revisions/confirm_unschedule.html"
|
||||
)
|
||||
|
||||
def test_unschedule_view_invalid_page_id(self):
|
||||
"""
|
||||
This tests that the unschedule view returns an error if the page id is invalid
|
||||
"""
|
||||
# Get unschedule page
|
||||
response = self.client.get(
|
||||
reverse("wagtailadmin_pages:revisions_unschedule", args=(12345, 67894))
|
||||
)
|
||||
|
||||
# Check that the user received a 404 response
|
||||
self.assertEqual(response.status_code, 404)
|
||||
|
||||
def test_unschedule_view_invalid_revision_id(self):
|
||||
"""
|
||||
This tests that the unschedule view returns an error if the page id is invalid
|
||||
"""
|
||||
# Get unschedule page
|
||||
response = self.client.get(
|
||||
reverse(
|
||||
"wagtailadmin_pages:revisions_unschedule",
|
||||
args=(self.christmas_event.id, 67894),
|
||||
)
|
||||
)
|
||||
|
||||
# Check that the user received a 404 response
|
||||
self.assertEqual(response.status_code, 404)
|
||||
|
||||
def test_unschedule_view_bad_permissions(self):
|
||||
"""
|
||||
This tests that the unschedule view doesn't allow users without publish permissions
|
||||
"""
|
||||
# Remove privileges from user
|
||||
self.user.is_superuser = False
|
||||
self.user.user_permissions.add(
|
||||
Permission.objects.get(
|
||||
content_type__app_label="wagtailadmin", codename="access_admin"
|
||||
)
|
||||
)
|
||||
self.user.save()
|
||||
|
||||
# Get unschedule page
|
||||
response = self.client.get(
|
||||
reverse(
|
||||
"wagtailadmin_pages:revisions_unschedule",
|
||||
args=(self.christmas_event.id, self.this_christmas_revision.id),
|
||||
)
|
||||
)
|
||||
|
||||
# Check that the user received a 302 redirected response
|
||||
self.assertEqual(response.status_code, 302)
|
||||
|
||||
def test_unschedule_view_post(self):
|
||||
"""
|
||||
This posts to the unschedule view and checks that the revision was unscheduled
|
||||
"""
|
||||
|
||||
# Post to the unschedule page
|
||||
response = self.client.post(
|
||||
reverse(
|
||||
"wagtailadmin_pages:revisions_unschedule",
|
||||
args=(self.christmas_event.id, self.this_christmas_revision.id),
|
||||
)
|
||||
)
|
||||
|
||||
# Should be redirected to page history
|
||||
self.assertRedirects(
|
||||
response,
|
||||
reverse("wagtailadmin_pages:history", args=(self.christmas_event.id,)),
|
||||
)
|
||||
|
||||
# Check that the page has no approved_schedule
|
||||
self.assertFalse(
|
||||
EventPage.objects.get(id=self.christmas_event.id).approved_schedule
|
||||
)
|
||||
|
||||
# Check that the approved_go_live_at has been cleared from the revision
|
||||
self.assertIsNone(
|
||||
self.christmas_event.revisions.get(
|
||||
id=self.this_christmas_revision.id
|
||||
).approved_go_live_at
|
||||
)
|
||||
|
||||
def test_unschedule_view_post_with_next_url(self):
|
||||
"""
|
||||
This tests that the redirect response follows the "next" parameter
|
||||
"""
|
||||
|
||||
unschedule_url = reverse(
|
||||
"wagtailadmin_pages:revisions_unschedule",
|
||||
args=(self.christmas_event.id, self.this_christmas_revision.id),
|
||||
)
|
||||
edit_url = reverse("wagtailadmin_pages:edit", args=(self.christmas_event.id,))
|
||||
|
||||
# Post to the unschedule page
|
||||
response = self.client.post(f"{unschedule_url}?next={edit_url}")
|
||||
|
||||
# Should be redirected to edit page
|
||||
self.assertRedirects(response, edit_url)
|
||||
|
||||
# Check that the page has no approved_schedule
|
||||
self.assertFalse(
|
||||
EventPage.objects.get(id=self.christmas_event.id).approved_schedule
|
||||
)
|
||||
|
||||
# Check that the approved_go_live_at has been cleared from the revision
|
||||
self.assertIsNone(
|
||||
self.christmas_event.revisions.get(
|
||||
id=self.this_christmas_revision.id
|
||||
).approved_go_live_at
|
||||
)
|
||||
|
||||
|
||||
class TestRevisionsUnscheduleForUnpublishedPages(WagtailTestUtils, TestCase):
|
||||
fixtures = ["test.json"]
|
||||
|
||||
def setUp(self):
|
||||
self.unpublished_event = EventPage.objects.get(
|
||||
url_path="/home/events/tentative-unpublished-event/"
|
||||
)
|
||||
self.unpublished_event.title = "Unpublished Page"
|
||||
self.unpublished_event.date_from = "2014-12-25"
|
||||
self.unpublished_event.body = "<p>Some Content</p>"
|
||||
self.unpublished_revision = self.unpublished_event.save_revision()
|
||||
self.unpublished_revision.created_at = local_datetime(2014, 12, 25)
|
||||
self.unpublished_revision.save()
|
||||
|
||||
self.user = self.login()
|
||||
|
||||
def test_unschedule_view(self):
|
||||
"""
|
||||
This tests that the unschedule view responds with a confirm page
|
||||
"""
|
||||
response = self.client.get(
|
||||
reverse(
|
||||
"wagtailadmin_pages:revisions_unschedule",
|
||||
args=(self.unpublished_event.id, self.unpublished_revision.id),
|
||||
)
|
||||
)
|
||||
self.assertEqual(response.status_code, 200)
|
||||
self.assertTemplateUsed(
|
||||
response, "wagtailadmin/shared/revisions/confirm_unschedule.html"
|
||||
)
|
||||
|
||||
def test_unschedule_view_post(self):
|
||||
"""
|
||||
This posts to the unschedule view and checks that the revision was unscheduled
|
||||
"""
|
||||
|
||||
# Post to the unschedule page
|
||||
response = self.client.post(
|
||||
reverse(
|
||||
"wagtailadmin_pages:revisions_unschedule",
|
||||
args=(self.unpublished_event.id, self.unpublished_revision.id),
|
||||
)
|
||||
)
|
||||
|
||||
# Should be redirected to page history
|
||||
self.assertRedirects(
|
||||
response,
|
||||
reverse("wagtailadmin_pages:history", args=(self.unpublished_event.id,)),
|
||||
)
|
||||
|
||||
# Check that the page has no approved_schedule
|
||||
self.assertFalse(
|
||||
EventPage.objects.get(id=self.unpublished_event.id).approved_schedule
|
||||
)
|
||||
|
||||
# Check that the approved_go_live_at has been cleared from the revision
|
||||
self.assertIsNone(
|
||||
self.unpublished_event.revisions.get(
|
||||
id=self.unpublished_revision.id
|
||||
).approved_go_live_at
|
||||
)
|
||||
264
env/lib/python3.10/site-packages/wagtail/admin/tests/pages/test_unpublish_page.py
vendored
Normal file
264
env/lib/python3.10/site-packages/wagtail/admin/tests/pages/test_unpublish_page.py
vendored
Normal file
@@ -0,0 +1,264 @@
|
||||
from unittest import mock
|
||||
|
||||
from django.contrib.auth.models import Permission
|
||||
from django.http import HttpRequest, HttpResponse
|
||||
from django.test import TestCase
|
||||
from django.urls import reverse
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
|
||||
from wagtail.models import Page
|
||||
from wagtail.signals import page_unpublished
|
||||
from wagtail.test.testapp.models import SimplePage
|
||||
from wagtail.test.utils import WagtailTestUtils
|
||||
|
||||
|
||||
class TestPageUnpublish(WagtailTestUtils, TestCase):
|
||||
def setUp(self):
|
||||
self.user = self.login()
|
||||
|
||||
# Create a page to unpublish
|
||||
self.root_page = Page.objects.get(id=2)
|
||||
self.page = SimplePage(
|
||||
title="Hello world!",
|
||||
slug="hello-world",
|
||||
content="hello",
|
||||
live=True,
|
||||
)
|
||||
self.root_page.add_child(instance=self.page)
|
||||
|
||||
def test_unpublish_view(self):
|
||||
"""
|
||||
This tests that the unpublish view responds with an unpublish confirm page
|
||||
"""
|
||||
# Get unpublish page
|
||||
response = self.client.get(
|
||||
reverse("wagtailadmin_pages:unpublish", args=(self.page.id,))
|
||||
)
|
||||
|
||||
# Check that the user received an unpublish confirm page
|
||||
self.assertEqual(response.status_code, 200)
|
||||
self.assertTemplateUsed(response, "wagtailadmin/pages/confirm_unpublish.html")
|
||||
|
||||
def test_unpublish_view_invalid_page_id(self):
|
||||
"""
|
||||
This tests that the unpublish view returns an error if the page id is invalid
|
||||
"""
|
||||
# Get unpublish page
|
||||
response = self.client.get(
|
||||
reverse("wagtailadmin_pages:unpublish", args=(12345,))
|
||||
)
|
||||
|
||||
# Check that the user received a 404 response
|
||||
self.assertEqual(response.status_code, 404)
|
||||
|
||||
def test_unpublish_view_bad_permissions(self):
|
||||
"""
|
||||
This tests that the unpublish view doesn't allow users without unpublish permissions
|
||||
"""
|
||||
# Remove privileges from user
|
||||
self.user.is_superuser = False
|
||||
self.user.user_permissions.add(
|
||||
Permission.objects.get(
|
||||
content_type__app_label="wagtailadmin", codename="access_admin"
|
||||
)
|
||||
)
|
||||
self.user.save()
|
||||
|
||||
# Get unpublish page
|
||||
response = self.client.get(
|
||||
reverse("wagtailadmin_pages:unpublish", args=(self.page.id,))
|
||||
)
|
||||
|
||||
# Check that the user received a 302 redirected response
|
||||
self.assertEqual(response.status_code, 302)
|
||||
|
||||
def test_unpublish_view_post(self):
|
||||
"""
|
||||
This posts to the unpublish view and checks that the page was unpublished
|
||||
"""
|
||||
# Connect a mock signal handler to page_unpublished signal
|
||||
mock_handler = mock.MagicMock()
|
||||
page_unpublished.connect(mock_handler)
|
||||
|
||||
try:
|
||||
# Post to the unpublish page
|
||||
response = self.client.post(
|
||||
reverse("wagtailadmin_pages:unpublish", args=(self.page.id,))
|
||||
)
|
||||
|
||||
# Should be redirected to explorer page
|
||||
self.assertRedirects(
|
||||
response, reverse("wagtailadmin_explore", args=(self.root_page.id,))
|
||||
)
|
||||
|
||||
# Check that the page was unpublished
|
||||
self.assertFalse(SimplePage.objects.get(id=self.page.id).live)
|
||||
|
||||
# Check that the page_unpublished signal was fired
|
||||
self.assertEqual(mock_handler.call_count, 1)
|
||||
mock_call = mock_handler.mock_calls[0][2]
|
||||
|
||||
self.assertEqual(mock_call["sender"], self.page.specific_class)
|
||||
self.assertEqual(mock_call["instance"], self.page)
|
||||
self.assertIsInstance(mock_call["instance"], self.page.specific_class)
|
||||
finally:
|
||||
page_unpublished.disconnect(mock_handler)
|
||||
|
||||
def test_after_unpublish_page(self):
|
||||
def hook_func(request, page):
|
||||
self.assertIsInstance(request, HttpRequest)
|
||||
self.assertEqual(page.id, self.page.id)
|
||||
|
||||
return HttpResponse("Overridden!")
|
||||
|
||||
with self.register_hook("after_unpublish_page", hook_func):
|
||||
post_data = {}
|
||||
response = self.client.post(
|
||||
reverse("wagtailadmin_pages:unpublish", args=(self.page.id,)), post_data
|
||||
)
|
||||
|
||||
self.assertEqual(response.status_code, 200)
|
||||
self.assertEqual(response.content, b"Overridden!")
|
||||
|
||||
self.page.refresh_from_db()
|
||||
self.assertEqual(self.page.status_string, _("draft"))
|
||||
|
||||
def test_before_unpublish_page(self):
|
||||
def hook_func(request, page):
|
||||
self.assertIsInstance(request, HttpRequest)
|
||||
self.assertEqual(page.id, self.page.id)
|
||||
|
||||
return HttpResponse("Overridden!")
|
||||
|
||||
with self.register_hook("before_unpublish_page", hook_func):
|
||||
post_data = {}
|
||||
response = self.client.post(
|
||||
reverse("wagtailadmin_pages:unpublish", args=(self.page.id,)), post_data
|
||||
)
|
||||
|
||||
self.assertEqual(response.status_code, 200)
|
||||
self.assertEqual(response.content, b"Overridden!")
|
||||
|
||||
# The hook response is served before unpublish is called.
|
||||
self.page.refresh_from_db()
|
||||
self.assertEqual(self.page.status_string, _("live"))
|
||||
|
||||
def test_unpublish_descendants_view(self):
|
||||
"""
|
||||
This tests that the unpublish view responds with an unpublish confirm page that does not contain the form field 'include_descendants'
|
||||
"""
|
||||
# Get unpublish page
|
||||
response = self.client.get(
|
||||
reverse("wagtailadmin_pages:unpublish", args=(self.page.id,))
|
||||
)
|
||||
|
||||
# Check that the user received an unpublish confirm page
|
||||
self.assertEqual(response.status_code, 200)
|
||||
self.assertTemplateUsed(response, "wagtailadmin/pages/confirm_unpublish.html")
|
||||
# Check the form does not contain the checkbox field include_descendants
|
||||
self.assertNotContains(
|
||||
response,
|
||||
'name="include_descendants"',
|
||||
)
|
||||
|
||||
|
||||
class TestPageUnpublishIncludingDescendants(WagtailTestUtils, TestCase):
|
||||
def setUp(self):
|
||||
self.user = self.login()
|
||||
# Find root page
|
||||
self.root_page = Page.objects.get(id=2)
|
||||
|
||||
# Create a page to unpublish
|
||||
self.test_page = self.root_page.add_child(
|
||||
instance=SimplePage(
|
||||
title="Hello world!",
|
||||
slug="hello-world",
|
||||
content="hello",
|
||||
live=True,
|
||||
has_unpublished_changes=False,
|
||||
)
|
||||
)
|
||||
|
||||
# Create a couple of child pages
|
||||
self.test_child_page = self.test_page.add_child(
|
||||
instance=SimplePage(
|
||||
title="Child page",
|
||||
slug="child-page",
|
||||
content="hello",
|
||||
live=True,
|
||||
has_unpublished_changes=True,
|
||||
)
|
||||
)
|
||||
|
||||
self.test_another_child_page = self.test_page.add_child(
|
||||
instance=SimplePage(
|
||||
title="Another Child page",
|
||||
slug="another-child-page",
|
||||
content="hello",
|
||||
live=True,
|
||||
has_unpublished_changes=True,
|
||||
)
|
||||
)
|
||||
|
||||
def test_unpublish_descendants_view(self):
|
||||
"""
|
||||
This tests that the unpublish view responds with an unpublish confirm page that contains the form field 'include_descendants'
|
||||
"""
|
||||
# Get unpublish page
|
||||
response = self.client.get(
|
||||
reverse("wagtailadmin_pages:unpublish", args=(self.test_page.id,))
|
||||
)
|
||||
|
||||
# Check that the user received an unpublish confirm page
|
||||
self.assertEqual(response.status_code, 200)
|
||||
self.assertTemplateUsed(response, "wagtailadmin/pages/confirm_unpublish.html")
|
||||
# Check the form contains the checkbox field include_descendants
|
||||
self.assertContains(
|
||||
response,
|
||||
'name="include_descendants"',
|
||||
)
|
||||
|
||||
def test_unpublish_include_children_view_post(self):
|
||||
"""
|
||||
This posts to the unpublish view and checks that the page and its descendants were unpublished
|
||||
"""
|
||||
# Post to the unpublish page
|
||||
response = self.client.post(
|
||||
reverse("wagtailadmin_pages:unpublish", args=(self.test_page.id,)),
|
||||
{"include_descendants": "on"},
|
||||
)
|
||||
|
||||
# Should be redirected to explorer page
|
||||
self.assertRedirects(
|
||||
response, reverse("wagtailadmin_explore", args=(self.root_page.id,))
|
||||
)
|
||||
|
||||
# Check that the page was unpublished
|
||||
self.assertFalse(SimplePage.objects.get(id=self.test_page.id).live)
|
||||
|
||||
# Check that the descendant pages were unpublished as well
|
||||
self.assertFalse(SimplePage.objects.get(id=self.test_child_page.id).live)
|
||||
self.assertFalse(
|
||||
SimplePage.objects.get(id=self.test_another_child_page.id).live
|
||||
)
|
||||
|
||||
def test_unpublish_not_include_children_view_post(self):
|
||||
"""
|
||||
This posts to the unpublish view and checks that the page was unpublished but its descendants were not
|
||||
"""
|
||||
# Post to the unpublish page
|
||||
response = self.client.post(
|
||||
reverse("wagtailadmin_pages:unpublish", args=(self.test_page.id,)), {}
|
||||
)
|
||||
|
||||
# Should be redirected to explorer page
|
||||
self.assertRedirects(
|
||||
response, reverse("wagtailadmin_explore", args=(self.root_page.id,))
|
||||
)
|
||||
|
||||
# Check that the page was unpublished
|
||||
self.assertFalse(SimplePage.objects.get(id=self.test_page.id).live)
|
||||
|
||||
# Check that the descendant pages were not unpublished
|
||||
self.assertTrue(SimplePage.objects.get(id=self.test_child_page.id).live)
|
||||
self.assertTrue(SimplePage.objects.get(id=self.test_another_child_page.id).live)
|
||||
114
env/lib/python3.10/site-packages/wagtail/admin/tests/pages/test_view_draft.py
vendored
Normal file
114
env/lib/python3.10/site-packages/wagtail/admin/tests/pages/test_view_draft.py
vendored
Normal file
@@ -0,0 +1,114 @@
|
||||
from django.contrib.auth import get_user_model
|
||||
from django.contrib.auth.models import Group, Permission
|
||||
from django.test import TestCase
|
||||
from django.urls import reverse
|
||||
|
||||
from wagtail.models import Page
|
||||
from wagtail.test.testapp.models import SimplePage, StreamPage
|
||||
from wagtail.test.utils import WagtailTestUtils
|
||||
|
||||
|
||||
class TestDraftAccess(WagtailTestUtils, TestCase):
|
||||
"""Tests for the draft view access restrictions."""
|
||||
|
||||
def setUp(self):
|
||||
# Find root page
|
||||
self.root_page = Page.objects.get(id=2)
|
||||
|
||||
# Add child page
|
||||
self.child_page = SimplePage(
|
||||
title="Hello world!",
|
||||
slug="hello-world",
|
||||
content="hello",
|
||||
)
|
||||
self.root_page.add_child(instance=self.child_page)
|
||||
|
||||
# Add stream page (which has empty preview_modes, and so doesn't allow viewing draft)
|
||||
self.stream_page = StreamPage(title="stream page", body=[("text", "hello")])
|
||||
self.root_page.add_child(instance=self.stream_page)
|
||||
|
||||
# create user with admin access (but not draft_view access)
|
||||
user = self.create_user(username="bob", password="password")
|
||||
user.user_permissions.add(
|
||||
Permission.objects.get(
|
||||
content_type__app_label="wagtailadmin", codename="access_admin"
|
||||
)
|
||||
)
|
||||
|
||||
def test_draft_access_admin(self):
|
||||
"""Test that admin can view draft."""
|
||||
# Login as admin
|
||||
self.user = self.login()
|
||||
|
||||
# Try getting page draft
|
||||
response = self.client.get(
|
||||
reverse("wagtailadmin_pages:view_draft", args=(self.child_page.id,))
|
||||
)
|
||||
|
||||
# User can view
|
||||
self.assertEqual(response.status_code, 200)
|
||||
|
||||
def test_page_without_preview_modes_is_unauthorised(self):
|
||||
# Login as admin
|
||||
self.user = self.login()
|
||||
|
||||
# Try getting page draft
|
||||
response = self.client.get(
|
||||
reverse("wagtailadmin_pages:view_draft", args=(self.stream_page.id,))
|
||||
)
|
||||
|
||||
# Unauthorised response (because this page type has previewing disabled)
|
||||
self.assertRedirects(response, "/admin/")
|
||||
|
||||
def test_draft_access_unauthorised(self):
|
||||
"""Test that user without edit/publish permission can't view draft."""
|
||||
self.login(username="bob", password="password")
|
||||
|
||||
# Try getting page draft
|
||||
response = self.client.get(
|
||||
reverse("wagtailadmin_pages:view_draft", args=(self.child_page.id,))
|
||||
)
|
||||
|
||||
# User gets redirected to the home page
|
||||
self.assertEqual(response.status_code, 302)
|
||||
|
||||
def test_draft_access_authorised(self):
|
||||
"""Test that user with edit permission can view draft."""
|
||||
# give user the permission to edit page
|
||||
user = get_user_model().objects.get(email="bob@example.com")
|
||||
user.groups.add(Group.objects.get(name="Moderators"))
|
||||
user.save()
|
||||
|
||||
self.login(username="bob", password="password")
|
||||
|
||||
# Get add subpage page
|
||||
response = self.client.get(
|
||||
reverse("wagtailadmin_pages:view_draft", args=(self.child_page.id,))
|
||||
)
|
||||
|
||||
# User can view
|
||||
self.assertEqual(response.status_code, 200)
|
||||
|
||||
def test_middleware_response_is_returned(self):
|
||||
"""
|
||||
If middleware returns a response while serving a page preview, that response should be
|
||||
returned back to the user
|
||||
"""
|
||||
self.login()
|
||||
response = self.client.get(
|
||||
reverse("wagtailadmin_pages:view_draft", args=(self.child_page.id,)),
|
||||
HTTP_USER_AGENT="EvilHacker",
|
||||
)
|
||||
self.assertEqual(response.status_code, 403)
|
||||
|
||||
def test_show_edit_link_in_userbar(self):
|
||||
self.login()
|
||||
response = self.client.get(
|
||||
reverse("wagtailadmin_pages:view_draft", args=(self.child_page.id,))
|
||||
)
|
||||
# Should show edit link in the userbar
|
||||
# https://github.com/wagtail/wagtail/issues/10002
|
||||
self.assertContains(response, "Edit this page")
|
||||
self.assertContains(
|
||||
response, reverse("wagtailadmin_pages:edit", args=(self.child_page.id,))
|
||||
)
|
||||
101
env/lib/python3.10/site-packages/wagtail/admin/tests/pages/test_workflow_history.py
vendored
Normal file
101
env/lib/python3.10/site-packages/wagtail/admin/tests/pages/test_workflow_history.py
vendored
Normal file
@@ -0,0 +1,101 @@
|
||||
from django.contrib.auth.models import Permission
|
||||
from django.test import TestCase
|
||||
from django.urls import reverse
|
||||
|
||||
from wagtail.models import Page
|
||||
from wagtail.test.utils import WagtailTestUtils
|
||||
|
||||
|
||||
class TestWorkflowHistoryDetail(WagtailTestUtils, TestCase):
|
||||
fixtures = ["test.json"]
|
||||
|
||||
def setUp(self):
|
||||
self.user = self.create_test_user()
|
||||
self.login(self.user)
|
||||
|
||||
self.christmas_event = Page.objects.get(
|
||||
url_path="/home/events/christmas/"
|
||||
).specific
|
||||
self.christmas_event.save_revision()
|
||||
|
||||
workflow = self.christmas_event.get_workflow()
|
||||
self.workflow_state = workflow.start(self.christmas_event, self.user)
|
||||
|
||||
def test_get_index(self):
|
||||
response = self.client.get(
|
||||
reverse(
|
||||
"wagtailadmin_pages:workflow_history", args=[self.christmas_event.id]
|
||||
)
|
||||
)
|
||||
self.assertEqual(response.status_code, 200)
|
||||
|
||||
self.assertContains(
|
||||
response, reverse("wagtailadmin_pages:edit", args=[self.christmas_event.id])
|
||||
)
|
||||
self.assertContains(
|
||||
response,
|
||||
reverse(
|
||||
"wagtailadmin_pages:workflow_history_detail",
|
||||
args=[self.christmas_event.id, self.workflow_state.id],
|
||||
),
|
||||
)
|
||||
|
||||
def test_get_index_with_bad_permissions(self):
|
||||
# Remove privileges from user
|
||||
self.user.is_superuser = False
|
||||
self.user.user_permissions.add(
|
||||
Permission.objects.get(
|
||||
content_type__app_label="wagtailadmin", codename="access_admin"
|
||||
)
|
||||
)
|
||||
self.user.save()
|
||||
|
||||
response = self.client.get(
|
||||
reverse(
|
||||
"wagtailadmin_pages:workflow_history", args=[self.christmas_event.id]
|
||||
)
|
||||
)
|
||||
|
||||
self.assertEqual(response.status_code, 302)
|
||||
|
||||
def test_get_detail(self):
|
||||
response = self.client.get(
|
||||
reverse(
|
||||
"wagtailadmin_pages:workflow_history_detail",
|
||||
args=[self.christmas_event.id, self.workflow_state.id],
|
||||
)
|
||||
)
|
||||
self.assertEqual(response.status_code, 200)
|
||||
|
||||
self.assertContains(
|
||||
response, reverse("wagtailadmin_pages:edit", args=[self.christmas_event.id])
|
||||
)
|
||||
self.assertContains(
|
||||
response,
|
||||
reverse(
|
||||
"wagtailadmin_pages:workflow_history", args=[self.christmas_event.id]
|
||||
),
|
||||
)
|
||||
|
||||
self.assertContains(response, '<div class="w-tabs" data-tabs>')
|
||||
|
||||
self.assertContains(response, '<div class="tab-content">')
|
||||
|
||||
def test_get_detail_with_bad_permissions(self):
|
||||
# Remove privileges from user
|
||||
self.user.is_superuser = False
|
||||
self.user.user_permissions.add(
|
||||
Permission.objects.get(
|
||||
content_type__app_label="wagtailadmin", codename="access_admin"
|
||||
)
|
||||
)
|
||||
self.user.save()
|
||||
|
||||
response = self.client.get(
|
||||
reverse(
|
||||
"wagtailadmin_pages:workflow_history_detail",
|
||||
args=[self.christmas_event.id, self.workflow_state.id],
|
||||
)
|
||||
)
|
||||
|
||||
self.assertEqual(response.status_code, 302)
|
||||
Reference in New Issue
Block a user