Exemplo n.º 1
0
    def test_future_go_live_page_will_not_be_published(self):
        page = SimplePage(
            title="Hello world!",
            slug="hello-world",
            content="hello",
            live=False,
            go_live_at=timezone.now() + timedelta(days=1),
        )
        self.root_page.add_child(instance=page)

        page.save_revision(approved_go_live_at=timezone.now() -
                           timedelta(days=1))

        p = Page.objects.get(slug="hello-world")
        self.assertFalse(p.live)
        self.assertTrue(
            PageRevision.objects.filter(page=p).exclude(
                approved_go_live_at__isnull=True).exists())

        management.call_command("publish_scheduled_pages")

        p = Page.objects.get(slug="hello-world")
        self.assertFalse(p.live)
        self.assertTrue(
            PageRevision.objects.filter(page=p).exclude(
                approved_go_live_at__isnull=True).exists())
Exemplo n.º 2
0
    def test_disable_preview_on_revisions_list(self):
        simple_page = SimplePage(title="simple page", content="hello")
        self.root_page.add_child(instance=simple_page)
        simple_page.save_revision(log_action=True)

        # check preview shows up by default
        response = self.client.get(
            reverse("wagtailadmin_pages:history", args=(simple_page.id,))
        )
        preview_url = reverse(
            "wagtailadmin_pages:revisions_view",
            args=(simple_page.id, simple_page.get_latest_revision().id),
        )
        self.assertContains(response, "Preview")
        self.assertContains(response, preview_url)

        stream_page = StreamPage(title="stream page", body=[("text", "hello")])
        self.root_page.add_child(instance=stream_page)
        latest_revision = stream_page.save_revision(log_action=True)

        # StreamPage has preview_modes = []
        response = self.client.get(
            reverse("wagtailadmin_pages:history", args=(stream_page.id,))
        )
        preview_url = reverse(
            "wagtailadmin_pages:revisions_view",
            args=(stream_page.id, latest_revision.id),
        )
        self.assertNotContains(response, "Preview")
        self.assertNotContains(response, preview_url)
Exemplo n.º 3
0
class TestApproveRejectModerationWithoutUser(TestCase, WagtailTestUtils):
    def setUp(self):
        self.submitter = self.create_superuser(
            username="******",
            email="*****@*****.**",
            password="******",
        )

        self.user = self.login()

        # Create a page and submit it for moderation
        root_page = Page.objects.get(id=2)
        self.page = SimplePage(
            title="Hello world!",
            slug="hello-world",
            content="hello",
            live=False,
            has_unpublished_changes=True,
        )
        root_page.add_child(instance=self.page)

        # save_revision without user
        self.page.save_revision(submitted_for_moderation=True)
        self.revision = self.page.get_latest_revision()

    def test_approve_moderation_view_without_user(self):
        """
        This posts to the approve moderation view and checks that the page was approved
        """
        # Connect a mock signal handler to page_published signal
        mock_handler = mock.MagicMock()
        page_published.connect(mock_handler)

        # Post
        response = self.client.post(
            reverse("wagtailadmin_pages:approve_moderation", args=(self.revision.id,))
        )

        # Check that the user was redirected to the dashboard
        self.assertRedirects(response, reverse("wagtailadmin_home"))

        page = Page.objects.get(id=self.page.id)
        # Page must be live
        self.assertTrue(page.live, "Approving moderation failed to set live=True")
        # Page should now have no unpublished changes
        self.assertFalse(
            page.has_unpublished_changes,
            "Approving moderation failed to set has_unpublished_changes=False",
        )

        # Check that the page_published 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)
Exemplo n.º 4
0
    def setUp(self):
        # Find root page
        self.root_page = Page.objects.get(id=2)

        # Add child page
        child_page = SimplePage(
            title="Hello world!",
            slug="hello-world",
            content="Some content here",
        )
        self.root_page.add_child(instance=child_page)
        child_page.save_revision().publish()
        self.child_page = SimplePage.objects.get(id=child_page.id)

        self.create_superuser(username="******", password="******")
        self.create_superuser(username="******", password="******")
Exemplo n.º 5
0
    def test_go_live_page_will_be_published(self):
        # Connect a mock signal handler to page_published signal
        signal_fired = [False]
        signal_page = [None]

        def page_published_handler(sender, instance, **kwargs):
            signal_fired[0] = True
            signal_page[0] = instance

        page_published.connect(page_published_handler)

        page = SimplePage(
            title="Hello world!",
            slug="hello-world",
            content="hello",
            live=False,
            has_unpublished_changes=True,
            go_live_at=timezone.now() - timedelta(days=1),
        )
        self.root_page.add_child(instance=page)

        page.save_revision(approved_go_live_at=timezone.now() -
                           timedelta(days=1))

        p = Page.objects.get(slug="hello-world")
        self.assertFalse(p.live)
        self.assertTrue(
            PageRevision.objects.filter(page=p).exclude(
                approved_go_live_at__isnull=True).exists())

        management.call_command("publish_scheduled_pages")

        p = Page.objects.get(slug="hello-world")
        self.assertTrue(p.live)
        self.assertTrue(p.first_published_at)
        self.assertFalse(p.has_unpublished_changes)
        self.assertFalse(
            PageRevision.objects.filter(page=p).exclude(
                approved_go_live_at__isnull=True).exists())

        # 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)
