Merge pull request #166 from plone/moderation-extended

Extended Moderation of comments
This commit is contained in:
Maurits van Rees
2020-03-16 23:18:14 +01:00
committed by GitHub
23 changed files with 1196 additions and 931 deletions
@@ -112,7 +112,7 @@ Administrators can see all posts and comment actions
>>> 'form.button.DeleteComment' in browser.contents
True
>>> 'form.button.PublishComment' in browser.contents
>>> 'form.button.TransmitComment' in browser.contents
True
Anonymous user can not see any posts or comment actions
@@ -128,7 +128,7 @@ Anonymous user can not see any posts or comment actions
>>> 'form.button.DeleteComment' in unprivileged_browser.contents
False
>>> 'form.button.PublishComment' in unprivileged_browser.contents
>>> 'form.button.TransmitComment' in unprivileged_browser.contents
False
The catalog does not list the comments yet:
@@ -156,7 +156,7 @@ actions.
>>> 'form.button.DeleteComment' in browser.contents
True
>>> 'form.button.PublishComment' in browser.contents
>>> 'form.button.TransmitComment' in browser.contents
True
@@ -176,7 +176,7 @@ flaw? Though, the comment is published properly.
>>> browser.raiseHttpErrors = False
>>> browser.getControl('Approve', index=0).click()
>>> 'Comment approved' in browser.contents
>>> 'Comment published' in browser.contents
True
>>> browser.handleErrors = False
@@ -284,7 +284,7 @@ Open the edit comment view
Change and save the comment
>>> ctrl.value = 'Comment from admin / was edited'
>>> browser.getControl('Edit comment').click()
>>> browser.getControl('Save').click()
This used to trigger permissions problems in some portlet configurations.
Check it ain't so.
@@ -325,19 +325,19 @@ Deleting existing comments | 'Delete comments' permission
Anonymous cannot delete comments
>>> unprivileged_browser.open(urldoc1)
>>> 'form.button.Delete' in unprivileged_browser.contents
>>> 'form.button.DeleteComment' in unprivileged_browser.contents
False
A member cannot delete his own comments if he can't review or he isn't a Site Administrator
>>> browser_member.open(urldoc1)
>>> 'form.button.Delete' in browser_member.contents
>>> 'form.button.DeleteComment' in browser_member.contents
False
Admin can delete comments
>>> browser.open(urldoc1)
>>> 'form.button.Delete' in browser.contents
>>> 'form.button.DeleteComment' in browser.contents
True
Extract the delete comment url from the first "delete comment" button
@@ -0,0 +1,84 @@
*** Settings ***
Resource plone/app/robotframework/saucelabs.robot
Resource plone/app/robotframework/selenium.robot
Library Remote ${PLONE_URL}/RobotRemote
Test Setup Run Keywords Plone test setup
Test Teardown Run keywords Plone test teardown
*** Test Cases ***
Add a Comment to a Document and bulk delete it
Given a logged-in Site Administrator
and workflow multiple enabled
and a document with discussion enabled
When I add a comment and delete it
Then I can not see the comment below the document
Last history entry is shown
Given a logged-in Site Administrator
and workflow multiple enabled
and a document with discussion enabled
When I add a comment
Then I can see the last history entry in moderation view
*** Keywords ***
# Given
a logged-in Site Administrator
Enable autologin as Site Administrator
a document
Create content type=Document id=my-document title=My Document
a document with discussion enabled
a document
I enable discussion on the document
# When
I enable discussion on the document
Go To ${PLONE_URL}/my-document/edit
Wait until page contains Settings
Click Link Settings
Wait until element is visible name=form.widgets.IAllowDiscussion.allow_discussion:list
Select From List name=form.widgets.IAllowDiscussion.allow_discussion:list True
Click Button Save
I add a comment
Wait until page contains element id=form-widgets-comment-text
Input Text id=form-widgets-comment-text This is a comment
Click Button Comment
I add a comment and delete it
Wait until page contains element id=form-widgets-comment-text
Input Text id=form-widgets-comment-text This is a comment
Click Button Comment
Go To ${PLONE_URL}/@@moderate-comments?review_state=all
Wait until page contains element name=form.select.BulkAction
Select from list by value xpath://select[@name='form.select.BulkAction'] delete
Select Checkbox name=check_all
Click Button Apply
Wait Until Page Does Not Contain This is a comment
workflow multiple enabled
Go To ${PLONE_URL}/@@content-controlpanel?type_id=Discussion%20Item&new_workflow=comment_review_workflow
Click Button Save
# Then
I can not see the comment below the document
Go To ${PLONE_URL}/my-document/view
Wait until page contains My Document
Page should not contain This is a comment
I can see the last history entry in moderation view
Go To ${PLONE_URL}/@@moderate-comments?review_state=all
Wait until page contains element name=form.select.BulkAction
Page should contain Create
@@ -599,10 +599,10 @@ class TestCommentsViewlet(unittest.TestCase):
self.assertTrue('actions' in reply)
self.assertEqual(
reply['actions'][0]['id'],
'publish',
'mark_as_spam',
)
expected_url = 'http://nohost/plone/doc1/++conversation++default/{0}' \
'/content_status_modify?workflow_action=publish'
'/content_status_modify?workflow_action=mark_as_spam'
self.assertEqual(
reply['actions'][0]['url'],
expected_url.format(int(c1)),
@@ -0,0 +1,124 @@
# -*- coding: utf-8 -*-
from plone.app.discussion.browser.moderation import BulkActionsView
from plone.app.discussion.browser.moderation import DeleteComment
from plone.app.discussion.browser.moderation import CommentTransition
from plone.app.discussion.browser.moderation import View
from plone.app.discussion.interfaces import IConversation
from plone.app.discussion.interfaces import IDiscussionSettings
from plone.app.discussion.testing import PLONE_APP_DISCUSSION_INTEGRATION_TESTING # noqa
from plone.app.testing import setRoles
from plone.app.testing import TEST_USER_ID
from plone.registry.interfaces import IRegistry
from Products.CMFCore.utils import getToolByName
from zope.component import createObject
from zope.component import queryUtility
import unittest
class ModerationBulkActionsViewTest(unittest.TestCase):
layer = PLONE_APP_DISCUSSION_INTEGRATION_TESTING
def setUp(self):
self.app = self.layer['app']
self.portal = self.layer['portal']
self.request = self.layer['request']
setRoles(self.portal, TEST_USER_ID, ['Manager'])
self.wf = getToolByName(self.portal,
'portal_workflow',
None)
self.context = self.portal
self.portal.portal_workflow.setChainForPortalTypes(
('Discussion Item',),
'comment_review_workflow',
)
self.wf_tool = self.portal.portal_workflow
# Add a conversation with three comments
conversation = IConversation(self.portal.doc1)
comment1 = createObject('plone.Comment')
comment1.title = 'Comment 1'
comment1.text = 'Comment text'
comment1.Creator = 'Jim'
new_id_1 = conversation.addComment(comment1)
self.comment1 = self.portal.doc1.restrictedTraverse(
'++conversation++default/{0}'.format(new_id_1),
)
comment2 = createObject('plone.Comment')
comment2.title = 'Comment 2'
comment2.text = 'Comment text'
comment2.Creator = 'Joe'
new_id_2 = conversation.addComment(comment2)
self.comment2 = self.portal.doc1.restrictedTraverse(
'++conversation++default/{0}'.format(new_id_2),
)
comment3 = createObject('plone.Comment')
comment3.title = 'Comment 3'
comment3.text = 'Comment text'
comment3.Creator = 'Emma'
new_id_3 = conversation.addComment(comment3)
self.comment3 = self.portal.doc1.restrictedTraverse(
'++conversation++default/{0}'.format(new_id_3),
)
self.conversation = conversation
def test_default_bulkaction(self):
# Make sure no error is raised when no bulk actions has been supplied
self.request.set('form.select.BulkAction', '-1')
self.request.set('paths', ['/'.join(self.comment1.getPhysicalPath())])
view = BulkActionsView(self.portal, self.request)
self.assertFalse(view())
def test_publish(self):
self.request.set('form.select.BulkAction', 'publish')
self.request.set('paths', ['/'.join(self.comment1.getPhysicalPath())])
view = BulkActionsView(self.portal, self.request)
view()
# Count published comments
published_comments = 0
for r in self.conversation.getThreads():
comment_obj = r['comment']
workflow_status = self.wf.getInfoFor(comment_obj, 'review_state')
if workflow_status == 'published':
published_comments += 1
# Make sure the comment has been published
self.assertEqual(published_comments, 1)
def test_mark_as_spam(self):
self.request.set('form.select.BulkAction', 'mark_as_spam')
self.request.set('paths', ['/'.join(self.comment1.getPhysicalPath())])
view = BulkActionsView(self.portal, self.request)
view()
# Count spam comments
spam_comments = 0
for r in self.conversation.getThreads():
comment_obj = r['comment']
workflow_status = self.wf.getInfoFor(comment_obj, 'review_state')
if workflow_status == 'spam':
spam_comments += 1
# Make sure the comment has been marked as spam
self.assertEqual(spam_comments, 1)
def test_delete(self):
# Initially we have three comments
self.assertEqual(len(self.conversation.objectIds()), 3)
# Delete two comments with bulk actions
self.request.set('form.select.BulkAction', 'delete')
self.request.set('paths', ['/'.join(self.comment1.getPhysicalPath()),
'/'.join(self.comment3.getPhysicalPath())])
view = BulkActionsView(self.app, self.request)
view()
# Make sure that the two comments have been deleted
self.assertEqual(len(self.conversation.objectIds()), 1)
comment = next(self.conversation.getComments())
self.assertTrue(comment)
self.assertEqual(comment, self.comment2)
@@ -1,7 +1,7 @@
# -*- coding: utf-8 -*-
from plone.app.discussion.browser.moderation import BulkActionsView
from plone.app.discussion.browser.moderation import DeleteComment
from plone.app.discussion.browser.moderation import PublishComment
from plone.app.discussion.browser.moderation import CommentTransition
from plone.app.discussion.browser.moderation import View
from plone.app.discussion.interfaces import IConversation
from plone.app.discussion.interfaces import IDiscussionSettings
@@ -110,14 +110,6 @@ class ModerationBulkActionsViewTest(unittest.TestCase):
self.assertFalse(view())
def test_retract(self):
self.request.set('form.select.BulkAction', 'retract')
self.request.set('paths', ['/'.join(self.comment1.getPhysicalPath())])
view = BulkActionsView(self.portal, self.request)
self.assertRaises(NotImplementedError, view)
def test_publish(self):
self.request.set('form.select.BulkAction', 'publish')
self.request.set('paths', ['/'.join(self.comment1.getPhysicalPath())])
@@ -135,15 +127,6 @@ class ModerationBulkActionsViewTest(unittest.TestCase):
# Make sure the comment has been published
self.assertEqual(published_comments, 1)
def test_mark_as_spam(self):
self.request.set('form.select.BulkAction', 'mark_as_spam')
self.request.set('paths', ['/'.join(self.comment1.getPhysicalPath())])
view = BulkActionsView(self.portal, self.request)
self.assertRaises(NotImplementedError,
view)
def test_delete(self):
# Initially we have three comments
self.assertEqual(len(self.conversation.objectIds()), 3)
@@ -195,14 +178,14 @@ class RedirectionTest(unittest.TestCase):
def test_regression(self):
page_url = self.page.absolute_url()
self.request['HTTP_REFERER'] = page_url
for Klass in (DeleteComment, PublishComment):
for Klass in (DeleteComment, CommentTransition):
view = Klass(self.comment, self.request)
view.__parent__ = self.comment
self.assertEqual(page_url, view())
def test_valid_next_url(self):
self.request['HTTP_REFERER'] = 'http://attacker.com'
for Klass in (DeleteComment, PublishComment):
for Klass in (DeleteComment, CommentTransition):
view = Klass(self.comment, self.request)
view.__parent__ = self.comment
self.assertNotEqual('http://attacker.com', view())
+2 -2
View File
@@ -272,7 +272,7 @@ class CommentReviewWorkflowTest(unittest.TestCase):
'review_state',
),
)
view = self.comment.restrictedTraverse('@@moderate-publish-comment')
view = self.comment.restrictedTraverse('@@transmit-comment')
view()
self.assertEqual(
'published',
@@ -295,7 +295,7 @@ class CommentReviewWorkflowTest(unittest.TestCase):
self.assertRaises(
Unauthorized,
self.comment.restrictedTraverse,
'@@moderate-publish-comment',
'@@transmit-comment',
)
self.assertEqual(
'pending',