class TestPageQueryInSite(TestCase): fixtures = ['test.json'] 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 test_in_site(self): site_2_pages = SimplePage.objects.in_site(self.site_2) self.assertIn(self.site_2_page, site_2_pages) self.assertIn(self.site_2_subpage, site_2_pages) self.assertNotIn(self.about_us_page, site_2_pages)
class TestPageQueryInSite(TestCase): fixtures = ['test.json'] 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 test_in_site(self): site_2_pages = SimplePage.objects.in_site(self.site_2) self.assertIn(self.site_2_page, site_2_pages) self.assertIn(self.site_2_subpage, site_2_pages) self.assertNotIn(self.about_us_page, site_2_pages)
def test_get_workflow_from_closest_ancestor(self): # test that using Page.get_workflow() tries to get the workflow from itself, then the closest ancestor, and does # not get Workflows from further up the page tree first workflow_1 = Workflow.objects.create(name='test_workflow_1') workflow_2 = Workflow.objects.create(name='test_workflow_2') homepage = Page.objects.get(url_path='/home/') WorkflowPage.objects.create(page=homepage, workflow=workflow_1) hello_page = SimplePage(title="Hello world", slug='hello-world', content="hello") homepage.add_child(instance=hello_page) WorkflowPage.objects.create(page=hello_page, workflow=workflow_2) goodbye_page = SimplePage(title="Goodbye world", slug='goodbye-world', content="goodbye") hello_page.add_child(instance=goodbye_page) self.assertEqual(hello_page.get_workflow(), workflow_2) self.assertEqual(goodbye_page.get_workflow(), workflow_2) # Check the .all_pages() method self.assertFalse( workflow_1.all_pages().filter(id=hello_page.id).exists()) self.assertFalse( workflow_1.all_pages().filter(id=goodbye_page.id).exists()) self.assertTrue( workflow_2.all_pages().filter(id=hello_page.id).exists()) self.assertTrue( workflow_2.all_pages().filter(id=goodbye_page.id).exists())
class TestBulkMove(TestCase, WagtailTestUtils): 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) for child_page in self.pages_to_be_moved: self.assertInHTML( '<li><a href="{edit_page_url}" target="_blank" rel="noopener 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_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( '<li>{page_title}</li>'.format(page_title=child_page.title), html) self.assertTagInHTML( '''<form action="{}" method="POST"></form>'''.format(self.url), 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='*****@*****.**') 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( '<p>The following pages cannot be moved to {}</p>'.format( page.title), html) for child_page in self.pages_to_be_moved: self.assertInHTML( '<li><a href="{edit_page_url}" target="_blank" rel="noopener 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="noopener 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)
class TestChooserBrowseChild(TestCase, WagtailTestUtils): def setUp(self): self.root_page = Page.objects.get(id=2) # Add child page self.child_page = SimplePage(title="foobarbaz", content="hello") self.root_page.add_child(instance=self.child_page) self.login() def get(self, params={}): return self.client.get(reverse('wagtailadmin_choose_page_child', args=(self.root_page.id,)), params) def get_invalid(self, params={}): return self.client.get(reverse('wagtailadmin_choose_page_child', args=(9999999,)), params) def test_simple(self): response = self.get() self.assertEqual(response.status_code, 200) self.assertTemplateUsed(response, 'wagtailadmin/chooser/browse.html') def test_get_invalid(self): self.assertEqual(self.get_invalid().status_code, 404) def test_with_page_type(self): # Add a page that is not a SimplePage event_page = EventPage( title="event", location='the moon', audience='public', cost='free', date_from='2001-01-01', ) self.root_page.add_child(instance=event_page) # Add a page with a child page event_index_page = EventIndex( title="events", ) self.root_page.add_child(instance=event_index_page) event_index_page.add_child(instance=EventPage( title="other event", location='the moon', audience='public', cost='free', date_from='2001-01-01', )) # Send request response = self.get({'page_type': 'tests.simplepage'}) self.assertEqual(response.status_code, 200) self.assertTemplateUsed(response, 'wagtailadmin/chooser/browse.html') self.assertEqual(response.context['page_type_string'], 'tests.simplepage') pages = { page.id: page for page in response.context['pages'].object_list } # Child page is a simple page directly underneath root # so should appear in the list self.assertIn(self.child_page.id, pages) self.assertTrue(pages[self.child_page.id].can_choose) self.assertFalse(pages[self.child_page.id].can_descend) # Event page is not a simple page and is not descendable either # so should not appear in the list self.assertNotIn(event_page.id, pages) # Event index page is not a simple page but has a child and is therefore descendable # so should appear in the list self.assertIn(event_index_page.id, pages) self.assertFalse(pages[event_index_page.id].can_choose) self.assertTrue(pages[event_index_page.id].can_descend) def test_with_url_extended_page_type(self): # Add a page that overrides the url path single_event_page = SingleEventPage( title="foo", location='the moon', audience='public', cost='free', date_from='2001-01-01', ) self.root_page.add_child(instance=single_event_page) # Send request response = self.get() self.assertEqual(response.status_code, 200) self.assertTemplateUsed(response, 'wagtailadmin/chooser/browse.html') page_urls = [ page.url for page in response.context['pages'] ] self.assertIn('/foo/pointless-suffix/', page_urls) def test_with_blank_page_type(self): # a blank page_type parameter should be equivalent to an absent parameter # (or an explicit page_type of wagtailcore.page) response = self.get({'page_type': ''}) self.assertEqual(response.status_code, 200) self.assertTemplateUsed(response, 'wagtailadmin/chooser/browse.html') def test_with_multiple_page_types(self): # Add a page that is not a SimplePage event_page = EventPage( title="event", location='the moon', audience='public', cost='free', date_from='2001-01-01', ) self.root_page.add_child(instance=event_page) # Send request response = self.get({'page_type': 'tests.simplepage,tests.eventpage'}) self.assertEqual(response.status_code, 200) self.assertTemplateUsed(response, 'wagtailadmin/chooser/browse.html') self.assertEqual(response.context['page_type_string'], 'tests.simplepage,tests.eventpage') pages = { page.id: page for page in response.context['pages'].object_list } # Simple page in results, as before self.assertIn(self.child_page.id, pages) self.assertTrue(pages[self.child_page.id].can_choose) # Event page should now also be choosable self.assertIn(event_page.id, pages) self.assertTrue(pages[self.child_page.id].can_choose) def test_with_unknown_page_type(self): response = self.get({'page_type': 'foo.bar'}) self.assertEqual(response.status_code, 404) def test_with_bad_page_type(self): response = self.get({'page_type': 'wagtailcore.site'}) self.assertEqual(response.status_code, 404) def test_with_invalid_page_type(self): response = self.get({'page_type': 'foo'}) self.assertEqual(response.status_code, 404) def test_with_admin_display_title(self): # Check the display of the child page title when it's a child response = self.get({'page_type': 'wagtailcore.Page'}) self.assertEqual(response.status_code, 200) self.assertTemplateUsed(response, 'wagtailadmin/chooser/browse.html') html = response.json().get('html') self.assertInHTML("foobarbaz (simple page)", html) # The data-title attribute should not use the custom admin display title, # because JS code that uses that attribute (e.g. the rich text editor) # should use the real page title. self.assertIn('data-title="foobarbaz"', html) def test_parent_with_admin_display_title(self): # Add another child under child_page so it renders a chooser list leaf_page = SimplePage(title="quux", content="goodbye") self.child_page.add_child(instance=leaf_page) # Use the child page as the chooser parent response = self.client.get( reverse('wagtailadmin_choose_page_child', args=(self.child_page.id,)), params={'page_type': 'wagtailcore.Page'} ) self.assertEqual(response.status_code, 200) self.assertTemplateUsed(response, 'wagtailadmin/chooser/browse.html') self.assertInHTML("foobarbaz (simple page)", response.json().get('html')) self.assertInHTML("quux (simple page)", response.json().get('html')) def test_admin_display_title_breadcrumb(self): # Add another child under child_page so we get breadcrumbs leaf_page = SimplePage(title="quux", content="goodbye") self.child_page.add_child(instance=leaf_page) # Use the leaf page as the chooser parent, so child is in the breadcrumbs response = self.client.get( reverse('wagtailadmin_choose_page_child', args=(leaf_page.id,)) ) self.assertEqual(response.status_code, 200) self.assertTemplateUsed(response, 'wagtailadmin/chooser/browse.html') # Look for a link element in the breadcrumbs with the admin title self.assertTagInHTML( '<li><a href="/admin/choose-page/{page_id}/?" class="navigate-pages">{page_title}</a></li>'.format( page_id=self.child_page.id, page_title="foobarbaz (simple page)", ), response.json().get('html') ) def setup_pagination_test_data(self): # Create lots of pages for i in range(100): new_page = SimplePage( title="foobarbaz", slug="foobarbaz-%d" % i, content="hello", ) self.root_page.add_child(instance=new_page) def test_pagination_basic(self): self.setup_pagination_test_data() response = self.get() self.assertEqual(response.context['pages'].paginator.num_pages, 5) self.assertEqual(response.context['pages'].number, 1) def test_pagination_another_page(self): self.setup_pagination_test_data() response = self.get({'p': 2}) self.assertEqual(response.context['pages'].number, 2) def test_pagination_invalid_page(self): self.setup_pagination_test_data() response = self.get({'p': 'foo'}) self.assertEqual(response.context['pages'].number, 1) def test_pagination_out_of_range_page(self): self.setup_pagination_test_data() response = self.get({'p': 100}) self.assertEqual(response.context['pages'].number, 5)
class TestChooserBrowseChild(TestCase, WagtailTestUtils): def setUp(self): self.root_page = Page.objects.get(id=2) # Add child page self.child_page = SimplePage(title="foobarbaz", content="hello") self.root_page.add_child(instance=self.child_page) self.login() def get(self, params={}): return self.client.get(reverse('wagtailadmin_choose_page_child', args=(self.root_page.id,)), params) def get_invalid(self, params={}): return self.client.get(reverse('wagtailadmin_choose_page_child', args=(9999999,)), params) def test_simple(self): response = self.get() self.assertEqual(response.status_code, 200) self.assertTemplateUsed(response, 'wagtailadmin/chooser/browse.html') def test_get_invalid(self): self.assertEqual(self.get_invalid().status_code, 404) def test_with_page_type(self): # Add a page that is not a SimplePage event_page = EventPage( title="event", location='the moon', audience='public', cost='free', date_from='2001-01-01', ) self.root_page.add_child(instance=event_page) # Add a page with a child page event_index_page = EventIndex( title="events", ) self.root_page.add_child(instance=event_index_page) event_index_page.add_child(instance=EventPage( title="other event", location='the moon', audience='public', cost='free', date_from='2001-01-01', )) # Send request response = self.get({'page_type': 'tests.simplepage'}) self.assertEqual(response.status_code, 200) self.assertTemplateUsed(response, 'wagtailadmin/chooser/browse.html') self.assertEqual(response.context['page_type_string'], 'tests.simplepage') pages = { page.id: page for page in response.context['pages'].object_list } # Child page is a simple page directly underneath root # so should appear in the list self.assertIn(self.child_page.id, pages) self.assertTrue(pages[self.child_page.id].can_choose) self.assertFalse(pages[self.child_page.id].can_descend) # Event page is not a simple page and is not descendable either # so should not appear in the list self.assertNotIn(event_page.id, pages) # Event index page is not a simple page but has a child and is therefore descendable # so should appear in the list self.assertIn(event_index_page.id, pages) self.assertFalse(pages[event_index_page.id].can_choose) self.assertTrue(pages[event_index_page.id].can_descend) def test_with_url_extended_page_type(self): # Add a page that overrides the url path single_event_page = SingleEventPage( title="foo", location='the moon', audience='public', cost='free', date_from='2001-01-01', ) self.root_page.add_child(instance=single_event_page) # Send request response = self.get() self.assertEqual(response.status_code, 200) self.assertTemplateUsed(response, 'wagtailadmin/chooser/browse.html') page_urls = [ page.url for page in response.context['pages'] ] self.assertIn('/foo/pointless-suffix/', page_urls) def test_with_blank_page_type(self): # a blank page_type parameter should be equivalent to an absent parameter # (or an explicit page_type of wagtailcore.page) response = self.get({'page_type': ''}) self.assertEqual(response.status_code, 200) self.assertTemplateUsed(response, 'wagtailadmin/chooser/browse.html') def test_with_multiple_page_types(self): # Add a page that is not a SimplePage event_page = EventPage( title="event", location='the moon', audience='public', cost='free', date_from='2001-01-01', ) self.root_page.add_child(instance=event_page) # Send request response = self.get({'page_type': 'tests.simplepage,tests.eventpage'}) self.assertEqual(response.status_code, 200) self.assertTemplateUsed(response, 'wagtailadmin/chooser/browse.html') self.assertEqual(response.context['page_type_string'], 'tests.simplepage,tests.eventpage') pages = { page.id: page for page in response.context['pages'].object_list } # Simple page in results, as before self.assertIn(self.child_page.id, pages) self.assertTrue(pages[self.child_page.id].can_choose) # Event page should now also be choosable self.assertIn(event_page.id, pages) self.assertTrue(pages[self.child_page.id].can_choose) def test_with_unknown_page_type(self): response = self.get({'page_type': 'foo.bar'}) self.assertEqual(response.status_code, 404) def test_with_bad_page_type(self): response = self.get({'page_type': 'wagtailcore.site'}) self.assertEqual(response.status_code, 404) def test_with_invalid_page_type(self): response = self.get({'page_type': 'foo'}) self.assertEqual(response.status_code, 404) def test_with_admin_display_title(self): # Check the display of the child page title when it's a child response = self.get({'page_type': 'wagtailcore.Page'}) self.assertEqual(response.status_code, 200) self.assertTemplateUsed(response, 'wagtailadmin/chooser/browse.html') self.assertInHTML("foobarbaz (simple page)", response.json().get('html')) def test_parent_with_admin_display_title(self): # Add another child under child_page so it renders a chooser list leaf_page = SimplePage(title="quux", content="goodbye") self.child_page.add_child(instance=leaf_page) # Use the child page as the chooser parent response = self.client.get( reverse('wagtailadmin_choose_page_child', args=(self.child_page.id,)), params={'page_type': 'wagtailcore.Page'} ) self.assertEqual(response.status_code, 200) self.assertTemplateUsed(response, 'wagtailadmin/chooser/browse.html') self.assertInHTML("foobarbaz (simple page)", response.json().get('html')) self.assertInHTML("quux (simple page)", response.json().get('html')) def test_admin_display_title_breadcrumb(self): # Add another child under child_page so we get breadcrumbs leaf_page = SimplePage(title="quux", content="goodbye") self.child_page.add_child(instance=leaf_page) # Use the leaf page as the chooser parent, so child is in the breadcrumbs response = self.client.get( reverse('wagtailadmin_choose_page_child', args=(leaf_page.id,)) ) self.assertEqual(response.status_code, 200) self.assertTemplateUsed(response, 'wagtailadmin/chooser/browse.html') # Look for a link element in the breadcrumbs with the admin title self.assertTagInHTML( '<li><a href="/admin/choose-page/{page_id}/?" class="navigate-pages">{page_title}</a></li>'.format( page_id=self.child_page.id, page_title="foobarbaz (simple page)", ), response.json().get('html') ) def setup_pagination_test_data(self): # Create lots of pages for i in range(100): new_page = SimplePage( title="foobarbaz", slug="foobarbaz-%d" % i, content="hello", ) self.root_page.add_child(instance=new_page) def test_pagination_basic(self): self.setup_pagination_test_data() response = self.get() self.assertEqual(response.context['pages'].paginator.num_pages, 5) self.assertEqual(response.context['pages'].number, 1) def test_pagination_another_page(self): self.setup_pagination_test_data() response = self.get({'p': 2}) self.assertEqual(response.context['pages'].number, 2) def test_pagination_invalid_page(self): self.setup_pagination_test_data() response = self.get({'p': 'foo'}) self.assertEqual(response.context['pages'].number, 1) def test_pagination_out_of_range_page(self): self.setup_pagination_test_data() response = self.get({'p': 100}) self.assertEqual(response.context['pages'].number, 5)
class TestPageMove(TestCase, WagtailTestUtils): 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", 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", content="hello") self.section_c.add_child(instance=self.test_page_b) # 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) 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 403 response self.assertEqual(response.status_code, 403) 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("{}".format(self.test_page_b.slug), messages[0].message) def test_page_set_page_position(self): response = self.client.get( reverse('wagtailadmin_pages:set_page_position', args=(self.test_page_a.id, ))) self.assertEqual(response.status_code, 200) 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)
class TestPageMove(TestCase, WagtailTestUtils): 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", 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", content="hello") self.section_c.add_child(instance=self.test_page_b) # 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() # 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) 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 403 response self.assertEqual(response.status_code, 403) 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='*****@*****.**') 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("{}".format(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) # Check that the pre_page_move signal was fired self.assertEqual(pre_moved_handler.call_count, 1) self.assertTrue( pre_moved_handler.called_with( sender=self.test_page_a.specific_class, instance=self.test_page_a, parent_page_before=self.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) self.assertTrue( post_moved_handler.called_with( sender=self.test_page_a.specific_class, instance=self.test_page_a, parent_page_before=self.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_page_set_page_position(self): response = self.client.get( reverse('wagtailadmin_pages:set_page_position', args=(self.test_page_a.id, ))) self.assertEqual(response.status_code, 200) 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)
class TestPageSlugChangedSignal(TestCase, WagtailTestUtils): """ Tests for the `wagtail.core.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)