Exemplo n.º 6
0
    def test_go_live_when_newer_revision_exists(self):
        page = SimplePage(
            title="Hello world!",
            slug="hello-world",
            content="hello",
            live=False,
            has_unpublished_changes=True,
            go_live_at=timezone.now() - timedelta(days=1),
        )
        self.root_page.add_child(instance=page)

        page.save_revision(approved_go_live_at=timezone.now() -
                           timedelta(days=1))

        page.title = "Goodbye world!"
        page.save_revision(submitted_for_moderation=False)

        management.call_command("publish_scheduled_pages")

        p = Page.objects.get(slug="hello-world")
        self.assertTrue(p.live)
        self.assertTrue(p.has_unpublished_changes)
        self.assertEqual(p.title, "Hello world!")
Exemplo n.º 7
0
    def test_expired_pages_are_dropped_from_mod_queue(self):
        page = SimplePage(
            title="Hello world!",
            slug="hello-world",
            content="hello",
            live=False,
            expire_at=timezone.now() - timedelta(days=1),
        )
        self.root_page.add_child(instance=page)

        page.save_revision(submitted_for_moderation=True)

        p = Page.objects.get(slug="hello-world")
        self.assertFalse(p.live)
        self.assertTrue(
            PageRevision.objects.filter(
                page=p, submitted_for_moderation=True).exists())

        management.call_command("publish_scheduled_pages")

        p = Page.objects.get(slug="hello-world")
        self.assertFalse(
            PageRevision.objects.filter(
                page=p, submitted_for_moderation=True).exists())
