def test_expired_page_will_be_unpublished(self): # Connect a mock signal handler to page_unpublished signal signal_fired = [False] signal_page = [None] def page_unpublished_handler(sender, instance, **kwargs): signal_fired[0] = True signal_page[0] = instance page_unpublished.connect(page_unpublished_handler) page = SimplePage( title="Hello world!", slug="hello-world", content="hello", live=True, has_unpublished_changes=False, expire_at=timezone.now() - timedelta(days=1), ) self.root_page.add_child(instance=page) p = Page.objects.get(slug="hello-world") self.assertTrue(p.live) management.call_command("publish_scheduled_pages") p = Page.objects.get(slug="hello-world") self.assertFalse(p.live) self.assertTrue(p.has_unpublished_changes) self.assertTrue(p.expired) # Check that the page_published signal was fired self.assertTrue(signal_fired[0]) self.assertEqual(signal_page[0], page) self.assertEqual(signal_page[0], signal_page[0].specific)
def test_unpublish(self): # set up a listener for the unpublish signal unpublish_signals_fired = [] def page_unpublished_handler(sender, instance, **kwargs): unpublish_signals_fired.append((sender, instance)) page_unpublished.connect(page_unpublished_handler) events_index = Page.objects.get(url_path="/home/events/") events_index.get_children().unpublish() # Previously-live children of event index should now be non-live christmas = EventPage.objects.get(url_path="/home/events/christmas/") saint_patrick = SingleEventPage.objects.get( url_path="/home/events/saint-patrick/") unpublished_event = EventPage.objects.get( url_path="/home/events/tentative-unpublished-event/") self.assertFalse(christmas.live) self.assertFalse(saint_patrick.live) # Check that a signal was fired for each unpublished page self.assertIn((EventPage, christmas), unpublish_signals_fired) self.assertIn((SingleEventPage, saint_patrick), unpublish_signals_fired) # a signal should not be fired for pages that were in the queryset # but already unpublished self.assertNotIn((EventPage, unpublished_event), unpublish_signals_fired)
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) # 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)
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_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) # 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)
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) # 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()), "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)
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 register_signal_handlers(): # Get list of models that are page types Page = apps.get_model("wagtailcore", "Page") indexed_models = [ model for model in apps.get_models() if issubclass(model, Page) ] # Loop through list and register signal handlers for each one for model in indexed_models: page_published.connect(page_published_signal_handler, sender=model) page_unpublished.connect(page_unpublished_signal_handler, sender=model)
def register_signal_handlers(): Image = get_image_model() Document = get_document_model() for model in get_page_models(): page_published.connect(purge_page_from_cache, sender=model) page_unpublished.connect(purge_page_from_cache, sender=model) post_save.connect(purge_image_from_cache, sender=Image) post_delete.connect(purge_image_from_cache, sender=Image) post_save.connect(purge_document_from_cache, sender=Document) post_delete.connect(purge_document_from_cache, sender=Document)
def test_bulk_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(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()), "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)
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(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()), "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)