class TestPageDelete(TestCase, WagtailTestUtils): 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 response = 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) # 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()), "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) 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) # 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()), "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) 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.id)) def pre_delete_handler(sender, instance, **kwargs): pre_delete_signals_received.append((sender, instance.id)) def post_delete_handler(sender, instance, **kwargs): post_delete_signals_received.append((sender, instance.id)) page_unpublished.connect(page_unpublished_handler) pre_delete.connect(pre_delete_handler) post_delete.connect(post_delete_handler) # 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()), "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 ) 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())
class TestLocking(TestCase, WagtailTestUtils): 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 LockUnlockAction is present and passes a valid csrf token self.assertRegex( response.content.decode("utf-8"), r"LockUnlockAction\(\'\w+\'\, \'\/admin\/'\)", ) 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, )) }, ) # Check response self.assertRedirects( response, reverse("wagtailadmin_pages:edit", args=(self.child_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_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)
class TestPageSlugChangedSignal(TestCase, WagtailTestUtils): """ Tests for the `wagtail.signals.page_slug_changed` signal """ def setUp(self): # Find root page site = Site.objects.select_related("root_page").get(is_default_site=True) root_page = site.root_page # Create two sections self.section_a = SimplePage( title="Section A", slug="section-a", content="hello" ) root_page.add_child(instance=self.section_a) self.section_b = SimplePage( title="Section B", slug="section-b", content="hello" ) root_page.add_child(instance=self.section_b) # Add test page to section A self.test_page = SimplePage( title="Hello world! A", slug="hello-world-a", content="hello" ) self.section_a.add_child(instance=self.test_page) def test_signal_emitted_on_slug_change(self): # Connect a mock signal handler to the signal handler = mock.MagicMock() page_slug_changed.connect(handler) old_page = SimplePage.objects.get(id=self.test_page.id) try: self.test_page.slug = "updated" self.test_page.save() # TODO: When Django 3.1< support is dropped, wrap save in # self.captureOnCommitCallbacks and remove this code for _, func in connection.run_on_commit: func() finally: # Disconnect mock handler to prevent cross-test pollution page_slug_changed.disconnect(handler) # Check the signal was fired self.assertEqual(handler.call_count, 1) self.assertTrue( handler.called_with( sender=SimplePage, instance=self.test_page, instance_before=old_page, ) ) def test_signal_not_emitted_on_title_change(self): # Connect a mock signal handler to the signal handler = mock.MagicMock() page_slug_changed.connect(handler) try: self.test_page.title = "Goodnight Moon!" self.test_page.save() # NOTE: Even though we're not expecting anything to happen here, # we need to invoke the callbacks in run_on_commit the same way # the same way we do in ``test_signal_emitted_on_slug_change``, # otherwise this test wouldn't prove anything. for _, func in connection.run_on_commit: func() finally: # Disconnect mock handler to prevent cross-test pollution page_slug_changed.disconnect(handler) # Check the signal was NOT fired self.assertEqual(handler.call_count, 0) def test_signal_not_emitted_on_page_move(self): # Connect a mock signal handler to the signal handler = mock.MagicMock() page_slug_changed.connect(handler) try: self.test_page.move(self.section_b, pos="last-child") # NOTE: Even though we're not expecting anything to happen here, # we need to invoke the callbacks in run_on_commit the same way # the same way we do in ``test_signal_emitted_on_slug_change``, # otherwise this test wouldn't prove anything. for _, func in connection.run_on_commit: func() finally: # Disconnect mock handler to prevent cross-test pollution page_slug_changed.disconnect(handler) # Check the signal was NOT fired self.assertEqual(handler.call_count, 0)
class TestPageDelete(TestCase, WagtailTestUtils): 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()) 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) # 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()), "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) 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) # 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()), "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) 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.id)) def pre_delete_handler(sender, instance, **kwargs): pre_delete_signals_received.append((sender, instance.id)) def post_delete_handler(sender, instance, **kwargs): post_delete_signals_received.append((sender, instance.id)) page_unpublished.connect(page_unpublished_handler) pre_delete.connect(pre_delete_handler) post_delete.connect(post_delete_handler) # 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()), "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) 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())