Exemplo n.º 8
0
class TestEnablePreview(TestCase, WagtailTestUtils):
    def setUp(self):
        self.root_page = Page.objects.get(id=2)
        self.user = self.login()

        # SimplePage only has one preview mode
        self.single = SimplePage(title="Single preview mode", content="foo")
        # MultiPreviewModesPage has two preview modes
        self.multiple = MultiPreviewModesPage(title="Multiple preview modes")

        self.root_page.add_child(instance=self.single)
        self.root_page.add_child(instance=self.multiple)

    def get_url_on_add(self, name, page):
        model_name = type(page)._meta.model_name
        return reverse(
            f"wagtailadmin_pages:{name}",
            args=("tests", model_name, self.root_page.id),
        )

    def get_url_on_edit(self, name, page):
        return reverse(f"wagtailadmin_pages:{name}", args=(page.id, ))

    def test_show_preview_panel_on_create_with_single_mode(self):
        create_url = self.get_url_on_add("add", self.single)
        preview_url = self.get_url_on_add("preview_on_add", self.single)
        iframe_url = preview_url + "?in_preview_panel=true&mode="
        response = self.client.get(create_url)

        self.assertEqual(response.status_code, 200)

        # Should show the preview panel
        self.assertContains(response, 'data-side-panel-toggle="preview"')
        self.assertContains(response, 'data-side-panel="preview"')
        self.assertContains(response, 'data-action="%s"' % preview_url)

        # Should show the iframe
        self.assertContains(
            response,
            f'<iframe title="Preview" class="preview-panel__iframe" data-preview-iframe src="{iframe_url}" aria-describedby="preview-panel-error-banner">',
        )

        # Should not show the preview mode selection
        self.assertNotContains(
            response,
            '<select id="id_preview_mode" name="preview_mode" class="preview-panel__mode-select" data-preview-mode-select>',
        )

    def test_show_preview_panel_on_create_with_multiple_modes(self):
        create_url = self.get_url_on_add("add", self.multiple)
        preview_url = self.get_url_on_add("preview_on_add", self.multiple)
        iframe_url = preview_url + "?in_preview_panel=true&mode=alt%231"
        response = self.client.get(create_url)

        self.assertEqual(response.status_code, 200)

        # Should show the preview panel
        self.assertContains(response, 'data-side-panel-toggle="preview"')
        self.assertContains(response, 'data-side-panel="preview"')
        self.assertContains(response, 'data-action="%s"' % preview_url)

        # Should show the iframe with the default mode set and correctly quoted
        self.assertContains(
            response,
            f'<iframe title="Preview" class="preview-panel__iframe" data-preview-iframe src="{iframe_url}" aria-describedby="preview-panel-error-banner">',
        )

        # should show the preview mode selection
        self.assertContains(
            response,
            '<select id="id_preview_mode" name="preview_mode" class="preview-panel__mode-select" data-preview-mode-select>',
        )
        self.assertContains(response,
                            '<option value="original">Original</option>')

        # Should respect the default_preview_mode
        self.assertContains(
            response, '<option value="alt#1" selected>Alternate</option>')

    def test_show_preview_panel_on_edit_with_single_mode(self):
        edit_url = self.get_url_on_edit("edit", self.single)
        preview_url = self.get_url_on_edit("preview_on_edit", self.single)
        iframe_url = preview_url + "?in_preview_panel=true&mode="
        response = self.client.get(edit_url)

        self.assertEqual(response.status_code, 200)

        # Should show the preview panel
        self.assertContains(response, 'data-side-panel-toggle="preview"')
        self.assertContains(response, 'data-side-panel="preview"')
        self.assertContains(response, 'data-action="%s"' % preview_url)

        # Should show the iframe
        self.assertContains(
            response,
            f'<iframe title="Preview" class="preview-panel__iframe" data-preview-iframe src="{iframe_url}" aria-describedby="preview-panel-error-banner">',
        )

        # Should not show the preview mode selection
        self.assertNotContains(
            response,
            '<select id="id_preview_mode" name="preview_mode" class="preview-panel__mode-select" data-preview-mode-select>',
        )

    def test_show_preview_panel_on_edit_with_multiple_modes(self):
        edit_url = self.get_url_on_edit("edit", self.multiple)
        preview_url = self.get_url_on_edit("preview_on_edit", self.multiple)
        iframe_url = preview_url + "?in_preview_panel=true&mode=alt%231"
        response = self.client.get(edit_url)

        self.assertEqual(response.status_code, 200)

        # Should show the preview panel
        self.assertContains(response, 'data-side-panel-toggle="preview"')
        self.assertContains(response, 'data-side-panel="preview"')
        self.assertContains(response, 'data-action="%s"' % preview_url)

        # Should show the iframe with the default mode set and correctly quoted
        self.assertContains(
            response,
            f'<iframe title="Preview" class="preview-panel__iframe" data-preview-iframe src="{iframe_url}" aria-describedby="preview-panel-error-banner">',
        )

        # should show the preview mode selection
        self.assertContains(
            response,
            '<select id="id_preview_mode" name="preview_mode" class="preview-panel__mode-select" data-preview-mode-select>',
        )
        self.assertContains(response,
                            '<option value="original">Original</option>')

        # Should respect the default_preview_mode
        self.assertContains(
            response, '<option value="alt#1" selected>Alternate</option>')

    def test_show_preview_on_revisions_list(self):
        latest_revision = self.single.save_revision(log_action=True)
        history_url = self.get_url_on_edit("history", self.single)
        preview_url = reverse(
            "wagtailadmin_pages:revisions_view",
            args=(self.single.id, latest_revision.id),
        )

        response = self.client.get(history_url)
        self.assertContains(response, "Preview")
        self.assertContains(response, preview_url)
Exemplo n.º 9
0
class TestCreateLogEntriesFromRevisionsCommand(TestCase):
    fixtures = ["test.json"]

    def setUp(self):
        self.page = SimplePage(
            title="Hello world!",
            slug="hello-world",
            content="hello",
            live=False,
            expire_at=timezone.now() - timedelta(days=1),
        )

        Page.objects.get(id=2).add_child(instance=self.page)

        # Create empty revisions, which should not be converted to log entries
        for i in range(3):
            self.page.save_revision()

        # Add another revision with a content change
        self.page.title = "Hello world!!"
        revision = self.page.save_revision()
        revision.publish()

        # Do the same with a SecretPage (to check that the version comparison code doesn't
        # trip up on permission-dependent edit handlers)
        self.secret_page = SecretPage(
            title="The moon",
            slug="the-moon",
            boring_data="the moon",
            secret_data="is made of cheese",
            live=False,
        )

        Page.objects.get(id=2).add_child(instance=self.secret_page)

        # Create empty revisions, which should not be converted to log entries
        for i in range(3):
            self.secret_page.save_revision()

        # Add another revision with a content change
        self.secret_page.secret_data = "is flat"
        revision = self.secret_page.save_revision()
        revision.publish()

        # clean up log entries
        PageLogEntry.objects.all().delete()

    def test_log_entries_created_from_revisions(self):
        management.call_command("create_log_entries_from_revisions")

        # Should not create entries for empty revisions.
        self.assertListEqual(
            list(PageLogEntry.objects.values_list("action", flat=True)),
            [
                "wagtail.publish",
                "wagtail.edit",
                "wagtail.create",
                "wagtail.publish",
                "wagtail.edit",
                "wagtail.create",
            ],
        )

    def test_command_doesnt_crash_for_revisions_without_page_model(self):
        with mock.patch(
                "wagtail.models.ContentType.model_class",
                return_value=None,
        ):
            management.call_command("create_log_entries_from_revisions")
            self.assertEqual(PageLogEntry.objects.count(), 0)
