diff --git a/plone/app/discussion/tests/functional_test_comment_review_workflow.txt b/plone/app/discussion/tests/functional_test_comment_review_workflow.txt new file mode 100644 index 0000000..324cbb5 --- /dev/null +++ b/plone/app/discussion/tests/functional_test_comment_review_workflow.txt @@ -0,0 +1,205 @@ +========================= + Comment Review Workflow +========================= + +This is a functional test for the comment review workflow. + +We use zope.testbrowser to simulate browser interaction in order to show +how this works. + +This test does not include test of the moderation control panel because it +heavly relies on Javascript (which zope.testbrowser can't test). + + +Setting up and logging in +------------------------- + +First we have to set up some things and login. + + >>> app = layer['app'] + >>> from plone.testing.z2 import Browser + >>> browser = Browser(app) + >>> browser.handleErrors = False + >>> browser.addHeader('Authorization', 'Basic admin:secret') + >>> portal = layer['portal'] + >>> portal_url = 'http://nohost/plone' + +By default, only HTTP error codes (e.g. 500 Server Side Error) are shown when an +error occurs on the server. To see more details, set handleErrors to False: + + >>> browser.handleErrors = False + +We also keep another testbrowser handy for testing how tiles are rendered if +you're not logged in:: + + >>> unprivileged_browser = Browser(app) + + +Enable comment review workflow +------------------------------ + +Enable the 'comment review workflow' for comments. + + >>> portal.portal_workflow.setChainForPortalTypes(('Discussion Item',), ('comment_review_workflow'),) + >>> portal.portal_workflow.getChainForPortalType('Discussion Item') + ('comment_review_workflow',) + +We need to commit the transaction, otherwise setting the workflow will not work. + + >>> import transaction + >>> transaction.commit() + +Enable anonymous comments + + >>> browser.open(portal_url+'/@@discussion-settings') + >>> browser.getControl(name='form.widgets.anonymous_comments:list').value = [True] + >>> browser.getControl(name='form.buttons.save').click() + +Create a public page with comments allowed. + + >>> browser.open(portal_url) + >>> browser.getLink(id='document').click() + >>> browser.getControl(name='title').value = "Doc" + >>> browser.getControl(name='allowDiscussion:boolean').value = True + >>> browser.getControl(name='form.button.save').click() + >>> urldoc = browser.url + +Check that the form has been properly submitted + + >>> browser.url + 'http://nohost/plone/doc' + +Post some comments as anonymous user: + + >>> unprivileged_browser.open(urldoc) + >>> unprivileged_browser.getControl(name='form.widgets.text').value = "First anonymous comment" + >>> unprivileged_browser.getControl(name='form.buttons.comment').click() + >>> unprivileged_browser.getControl(name='form.widgets.text').value = "Second anonymous comment" + >>> unprivileged_browser.getControl(name='form.buttons.comment').click() + +Make sure the user gets a notification that the comment awaits moderator +approval. + + >>> 'Your comment awaits moderator approval' in unprivileged_browser.contents + True + +Administrators can see all posts and comment actions + + >>> browser.open(urldoc) + + >>> 'Moderate comments' in browser.contents + True + + >>> 'First anonymous comment' in browser.contents + True + + >>> 'form.button.DeleteComment' in browser.contents + True + + >>> 'form.button.PublishComment' in browser.contents + True + +Anonymous user can not see any posts or comment actions + + >>> unprivileged_browser.open(urldoc) + + >>> 'Moderate comments' in unprivileged_browser.contents + False + + >>> 'First anonymous comment' in unprivileged_browser.contents + False + + >>> 'form.button.DeleteComment' in unprivileged_browser.contents + False + + >>> 'form.button.PublishComment' in unprivileged_browser.contents + False + +Users with 'Review comment' permission can see unapproved comments and comment +actions. + + >>> browser.open(portal_url + '/logout') + >>> browser.open(portal_url + '/login_form') + >>> browser.getControl(name='__ac_name').value = 'jack' + >>> browser.getControl(name='__ac_password').value = 'secret' + >>> browser.getControl(name='submit').click() + + >>> browser.open(urldoc) + + >>> 'Moderate comments' in browser.contents + True + + >>> 'First anonymous comment' in browser.contents + True + + >>> 'form.button.DeleteComment' in browser.contents + True + + >>> 'form.button.PublishComment' in browser.contents + True + + +Publish a comment in the comments view +-------------------------------------- + +Publish the first anonymous comment in the main comments view. The publish call +on the comment currently raises an 404 error, because of a zope.testbrowser +flaw? Though, the comment is published properly. + + >>> browser.open(urldoc) + >>> 'First anonymous comment' in unprivileged_browser.contents + False + + >>> browser.open(urldoc) + >>> browser.handleErrors = True + >>> browser.raiseHttpErrors = False + >>> browser.getControl('Approve', index=0).click() + Traceback (most recent call last): + ... + HTTPError: HTTP Error 404: Not Found + + >>> 'Comment approved' in browser.contents + True + + >>> browser.handleErrors = False + >>> browser.raiseHttpErrors = True + +Make sure anonyous users see the approved comment, but not the unapproved ones. + + >>> unprivileged_browser.open(urldoc) + >>> 'First anonymous comment' in unprivileged_browser.contents + True + + +Delete a comment in the comments view +------------------------------------- + +Delete the second anonymous comment in the main comments view. The delete call +on the comment currently raises an 404 error, because of a zope.testbrowser +flaw? Though, the comment is deleted properly. + + >>> browser.open(urldoc) + >>> 'Second anonymous comment' in browser.contents + True + + >>> browser.open(urldoc) + >>> browser.handleErrors = True + >>> browser.raiseHttpErrors = False + >>> browser.getControl('Delete', index=1).click() + Traceback (most recent call last): + ... + HTTPError: HTTP Error 404: Not Found + + >>> browser.handleErrors = False + >>> browser.raiseHttpErrors = True + + >>> 'Comment deleted' in browser.contents + True + +Make sure the second comment has been deleted. + + >>> browser.open(urldoc) + >>> 'Second anonymous comment' in browser.contents + False + + \ No newline at end of file diff --git a/plone/app/discussion/tests/functional_test_comments.txt b/plone/app/discussion/tests/functional_test_comments.txt new file mode 100644 index 0000000..cefb046 --- /dev/null +++ b/plone/app/discussion/tests/functional_test_comments.txt @@ -0,0 +1,267 @@ +====================== + plone.app.discussion +====================== + +This is a functional test for the plone.app.discussion comments viewlet. + +We use zope.testbrowser to simulate browser interaction in order to show how +the plone.app.discussion commenting works. + + +Setting up and logging in +------------------------- + +First we have to set up some things and login. + + >>> app = layer['app'] + >>> from plone.testing.z2 import Browser + >>> browser = Browser(app) + >>> browser.handleErrors = False + >>> browser.addHeader('Authorization', 'Basic admin:secret') + >>> portal = layer['portal'] + >>> portal_url = 'http://nohost/plone' + +By default, only HTTP error codes (e.g. 500 Server Side Error) are shown when an +error occurs on the server. To see more details, set handleErrors to False: + + >>> browser.handleErrors = False + +We also keep another testbrowser handy for testing how tiles are rendered if +you're not logged in:: + + >>> unprivileged_browser = Browser(app) + +Add a test user + + >>> from Products.CMFCore.utils import getToolByName + >>> mtool = getToolByName(portal, 'portal_membership', None) + >>> mtool.addMember('jim', 'Jim', ['Member'], []) + >>> mtool.getMemberById('jim').setMemberProperties({"fullname": 'Jim Fulton'}) + +Create a public page with comments allowed. + + >>> browser.open(portal_url) + >>> browser.getLink(id='document').click() + >>> browser.getControl(name='title').value = "Doc1" + >>> browser.getControl(name='allowDiscussion:boolean').value = True + >>> browser.getControl(name='form.button.save').click() + >>> urldoc1 = browser.url + +Check that the form has been properly submitted + + >>> browser.url + 'http://nohost/plone/doc1' + + +Comment Viewlet +--------------- + +Check that the old comments viewlet does not show up + + >>> 'discussion_reply_form' in browser.contents + False + +Check that the comment form/viewlet shows up + + >>> 'formfield-form-widgets-in_reply_to' in browser.contents + True + + >>> 'formfield-form-widgets-text' in browser.contents + True + + +Post a comment as admin +----------------------- + +Login as admin. + + >>> from plone.app.testing import setRoles + >>> from plone.app.testing import TEST_USER_NAME + >>> setRoles(portal, TEST_USER_NAME, ['Manager']) + +Post a comment as admin. + + >>> browser.getControl(name='form.widgets.text').value = "Comment from admin" + >>> submit = browser.getControl(name='form.buttons.comment') + >>> submit.click() + +Check if comment has been added properly. + + >>> 'admin' in browser.contents + True + + >>> browser.contents + '...admin...says:...' + + >>> "Comment from admin" in browser.contents + True + + +Post a comment as user +---------------------- + +Login as user 'jim'. + + >>> browser.open(portal_url + '/logout') + >>> browser.open(portal_url + '/login_form') + >>> browser.getControl(name='__ac_name').value = 'jim' + >>> browser.getControl(name='__ac_password').value = 'secret' + >>> browser.getControl(name='submit').click() + +Post a comment as user jim. + + >>> browser.open(urldoc1) + >>> browser.getControl(name='form.widgets.text').value = "Comment from Jim" + >>> submit = browser.getControl(name='form.buttons.comment') + >>> submit.click() + +Check if the comment has been added properly. + + >>> browser.contents + '...Jim Fulton...says:...' + + >>> "Comment from Jim" in browser.contents + True + + +Post a comment as anonymous user +-------------------------------- + +Login and post comment as Anonymous + + >>> unprivileged_browser.open(urldoc1) + + >>> 'Log in to add comments' in unprivileged_browser.contents + True + +Enable anonymous comment + + >>> browser.open(portal_url + '/logout') + >>> browser.open(portal_url + '/login_form') + >>> browser.getControl(name='__ac_name').value = 'admin' + >>> browser.getControl(name='__ac_password').value = 'secret' + >>> browser.getControl(name='submit').click() + >>> browser.open(portal_url+'/@@discussion-settings') + >>> browser.getControl(name='form.widgets.anonymous_comments:list').value = [True] + >>> browser.getControl(name='form.buttons.save').click() + >>> browser.open(portal_url + '/logout') + +Now we can post an anonymous comment. + + >>> unprivileged_browser.open(urldoc1) + >>> unprivileged_browser.getControl(name='form.widgets.text').value = "This is an anonymous comment" + >>> unprivileged_browser.getControl(name='form.buttons.comment').click() + + >>> 'Anonymous' in unprivileged_browser.contents + True + + >>> 'says' in unprivileged_browser.contents + True + + >>> 'This is an anonymous comment' in unprivileged_browser.contents + True + +Make sure special characters work as well. + + >>> unprivileged_browser.open(urldoc1) + >>> unprivileged_browser.getControl(name='form.widgets.author_name').value = "Tarek Ziadé" + >>> unprivileged_browser.getControl(name='form.widgets.text').value = "This is an äüö comment" + >>> unprivileged_browser.getControl(name='form.buttons.comment').click() + + >>> 'Tarek Ziadé' in unprivileged_browser.contents + True + + >>> 'says' in unprivileged_browser.contents + True + + >>> 'This is an äüö comment' in unprivileged_browser.contents + True + + +Reply to an existing comment +---------------------------- + +Check that there is no existing direct reply to a comment. + + >>> 'replyTreeLevel1' in browser.contents + False + +Find a comment id to reply to. + + >>> browser.open(urldoc1) + >>> import re + >>> comment_div = re.findall('', browser.contents)[0] + >>> id = re.findall('"([^"]*)"', comment_div)[2] + +Post a reply to an existing comment. + + >>> browser.getControl(name='form.widgets.in_reply_to').value = id + >>> browser.getControl(name='form.widgets.text').value = "Reply comment" + >>> browser.getControl(name='form.buttons.comment').click() + +Check that the reply has been posted properly. + + >>> 'Reply comment' in browser.contents + True + + >>> 'replyTreeLevel1' in browser.contents + True + + +Post a comment with comment review workflow enabled +--------------------------------------------------- + +Enable the 'comment review workflow' for comments. + + >>> portal.portal_workflow.setChainForPortalTypes(('Discussion Item',), ('comment_review_workflow'),) + >>> portal.portal_workflow.getChainForPortalType('Discussion Item') + ('comment_review_workflow',) + +We need to commit the transaction, otherwise setting the workflow will not work. + + >>> import transaction + >>> transaction.commit() + +Post comment as anonymous user. + + >>> unprivileged_browser.open(urldoc1) + >>> unprivileged_browser.getControl(name='form.widgets.text').value = "Comment review workflow comment" + >>> unprivileged_browser.getControl(name='form.buttons.comment').click() + +Make sure the comment has not been published. + + >>> 'Comment review workflow comment' not in unprivileged_browser.contents + True + +Make sure the user gets a notification that the comment awaits moderator +approval. + + >>> 'Your comment awaits moderator approval' in unprivileged_browser.contents + True + + +Regression Test +--------------- + +Make sure we still can edit the content object after a comment has been posted. +This is a regression test for http://dev.plone.org/plone/ticket/11157 +(TypeError: Can't pickle objects in acquisition wrappers). + +Login as admin. + + >>> browser.open(portal_url + '/logout') + >>> browser.open(portal_url + '/login_form') + >>> browser.getControl(name='__ac_name').value = 'admin' + >>> browser.getControl(name='__ac_password').value = 'secret' + >>> browser.getControl(name='submit').click() + +Edit the content object. + + >>> browser.open(urldoc1 + "/edit") + >>> browser.getControl(name='text').value = "Lorem ipsum" + >>> browser.getControl(name='form.button.save').click() + +Make sure the edit was successful. + + >>> 'Lorem ipsum' in browser.contents + True diff --git a/plone/app/discussion/tests/test_functional.py b/plone/app/discussion/tests/test_functional.py index ed21ba4..6c1a17b 100644 --- a/plone/app/discussion/tests/test_functional.py +++ b/plone/app/discussion/tests/test_functional.py @@ -10,7 +10,8 @@ from plone.app.discussion.testing import \ optionflags = (doctest.ELLIPSIS | doctest.NORMALIZE_WHITESPACE | doctest.REPORT_ONLY_FIRST_FAILURE) normal_testfiles = [ - 'functional.txt', + 'functional_test_comments.txt', + 'functional_test_comment_review_workflow.txt' ] def test_suite():