def test_cant_move_pages_between_locales(self): user = get_user_model().objects.get(email="*****@*****.**") homepage = Page.objects.get(url_path="/home/").specific root = Page.objects.get(url_path="/").specific fr_locale = Locale.objects.create(language_code="fr") fr_page = root.add_child(instance=Page( title="French page", slug="french-page", locale=fr_locale, )) fr_homepage = root.add_child(instance=Page( title="French homepage", slug="french-homepage", locale=fr_locale, )) french_page_perms = fr_page.permissions_for_user(user) # fr_page can be moved into fr_homepage but not homepage self.assertFalse(french_page_perms.can_move_to(homepage)) self.assertTrue(french_page_perms.can_move_to(fr_homepage)) # All pages can be moved to the root, regardless what language they are self.assertTrue(french_page_perms.can_move_to(root)) events_index = Page.objects.get(url_path="/home/events/") events_index_perms = events_index.permissions_for_user(user) self.assertTrue(events_index_perms.can_move_to(root))
def _page_urls_for_sites(page: Page, sites: Tuple[Site], cache_target: Page) -> Set[Tuple[Site, str, str]]: urls = set() for site in sites: # use a `HttpRequest` to influence the return value request = get_dummy_request(site=site) # reuse cached site root paths if available if hasattr(cache_target, "_wagtail_cached_site_root_paths"): request._wagtail_cached_site_root_paths = ( cache_target._wagtail_cached_site_root_paths) url_parts = page.get_url_parts(request) if url_parts is None: continue site_id, root_url, page_path = url_parts if page_path: for route_path in page.get_route_paths(): normalized_route_path = Redirect.normalise_page_route_path( route_path) old_path = Redirect.normalise_path( page_path.rstrip("/") + (normalized_route_path or "/")) urls.add((site, old_path, normalized_route_path)) # copy cached site root paths to `cache_target` to retain benefits cache_target._wagtail_cached_site_root_paths = ( request._wagtail_cached_site_root_paths) return urls
def test_change_root_page_locale_on_locale_deletion(self): """ On deleting the locale used for the root page (but no 'real' pages), the root page should be reassigned to a new locale (the default one, if possible) """ # change 'real' pages first Page.objects.filter(depth__gt=1).update(locale=Locale.objects.get( language_code="fr")) self.assertEqual(Page.get_first_root_node().locale.language_code, "en") Locale.objects.get(language_code="en").delete() self.assertEqual(Page.get_first_root_node().locale.language_code, "fr")
def test_construct_queryset_hook(self): page = SimplePage(title="Test shown", content="hello") Page.get_first_root_node().add_child(instance=page) page_not_shown = SimplePage(title="Test not shown", content="hello") Page.get_first_root_node().add_child(instance=page_not_shown) def filter_pages(pages, request): return pages.filter(id=page.id) with self.register_hook("construct_page_chooser_queryset", filter_pages): response = self.get() self.assertEqual(len(response.context["pages"]), 1) self.assertEqual(response.context["pages"][0].specific, page)
def test_can_delete_default_locale_when_language_code_has_no_locale(self): Locale.objects.create(language_code="fr") self.assertTrue(Page.get_first_root_node().locale.language_code, "en") Page.objects.filter(depth__gt=1).delete() response = self.post() # Should redirect back to index self.assertRedirects(response, reverse("wagtaillocales:index")) # Check that the locale was deleted self.assertFalse(Locale.objects.filter(language_code="en").exists()) # root node's locale should now have been reassigned to 'fr' despite that not matching # LANGUAGE_CODE (because it's the only remaining Locale record) self.assertTrue(Page.get_first_root_node().locale.language_code, "fr")
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_submit_page_translation_view_test_post_multiple_locales(self): # Needs an extra page to hit recursive function en_blog_post_sub = Page(title="Blog post sub", slug="blog-post-sub") self.en_blog_post.add_child(instance=en_blog_post_sub) url = reverse("simple_translation:submit_page_translation", args=(self.en_blog_post.id, )) de = Locale.objects.get(language_code="de").id fr = Locale.objects.get(language_code="fr").id data = {"locales": [de, fr], "include_subtree": True} self.login() with self.assertRaisesMessage(ParentNotTranslatedError, ""): self.client.post(url, data) url = reverse("simple_translation:submit_page_translation", args=(self.en_blog_index.id, )) response = self.client.post(url, data) assert response.status_code == 302 assert response.url == f"/admin/pages/{self.en_blog_index.get_parent().id}/" response = self.client.get(response.url) # follow the redirect assert [msg.message for msg in response.context["messages"] ] == ["The page 'Blog' was successfully created in 2 locales"]
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_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 clean(self): cleaned_data = super().clean() if "slug" in self.cleaned_data: if not Page._slug_is_available(cleaned_data["slug"], self.parent_page, self.instance): self.add_error( "slug", forms.ValidationError(_("This slug is already in use"))) # Check scheduled publishing fields go_live_at = cleaned_data.get("go_live_at") expire_at = cleaned_data.get("expire_at") # Go live must be before expire if go_live_at and expire_at: if go_live_at > expire_at: msg = _("Go live date/time must be before expiry date/time") self.add_error("go_live_at", forms.ValidationError(msg)) self.add_error("expire_at", forms.ValidationError(msg)) # Expire at must be in the future if expire_at and expire_at < timezone.now(): self.add_error( "expire_at", forms.ValidationError( _("Expiry date/time must be in the future")), ) # Don't allow an existing first_published_at to be unset by clearing the field if ("first_published_at" in cleaned_data and not cleaned_data["first_published_at"]): del cleaned_data["first_published_at"] return cleaned_data
def test_not_translation_of(self): en_homepage = Page.objects.get(url_path="/home/") # Create a translation of the homepage fr_locale = Locale.objects.create(language_code="fr") root_page = Page.objects.get(depth=1) fr_homepage = root_page.add_child(instance=Page( title="French homepage", slug="home-fr", locale=fr_locale, translation_key=en_homepage.translation_key, )) with self.assertNumQueries(1): translations = list(Page.objects.not_translation_of(en_homepage)) # Check that every single page is in the queryset, except for fr_homepage for page in Page.objects.all(): if page in [fr_homepage]: self.assertNotIn(page, translations) else: self.assertIn(page, translations) # Test with inclusive with self.assertNumQueries(1): translations = list( Page.objects.not_translation_of(en_homepage, inclusive=True)) # Check that every single page is in the queryset, except for fr_homepage and en_homepage for page in Page.objects.all(): if page in [en_homepage, fr_homepage]: self.assertNotIn(page, translations) else: self.assertIn(page, translations)
def move_confirm(request, page_to_move_id, destination_id): page_to_move = get_object_or_404(Page, id=page_to_move_id).specific # Needs .specific_deferred because the .get_admin_display_title method is called in template destination = get_object_or_404(Page, id=destination_id).specific_deferred if not Page._slug_is_available( page_to_move.slug, destination, page=page_to_move): messages.error( request, _("The slug '{0}' is already in use at the selected parent page. Make sure the slug is unique and try again" ).format(page_to_move.slug), ) return redirect( "wagtailadmin_pages:move_choose_destination", page_to_move.id, destination.id, ) for fn in hooks.get_hooks("before_move_page"): result = fn(request, page_to_move, destination) if hasattr(result, "status_code"): return result if request.method == "POST": # any invalid moves *should* be caught by the permission check in the action class, # so don't bother to catch InvalidMoveToDescendant action = MovePageAction(page_to_move, destination, pos="last-child", user=request.user) action.execute() messages.success( request, _("Page '{0}' moved.").format( page_to_move.get_admin_display_title()), buttons=[ messages.button( reverse("wagtailadmin_pages:edit", args=(page_to_move.id, )), _("Edit"), ) ], ) for fn in hooks.get_hooks("after_move_page"): result = fn(request, page_to_move) if hasattr(result, "status_code"): return result return redirect("wagtailadmin_explore", destination.id) return TemplateResponse( request, "wagtailadmin/pages/confirm_move.html", { "page_to_move": page_to_move, "destination": destination, }, )
def setUp(self): self.root_page = Page.objects.get(depth=1) self.home_page = Page.objects.get(depth=2) self.second_home_page = self.root_page.add_child( instance=Page(title="Second homepage", slug="home-1") )
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 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 create_redirects(page: Page, page_old: Page, sites: Iterable[Site]) -> None: url_path_length = len(page.url_path) sites = tuple(sites) if not sites: return None logger.info(f"Creating redirects for page: '{page}' id={page.id}") # For bulk-creating redirects in batches batch = BatchRedirectCreator(max_size=2000, ignore_conflicts=True) # Treat the page that was updated / moved separately to it's decendants, # because there may be changes to fields other than `slug` or `url_path` # that impact the URL. old_urls = _page_urls_for_sites(page_old, sites, cache_target=page) new_urls = _page_urls_for_sites(page, sites, cache_target=page) # Add redirects for urls that have changed changed_urls = old_urls - new_urls for site, old_path, route_path in changed_urls: batch.add( old_path=old_path, site=site, redirect_page=page, redirect_page_route_path=route_path, automatically_created=True, ) # Now, repeat the process for each descendant page. # Only the `url_path` value of descendants should have been affected by the # change, so we can use in-memory manipulation of `url_path` to figure out what # the old URLS were for descendant in (page.get_descendants().live().defer_streamfields(). specific().iterator()): new_urls = _page_urls_for_sites(descendant, sites, cache_target=page) # Restore old 'url_path' value on in-memory instance descendant.url_path = page_old.url_path + descendant.url_path[ url_path_length:] old_urls = _page_urls_for_sites(descendant, sites, cache_target=page) # Add redirects for urls that have changed changed_urls = old_urls - new_urls for site, old_path, route_path in changed_urls: batch.add( old_path=old_path, site=site, redirect_page=descendant, redirect_page_route_path=route_path, automatically_created=True, ) # Process the final batch batch.process() logger.info(batch.get_summary())
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 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 get_actionable_objects(self): objects, objects_without_access = super().get_actionable_objects() request = self.request if objects: self.target_parent_models = set( objects[0].specific_class.allowed_parent_page_models()) for obj in objects: self.target_parent_models.intersection_update( set(obj.specific_class.allowed_parent_page_models())) self.pages_to_move = [page.id for page in objects] if self.cleaned_form is None: if len(self.target_parent_models) == 0: return [], { **objects_without_access, "pages_without_common_parent_page": [{ "item": page, "can_edit": page.permissions_for_user( self.request.user).can_edit(), } for page in objects], } return objects, objects_without_access destination = self.cleaned_form.cleaned_data["chooser"] pages = [] pages_without_destination_access = [] pages_with_duplicate_slugs = [] for page in objects: if not page.permissions_for_user( request.user).can_move_to(destination): pages_without_destination_access.append(page) elif not Page._slug_is_available(page.slug, destination, page=page): pages_with_duplicate_slugs.append(page) else: pages.append(page) return pages, { **objects_without_access, "pages_without_destination_access": [{ "item": page, "can_edit": page.permissions_for_user(self.request.user).can_edit(), } for page in pages_without_destination_access], "pages_with_duplicate_slugs": [{ "item": page, "can_edit": page.permissions_for_user(self.request.user).can_edit(), } for page in pages_with_duplicate_slugs], }
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 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_can_delete_default_locale(self): # The presence of the locale on the root page node (if that's the only thing using the # locale) should not prevent deleting it for lang in ("fr", "de", "pl", "ja"): Locale.objects.create(language_code=lang) self.assertTrue(Page.get_first_root_node().locale.language_code, "en") Page.objects.filter(depth__gt=1).delete() response = self.post() # Should redirect back to index self.assertRedirects(response, reverse("wagtaillocales:index")) # Check that the locale was deleted self.assertFalse(Locale.objects.filter(language_code="en").exists()) # root node's locale should now have been reassigned to the one matching the current # LANGUAGE_CODE self.assertTrue(Page.get_first_root_node().locale.language_code, "de")
def setUpClass(cls): super().setUpClass() cls.test_page = SimplePage(title="test", slug="test", content="test") cls.wagtail_root = Page.get_first_root_node() cls.wagtail_root.add_child(instance=cls.test_page) cls.test_page_group = Group.objects.create(name="Test page") GroupPagePermission.objects.create( group=cls.test_page_group, page=cls.test_page, permission_type="edit" )
def setUp(self): self.site_2_page = SimplePage( title="Site 2 page", slug="site_2_page", content="Hello", ) Page.get_first_root_node().add_child(instance=self.site_2_page) self.site_2_subpage = SimplePage( title="Site 2 subpage", slug="site_2_subpage", content="Hello again", ) self.site_2_page.add_child(instance=self.site_2_subpage) self.site_2 = Site.objects.create( hostname="example.com", port=8080, root_page=Page.objects.get(pk=self.site_2_page.pk), is_default_site=False, ) self.about_us_page = SimplePage.objects.get(url_path="/home/about-us/")
def autocreate_redirects_on_slug_change(instance_before: Page, instance: Page, **kwargs): # NB: `page_slug_changed` provides specific page instances, # so we do not need to 'upcast' them for create_redirects here if not getattr(settings, "WAGTAILREDIRECTS_AUTO_CREATE", True): return None # Determine sites to create redirects for sites = Site.objects.filter(id__in=[ option.site_id for option in instance._get_relevant_site_root_paths( cache_object=instance) ]).exclude(root_page=instance) create_redirects(page=instance, page_old=instance_before, sites=sites)
def setUp(self): root = Page.objects.first() other_home = Page(title="Other Root") root.add_child(instance=other_home) self.default_site = Site.objects.get(is_default_site=True) self.default_settings = TestSiteSetting.objects.create( title="Site title", email="*****@*****.**", site=self.default_site) self.other_site = Site.objects.create(hostname="other", root_page=other_home) self.other_settings = TestSiteSetting.objects.create( title="Other title", email="*****@*****.**", site=self.other_site)
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_slugurl_tag_returns_url_for_current_site(self): home_page = Page.objects.get(url_path="/home/") new_home_page = home_page.copy( update_attrs={"title": "New home page", "slug": "new-home"} ) second_site = Site.objects.create( hostname="site2.example.com", root_page=new_home_page ) # Add a page to the new site that has a slug that is the same as one on # the first site, but is in a different position in the treeself. new_christmas_page = Page(title="Christmas", slug="christmas") new_home_page.add_child(instance=new_christmas_page) request = HttpRequest() request.META["HTTP_HOST"] = second_site.hostname request.META["SERVER_PORT"] = second_site.port url = slugurl(context=template.Context({"request": request}), slug="christmas") self.assertEqual(url, "/christmas/")
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_no_redirects_created_when_pages_are_moved_to_a_different_site( self): # Add a new home page homepage_2 = Page( title="Second home", slug="second-home", ) root_page = Page.objects.get(depth=1) root_page.add_child(instance=homepage_2) # Create a site with the above as the root_page Site.objects.create( root_page=homepage_2, hostname="newsite.com", port=80, ) # Move the event index to the new site self.event_index.move(homepage_2, pos="last-child") # No redirects should have been created self.assertFalse(Redirect.objects.exists())
def test_translation_of(self): en_homepage = Page.objects.get(url_path="/home/") # Create a translation of the homepage fr_locale = Locale.objects.create(language_code="fr") root_page = Page.objects.get(depth=1) fr_homepage = root_page.add_child(instance=Page( title="French homepage", slug="home-fr", locale=fr_locale, translation_key=en_homepage.translation_key, )) with self.assertNumQueries(1): translations = Page.objects.translation_of(en_homepage) self.assertListEqual(list(translations), [fr_homepage]) # Now test with inclusive with self.assertNumQueries(1): translations = Page.objects.translation_of( en_homepage, inclusive=True).order_by("id") self.assertListEqual(list(translations), [en_homepage, fr_homepage])