Exemplo n.º 10
0
class TestPurgeRevisionsCommand(TestCase):
    fixtures = ["test.json"]

    def setUp(self):
        # Find root page
        self.root_page = Page.objects.get(id=2)
        self.page = SimplePage(
            title="Hello world!",
            slug="hello-world",
            content="hello",
            live=False,
        )
        self.root_page.add_child(instance=self.page)
        self.page.refresh_from_db()

    def run_command(self, days=None):
        if days:
            days_input = "--days=" + str(days)
            return management.call_command("purge_revisions",
                                           days_input,
                                           stdout=StringIO())
        return management.call_command("purge_revisions", stdout=StringIO())

    def test_latest_revision_not_purged(self):

        revision_1 = self.page.save_revision()

        revision_2 = self.page.save_revision()

        self.run_command()

        # revision 1 should be deleted, revision 2 should not be
        self.assertNotIn(revision_1,
                         PageRevision.objects.filter(page=self.page))
        self.assertIn(revision_2, PageRevision.objects.filter(page=self.page))

    def test_revisions_in_moderation_not_purged(self):

        self.page.save_revision(submitted_for_moderation=True)

        revision = self.page.save_revision()

        self.run_command()

        self.assertTrue(
            PageRevision.objects.filter(
                page=self.page, submitted_for_moderation=True).exists())

        try:
            from wagtail.models import Task, Workflow, WorkflowTask

            workflow = Workflow.objects.create(name="test_workflow")
            task_1 = Task.objects.create(name="test_task_1")
            user = get_user_model().objects.first()
            WorkflowTask.objects.create(workflow=workflow,
                                        task=task_1,
                                        sort_order=1)
            workflow.start(self.page, user)
            self.page.save_revision()
            self.run_command()
            # even though no longer the latest revision, the old revision should stay as it is
            # attached to an in progress workflow
            self.assertIn(revision,
                          PageRevision.objects.filter(page=self.page))
        except ImportError:
            pass

    def test_revisions_with_approve_go_live_not_purged(self):

        approved_revision = self.page.save_revision(
            approved_go_live_at=timezone.now() + timedelta(days=1))

        self.page.save_revision()

        self.run_command()

        self.assertIn(approved_revision,
                      PageRevision.objects.filter(page=self.page))

    def test_purge_revisions_with_date_cutoff(self):

        old_revision = self.page.save_revision()

        self.page.save_revision()

        self.run_command(days=30)

        # revision should not be deleted, as it is younger than 30 days
        self.assertIn(old_revision,
                      PageRevision.objects.filter(page=self.page))

        old_revision.created_at = timezone.now() - timedelta(days=31)
        old_revision.save()

        self.run_command(days=30)

        # revision is now older than 30 days, so should be deleted
        self.assertNotIn(old_revision,
                         PageRevision.objects.filter(page=self.page))
Exemplo n.º 11
0
class TestNotificationPreferences(TestCase, WagtailTestUtils):
    def setUp(self):
        # Find root page
        self.root_page = Page.objects.get(id=2)

        # Login
        self.user = self.login()

        # Create two moderator users for testing 'submitted' email
        self.moderator = self.create_superuser("moderator",
                                               "*****@*****.**",
                                               "password")
        self.moderator2 = self.create_superuser("moderator2",
                                                "*****@*****.**",
                                                "password")

        # Create a submitter for testing 'rejected' and 'approved' emails
        self.submitter = self.create_user("submitter", "*****@*****.**",
                                          "password")

        # User profiles for moderator2 and the submitter
        self.moderator2_profile = UserProfile.get_for_user(self.moderator2)
        self.submitter_profile = UserProfile.get_for_user(self.submitter)

        # 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)

        # POST data to edit the page
        self.post_data = {
            "title": "I've been edited!",
            "content": "Some content",
            "slug": "hello-world",
            "action-submit": "Submit",
        }

    def submit(self):
        return self.client.post(
            reverse("wagtailadmin_pages:edit", args=(self.child_page.id, )),
            self.post_data,
        )

    def silent_submit(self):
        """
        Sets up the child_page as needing moderation, without making a request
        """
        self.child_page.save_revision(user=self.submitter,
                                      submitted_for_moderation=True)
        self.revision = self.child_page.get_latest_revision()

    def approve(self):
        return self.client.post(
            reverse("wagtailadmin_pages:approve_moderation",
                    args=(self.revision.id, )))

    def reject(self):
        return self.client.post(
            reverse("wagtailadmin_pages:reject_moderation",
                    args=(self.revision.id, )))

    def test_vanilla_profile(self):
        # Check that the vanilla profile has rejected notifications on
        self.assertIs(self.submitter_profile.rejected_notifications, True)

        # Check that the vanilla profile has approved notifications on
        self.assertIs(self.submitter_profile.approved_notifications, True)

    def test_approved_notifications(self):
        # Set up the page version
        self.silent_submit()
        # Approve
        self.approve()

        # Submitter must receive an approved email
        self.assertEqual(len(mail.outbox), 1)
        self.assertEqual(mail.outbox[0].to, ["*****@*****.**"])
        self.assertEqual(mail.outbox[0].subject,
                         'The page "Hello world!" has been approved')

    def test_approved_notifications_preferences_respected(self):
        # Submitter doesn't want 'approved' emails
        self.submitter_profile.approved_notifications = False
        self.submitter_profile.save()

        # Set up the page version
        self.silent_submit()
        # Approve
        self.approve()

        # No email to send
        self.assertEqual(len(mail.outbox), 0)

    def test_rejected_notifications(self):
        # Set up the page version
        self.silent_submit()
        # Reject
        self.reject()

        # Submitter must receive a rejected email
        self.assertEqual(len(mail.outbox), 1)
        self.assertEqual(mail.outbox[0].to, ["*****@*****.**"])
        self.assertEqual(mail.outbox[0].subject,
                         'The page "Hello world!" has been rejected')

    def test_rejected_notification_preferences_respected(self):
        # Submitter doesn't want 'rejected' emails
        self.submitter_profile.rejected_notifications = False
        self.submitter_profile.save()

        # Set up the page version
        self.silent_submit()
        # Reject
        self.reject()

        # No email to send
        self.assertEqual(len(mail.outbox), 0)

    @override_settings(WAGTAILADMIN_NOTIFICATION_INCLUDE_SUPERUSERS=False)
    def test_disable_superuser_notification(self):
        # Add one of the superusers to the moderator group
        self.moderator.groups.add(Group.objects.get(name="Moderators"))

        response = self.submit()

        # Should be redirected to explorer page
        self.assertEqual(response.status_code, 302)

        # Check that the non-moderator superuser is not being notified
        expected_emails = 1
        self.assertEqual(len(mail.outbox), expected_emails)
        # Use chain as the 'to' field is a list of recipients
        email_to = list(chain.from_iterable([m.to for m in mail.outbox]))
        self.assertIn(self.moderator.email, email_to)
        self.assertNotIn(self.moderator2.email, email_to)

    @mock.patch.object(EmailMultiAlternatives,
                       "send",
                       side_effect=IOError("Server down"))
    def test_email_send_error(self, mock_fn):
        logging.disable(logging.CRITICAL)
        # Approve
        self.silent_submit()
        response = self.approve()
        logging.disable(logging.NOTSET)

        # An email that fails to send should return a message rather than crash the page
        self.assertEqual(response.status_code, 302)
        response = self.client.get(reverse("wagtailadmin_home"))

        # There should be one "approved" message and one "failed to send notifications"
        messages = list(response.context["messages"])
        self.assertEqual(len(messages), 2)
        self.assertEqual(messages[0].level, message_constants.SUCCESS)
        self.assertEqual(messages[1].level, message_constants.ERROR)

    def test_email_headers(self):
        # Submit
        self.submit()

        msg_headers = set(mail.outbox[0].message().items())
        headers = {("Auto-Submitted", "auto-generated")}
        self.assertTrue(
            headers.issubset(msg_headers),
            msg="Message is missing the Auto-Submitted header.",
        )
Exemplo n.º 12
0
class TestApproveRejectModeration(TestCase, WagtailTestUtils):
    def setUp(self):
        self.submitter = self.create_superuser(
            username="******",
            email="*****@*****.**",
            password="******",
        )

        self.user = self.login()

        # Create a page and submit it for moderation
        root_page = Page.objects.get(id=2)
        self.page = SimplePage(
            title="Hello world!",
            slug="hello-world",
            content="hello",
            live=False,
            has_unpublished_changes=True,
        )
        root_page.add_child(instance=self.page)

        self.page.save_revision(user=self.submitter,
                                submitted_for_moderation=True)
        self.revision = self.page.get_latest_revision()

    def test_approve_moderation_view(self):
        """
        This posts to the approve moderation view and checks that the page was approved
        """
        # Connect a mock signal handler to page_published signal
        mock_handler = mock.MagicMock()
        page_published.connect(mock_handler)

        # Post
        response = self.client.post(
            reverse("wagtailadmin_pages:approve_moderation",
                    args=(self.revision.id, )))

        # Check that the user was redirected to the dashboard
        self.assertRedirects(response, reverse("wagtailadmin_home"))

        page = Page.objects.get(id=self.page.id)
        # Page must be live
        self.assertTrue(page.live,
                        "Approving moderation failed to set live=True")
        # Page should now have no unpublished changes
        self.assertFalse(
            page.has_unpublished_changes,
            "Approving moderation failed to set has_unpublished_changes=False",
        )

        # Check that the page_published 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_approve_moderation_when_later_revision_exists(self):
        self.page.title = "Goodbye world!"
        self.page.save_revision(user=self.submitter,
                                submitted_for_moderation=False)

        response = self.client.post(
            reverse("wagtailadmin_pages:approve_moderation",
                    args=(self.revision.id, )))

        # Check that the user was redirected to the dashboard
        self.assertRedirects(response, reverse("wagtailadmin_home"))

        page = Page.objects.get(id=self.page.id)
        # Page must be live
        self.assertTrue(page.live,
                        "Approving moderation failed to set live=True")
        # Page content should be the submitted version, not the published one
        self.assertEqual(page.title, "Hello world!")
        # Page should still have unpublished changes
        self.assertTrue(
            page.has_unpublished_changes,
            "has_unpublished_changes incorrectly cleared on approve_moderation when a later revision exists",
        )

    def test_approve_moderation_view_bad_revision_id(self):
        """
        This tests that the approve moderation view handles invalid revision ids correctly
        """
        # Post
        response = self.client.post(
            reverse("wagtailadmin_pages:approve_moderation", args=(12345, )))

        # Check that the user received a 404 response
        self.assertEqual(response.status_code, 404)

    def test_approve_moderation_view_bad_permissions(self):
        """
        This tests that the approve moderation view doesn't allow users without moderation permissions
        """
        # Remove privileges from user
        self.user.is_superuser = False
        self.user.user_permissions.add(
            Permission.objects.get(content_type__app_label="wagtailadmin",
                                   codename="access_admin"))
        self.user.save()

        # Post
        response = self.client.post(
            reverse("wagtailadmin_pages:approve_moderation",
                    args=(self.revision.id, )))

        # Check that the user received a 302 redirected response
        self.assertEqual(response.status_code, 302)

    def test_reject_moderation_view(self):
        """
        This posts to the reject moderation view and checks that the page was rejected
        """
        # Post
        response = self.client.post(
            reverse("wagtailadmin_pages:reject_moderation",
                    args=(self.revision.id, )))

        # Check that the user was redirected to the dashboard
        self.assertRedirects(response, reverse("wagtailadmin_home"))

        # Page must not be live
        self.assertFalse(Page.objects.get(id=self.page.id).live)

        # Revision must no longer be submitted for moderation
        self.assertFalse(
            PageRevision.objects.get(
                id=self.revision.id).submitted_for_moderation)

    def test_reject_moderation_view_bad_revision_id(self):
        """
        This tests that the reject moderation view handles invalid revision ids correctly
        """
        # Post
        response = self.client.post(
            reverse("wagtailadmin_pages:reject_moderation", args=(12345, )))

        # Check that the user received a 404 response
        self.assertEqual(response.status_code, 404)

    def test_reject_moderation_view_bad_permissions(self):
        """
        This tests that the reject moderation view doesn't allow users without moderation permissions
        """
        # Remove privileges from user
        self.user.is_superuser = False
        self.user.user_permissions.add(
            Permission.objects.get(content_type__app_label="wagtailadmin",
                                   codename="access_admin"))
        self.user.save()

        # Post
        response = self.client.post(
            reverse("wagtailadmin_pages:reject_moderation",
                    args=(self.revision.id, )))

        # Check that the user received a 302 redirected response
        self.assertEqual(response.status_code, 302)

    def test_preview_for_moderation(self):
        response = self.client.get(
            reverse("wagtailadmin_pages:preview_for_moderation",
                    args=(self.revision.id, )))

        # Check response
        self.assertEqual(response.status_code, 200)
        self.assertTemplateUsed(response, "tests/simple_page.html")
        self.assertContains(response, "Hello world!")
Exemplo n.º 13
0
class TestAuditLogAdmin(TestCase, WagtailTestUtils):
    def setUp(self):
        self.root_page = Page.objects.get(id=2)

        self.hello_page = SimplePage(
            title="Hello world!",
            slug="hello-world",
            content="hello",
            live=False,
        )
        self.root_page.add_child(instance=self.hello_page)

        self.about_page = SimplePage(title="About", slug="about", content="hello")
        self.root_page.add_child(instance=self.about_page)

        self.administrator = self.create_superuser(
            username="******",
            email="*****@*****.**",
            password="******",
        )
        self.editor = self.create_user(
            username="******", email="*****@*****.**", password="******"
        )
        sub_editors = Group.objects.create(name="Sub editors")
        sub_editors.permissions.add(
            Permission.objects.get(
                content_type__app_label="wagtailadmin", codename="access_admin"
            )
        )
        self.editor.groups.add(sub_editors)

        for permission_type in ["add", "edit", "publish"]:
            GroupPagePermission.objects.create(
                group=sub_editors, page=self.hello_page, permission_type=permission_type
            )

    def _update_page(self, page):
        # save revision
        page.save_revision(user=self.editor, log_action=True)
        # schedule for publishing
        page.go_live_at = timezone.now() + timedelta(seconds=1)
        revision = page.save_revision(user=self.editor, log_action=True)
        revision.publish(user=self.editor)

        # publish
        with freeze_time(timezone.now() + timedelta(seconds=2)):
            revision.publish(user=self.editor)

            # lock/unlock
            page.save(user=self.editor, log_action="wagtail.lock")
            page.save(user=self.editor, log_action="wagtail.unlock")

            # change privacy
            restriction = PageViewRestriction(
                page=page, restriction_type=PageViewRestriction.LOGIN
            )
            restriction.save(user=self.editor)
            restriction.restriction_type = PageViewRestriction.PASSWORD
            restriction.save(user=self.administrator)
            restriction.delete()

    def test_page_history(self):
        self._update_page(self.hello_page)

        history_url = reverse(
            "wagtailadmin_pages:history", kwargs={"page_id": self.hello_page.id}
        )

        self.login(user=self.editor)

        response = self.client.get(history_url)
        self.assertEqual(response.status_code, 200)

        self.assertContains(response, "Created", 1)
        self.assertContains(response, "Draft saved", 2)
        self.assertContains(response, "Locked", 1)
        self.assertContains(response, "Unlocked", 1)
        self.assertContains(response, "Page scheduled for publishing", 1)
        self.assertContains(response, "Published", 1)

        self.assertContains(
            response,
            "Added the &#x27;Private, accessible to logged-in users&#x27; view restriction",
        )
        self.assertContains(
            response,
            "Updated the view restriction to &#x27;Private, accessible with the following password&#x27;",
        )
        self.assertContains(
            response,
            "Removed the &#x27;Private, accessible with the following password&#x27; view restriction",
        )

        self.assertContains(
            response, "system", 2
        )  # create without a user + remove restriction
        self.assertContains(
            response, "the_editor", 9
        )  # 7 entries by editor + 1 in sidebar menu + 1 in filter
        self.assertContains(
            response, "administrator", 2
        )  # the final restriction change + filter

    def test_page_history_filters(self):
        self.login(user=self.editor)
        self._update_page(self.hello_page)

        history_url = reverse(
            "wagtailadmin_pages:history", kwargs={"page_id": self.hello_page.id}
        )
        response = self.client.get(history_url + "?action=wagtail.edit")
        self.assertEqual(response.status_code, 200)
        self.assertContains(response, "Draft saved", count=2)
        self.assertNotContains(response, "Locked")
        self.assertNotContains(response, "Unlocked")
        self.assertNotContains(response, "Page scheduled for publishing")
        self.assertNotContains(response, "Published")

    def test_site_history(self):
        self._update_page(self.hello_page)
        self.about_page.save_revision(user=self.administrator, log_action=True)
        self.about_page.delete(user=self.administrator)

        site_history_url = reverse("wagtailadmin_reports:site_history")

        # the editor has access to the root page, so should see everything
        self.login(user=self.editor)

        response = self.client.get(site_history_url)
        self.assertEqual(response.status_code, 200)

        self.assertNotContains(response, "About")
        self.assertContains(response, "Draft saved", 2)
        self.assertNotContains(response, "Deleted")

        # once a page is deleted, its log entries are only visible to super admins or users with
        # permissions on the root page
        self.hello_page.delete(user=self.administrator)
        response = self.client.get(site_history_url)
        self.assertContains(response, "No log entries found")

        # add the editor user to the Editors group which has permissions on the root page
        self.editor.groups.add(Group.objects.get(name="Editors"))
        response = self.client.get(site_history_url)

        self.assertContains(response, "About", 3)  # create, save draft, delete
        self.assertContains(response, "Created", 2)
        self.assertContains(response, "Deleted", 2)

        # check with super admin
        self.login(user=self.administrator)
        response = self.client.get(site_history_url)

        self.assertContains(response, "About", 3)  # create, save draft, delete
        self.assertContains(response, "Deleted", 2)

    def test_history_with_deleted_user(self):
        self._update_page(self.hello_page)

        expected_deleted_string = f"user {self.editor.pk} (deleted)"
        self.editor.delete()

        self.login(user=self.administrator)

        # check page history
        response = self.client.get(
            reverse(
                "wagtailadmin_pages:history", kwargs={"page_id": self.hello_page.id}
            )
        )
        self.assertContains(response, expected_deleted_string)

        # check site history
        response = self.client.get(reverse("wagtailadmin_reports:site_history"))
        self.assertContains(response, expected_deleted_string)

    def test_edit_form_has_history_link(self):
        self.hello_page.save_revision()
        self.login(user=self.editor)
        response = self.client.get(
            reverse("wagtailadmin_pages:edit", args=[self.hello_page.id])
        )
        self.assertEqual(response.status_code, 200)
        history_url = reverse("wagtailadmin_pages:history", args=[self.hello_page.id])
        self.assertContains(response, history_url)

    def test_create_and_publish_does_not_log_revision_save(self):
        self.login(user=self.administrator)
        post_data = {
            "title": "New page!",
            "content": "Some content",
            "slug": "hello-world-redux",
            "action-publish": "action-publish",
        }
        response = self.client.post(
            reverse(
                "wagtailadmin_pages:add",
                args=("tests", "simplepage", self.root_page.id),
            ),
            post_data,
            follow=True,
        )
        self.assertEqual(response.status_code, 200)

        page_id = Page.objects.get(
            path__startswith=self.root_page.path, slug="hello-world-redux"
        ).id

        self.assertListEqual(
            list(
                PageLogEntry.objects.filter(page=page_id).values_list(
                    "action", flat=True
                )
            ),
            ["wagtail.publish", "wagtail.create"],
        )

    def test_revert_and_publish_logs_reversion_and_publish(self):
        revision = self.hello_page.save_revision(user=self.editor)
        self.hello_page.save_revision(user=self.editor)

        self.login(user=self.administrator)
        response = self.client.post(
            reverse("wagtailadmin_pages:edit", args=(self.hello_page.id,)),
            {
                "title": "Hello World!",
                "content": "another hello",
                "slug": "hello-world",
                "revision": revision.id,
                "action-publish": "action-publish",
            },
            follow=True,
        )
        self.assertEqual(response.status_code, 200)

        entries = PageLogEntry.objects.filter(page=self.hello_page).values_list(
            "action", flat=True
        )
        self.assertListEqual(
            list(entries),
            ["wagtail.publish", "wagtail.rename", "wagtail.revert", "wagtail.create"],
        )
Exemplo n.º 14
0
class TestModerationList(TestCase, WagtailTestUtils):
    """Test moderation list rendered by `wagtailadmin_home` view"""
    def setUp(self):
        # Create a submitter
        submitter = self.create_user(
            username="******",
            email="*****@*****.**",
            password="******",
        )

        # Find root page
        self.root_page = Page.objects.get(id=2)

        # Create a page
        self.page = SimplePage(
            title="Wagtail, the powerful CMS for modern websites",
            slug="wagtail",
            content="Fast, elegant, open source",
        )

        self.root_page.add_child(instance=self.page)

        # Submit it for moderation
        self.page.save_revision(user=submitter, submitted_for_moderation=True)

        # Create a revision
        self.revision = self.page.get_latest_revision()

        self.edit_page_url = reverse("wagtailadmin_pages:edit",
                                     args=(self.revision.page.id, ))
        self.preview_page_url = reverse(
            "wagtailadmin_pages:preview_for_moderation",
            args=(self.revision.id, ))

    def login_as_moderator_without_edit(self):
        # Create moderators group without edit permissions
        moderators_group = Group.objects.create(name="Moderators without edit")

        admin_permission = Permission.objects.get(
            content_type__app_label="wagtailadmin", codename="access_admin")

        moderators_group.permissions.add(admin_permission)

        # Create group permissions
        GroupPagePermission.objects.create(
            group=moderators_group,
            page=self.root_page,
            permission_type="publish",
        )

        # Create a moderator without edit permissions
        moderator = self.create_user(username="******",
                                     email="*****@*****.**",
                                     password="******")

        moderator.groups.add(moderators_group)

        self.login(moderator)

    def get(self):
        return self.client.get(reverse("wagtailadmin_home"))

    def test_edit_page(self):
        # Login as moderator
        self.login()

        response = self.get()

        self.assertEqual(response.status_code, 200)
        self.assertTemplateUsed(response, "wagtailadmin/home.html")

        # Check response
        self.assertContains(response, self.edit_page_url, count=2)

        # page should contain Approve and Reject forms including a valid CSRF token
        self.assertRegex(
            response.content.decode("utf-8"),
            r'<input type="hidden" name="csrfmiddlewaretoken" value="\w+">',
        )

    def test_preview_for_moderation(self):
        # Login as moderator without edit permissions
        self.login_as_moderator_without_edit()

        response = self.get()

        self.assertEqual(response.status_code, 200)
        self.assertTemplateUsed(response, "wagtailadmin/home.html")

        # Check response
        self.assertContains(response, self.preview_page_url, count=2)
        self.assertNotContains(response, self.edit_page_url)