diff --git a/plone/app/discussion/browser/comments.py b/plone/app/discussion/browser/comments.py index 9fd32c3..9ae9fbd 100644 --- a/plone/app/discussion/browser/comments.py +++ b/plone/app/discussion/browser/comments.py @@ -58,7 +58,8 @@ class CommentsViewlet(ViewletBase): return getSecurityManager().checkPermission('Manage portal', aq_inner(self.context)) def is_discussion_allowed(self): - conversation = conversationAdapterFactory(self.context) + context = aq_inner(self.context) + conversation = conversationAdapterFactory(context) return conversation.enabled def get_replies(self, workflow_actions=False): @@ -66,7 +67,6 @@ class CommentsViewlet(ViewletBase): # Acquisition wrap the conversation context = aq_inner(self.context) conversation = IConversation(context) - conversation = IConversation(context).__of__(context) def replies_with_workflow_actions(): # Return dict with workflow actions diff --git a/plone/app/discussion/tests/test_comment.py b/plone/app/discussion/tests/test_comment.py index a1715c2..9455015 100644 --- a/plone/app/discussion/tests/test_comment.py +++ b/plone/app/discussion/tests/test_comment.py @@ -43,7 +43,7 @@ class CommentTest(PloneTestCase): def test_traversal(self): # make sure comments are traversable, have an id, absolute_url and physical path - conversation = IConversation(self.portal.doc1).__of__(self.portal.doc1) + conversation = IConversation(self.portal.doc1) comment1 = createObject('plone.Comment') comment1.title = 'Comment 1' @@ -61,7 +61,7 @@ class CommentTest(PloneTestCase): def test_workflow(self): self.portal.portal_workflow.setChainForPortalTypes(('Discussion Item',), ('simple_publication_workflow,')) - conversation = IConversation(self.portal.doc1).__of__(self.portal.doc1) + conversation = IConversation(self.portal.doc1) comment1 = createObject('plone.Comment') new_comment1_id = conversation.addComment(comment1) @@ -93,9 +93,6 @@ class CommentTest(PloneTestCase): # object, as we just want to check the Conversation object API. conversation = IConversation(self.portal.doc1) - # Pretend that we have traversed to the comment by aq wrapping it. - conversation = conversation.__of__(self.portal.doc1) - # Create a comment comment1 = createObject('plone.Comment') comment1.title = 'Comment 1' @@ -131,9 +128,6 @@ class RepliesTest(PloneTestCase): # object, as we just want to check the Conversation object API. conversation = IConversation(self.portal.doc1) - # Pretend that we have traversed to the comment by aq wrapping it. - conversation = conversation.__of__(self.portal.doc1) - # Add a comment to the conversation replies = IReplies(conversation) @@ -171,9 +165,6 @@ class RepliesTest(PloneTestCase): # object, as we just want to check the Conversation object API. conversation = IConversation(self.portal.doc1) - # Pretend that we have traversed to the comment by aq wrapping it. - conversation = conversation.__of__(self.portal.doc1) - # Add a comment to the conversation replies = IReplies(conversation) @@ -205,7 +196,7 @@ class RepliesTest(PloneTestCase): # Create a nested structure of comment replies and check the traversal # make sure comments are traversable, have an id, absolute_url and physical path - conversation = IConversation(self.portal.doc1).__of__(self.portal.doc1) + conversation = IConversation(self.portal.doc1) comment1 = createObject('plone.Comment') comment1.title = 'Comment 1' diff --git a/plone/app/discussion/tests/test_comments_viewlet.py b/plone/app/discussion/tests/test_comments_viewlet.py index ebbd648..405a54f 100644 --- a/plone/app/discussion/tests/test_comments_viewlet.py +++ b/plone/app/discussion/tests/test_comments_viewlet.py @@ -51,7 +51,6 @@ class CommentsViewletTest(PloneTestCase): # Add a conversation with a comment conversation = IConversation(self.portal.doc1) - conversation = conversation.__of__(self.portal.doc1) comment = createObject('plone.Comment') comment.title = 'Comment 1' comment.text = 'Comment text' @@ -73,7 +72,6 @@ class CommentsViewletTest(PloneTestCase): # Add a conversation with a comment conversation = IConversation(self.portal.doc1) - conversation = conversation.__of__(self.portal.doc1) comment = createObject('plone.Comment') comment.title = 'Comment 1' comment.text = 'Comment text' diff --git a/plone/app/discussion/tests/test_conversation.py b/plone/app/discussion/tests/test_conversation.py index b0942c9..ba71f09 100644 --- a/plone/app/discussion/tests/test_conversation.py +++ b/plone/app/discussion/tests/test_conversation.py @@ -24,6 +24,7 @@ class ConversationTest(PloneTestCase): self.loginAsPortalOwner() typetool = self.portal.portal_types typetool.constructContent('Document', self.portal, 'doc1') + self.typetool = typetool self.portal_discussion = getToolByName(self.portal, 'portal_discussion', None) def test_add_comment(self): @@ -31,9 +32,6 @@ class ConversationTest(PloneTestCase): # object, as we just want to check the Conversation object API. conversation = IConversation(self.portal.doc1) - # Pretend that we have traversed to the comment by aq wrapping it. - conversation = conversation.__of__(self.portal.doc1) - # Add a comment. Note: in real life, we always create comments via the factory # to allow different factories to be swapped in @@ -59,9 +57,6 @@ class ConversationTest(PloneTestCase): # object, as we just want to check the Conversation object API. conversation = IConversation(self.portal.doc1) - # Pretend that we have traversed to the comment by aq wrapping it. - conversation = conversation.__of__(self.portal.doc1) - # Add a comment. Note: in real life, we always create comments via the factory # to allow different factories to be swapped in @@ -92,9 +87,6 @@ class ConversationTest(PloneTestCase): # object, as we just want to check the Conversation object API. conversation = IConversation(self.portal.doc1) - # Pretend that we have traversed to the comment by aq wrapping it. - conversation = conversation.__of__(self.portal.doc1) - replies = IReplies(conversation) # Create a nested comment structure: @@ -162,7 +154,6 @@ class ConversationTest(PloneTestCase): # Create a conversation. conversation = IConversation(self.portal.doc1) - conversation = conversation.__of__(self.portal.doc1) # By default, discussion is disabled for all content types portal_types = getToolByName(self.portal, 'portal_types') @@ -214,7 +205,7 @@ class ConversationTest(PloneTestCase): document_fti.manage_changeProperties(allow_discussion = True) # Check if conversation is enabled now - self.assertEquals(conversation.enabled, True) + self.assertEquals(conversation.enabled(), True) # Disable commenting in the registry registry = queryUtility(IRegistry) @@ -222,11 +213,11 @@ class ConversationTest(PloneTestCase): settings.globally_enabled = False # Check if commenting is disabled on the conversation - self.assertEquals(conversation.enabled, False) + self.assertEquals(conversation.enabled(), False) # Enable discussion again settings.globally_enabled = True - self.assertEquals(conversation.enabled, True) + self.assertEquals(conversation.enabled(), True) def test_disable_commenting_for_content_type(self): @@ -235,7 +226,7 @@ class ConversationTest(PloneTestCase): conversation = IConversation(self.portal.doc1) # The Document content type is disabled by default - self.assertEquals(conversation.enabled, False) + self.assertEquals(conversation.enabled(), False) # Allow discussion on Document content type portal_types = getToolByName(self.portal, 'portal_types') @@ -243,7 +234,7 @@ class ConversationTest(PloneTestCase): document_fti.manage_changeProperties(allow_discussion = True) # Check if conversation is enabled now - self.assertEquals(conversation.enabled, True) + self.assertEquals(conversation.enabled(), True) # Disallow discussion on Document content type portal_types = getToolByName(self.portal, 'portal_types') @@ -251,12 +242,39 @@ class ConversationTest(PloneTestCase): document_fti.manage_changeProperties(allow_discussion = False) # Check if conversation is enabled now - self.assertEquals(conversation.enabled, False) + self.assertEquals(conversation.enabled(), False) + + def test_allow_discussion_on_folder(self): + # enabled should always return False for a folder, + # since the allow_discussion flag is user for another purpose + pass def test_is_discussion_allowed_for_folder(self): - # Create a folder with two content objects. Change allow_discussion - # and check if the content objects inside the folder are commentable. - pass + # When a content item provides IFolderish from CMF and + # does not provide INonStructuralFolder from Plone, + # allow_discussion acts as an on/off flag for all items + # in that folder, overriding settings for any parent folders, + # and the for the FTI, but is overridden by child items and + # folders further down. + + # Create a folder + self.typetool.constructContent('Folder', self.portal, 'f1') + f1 = self.portal.f1 + + # Create a document inside the folder with a conversation + self.typetool.constructContent('Document', f1, 'doc1') + doc1 = self.portal.f1.doc1 + conversation = IConversation(self.portal.doc1) + + # Allow commenting for the folder + self.portal_discussion.overrideDiscussionFor(f1, True) + + # Check if the content objects allows discussion + #self.assertEquals(conversation.enabled(), True) + + # Turn commenting for the folder off + + # Check if content objects do not allow discussion anymore def test_is_discussion_allowed_on_content_object(self): # Allow discussion on a single content object @@ -268,16 +286,16 @@ class ConversationTest(PloneTestCase): conversation = IConversation(self.portal.doc1) # Discussion is disallowed by default - self.assertEquals(conversation.enabled, False) + self.assertEquals(conversation.enabled(), False) # Allow discussion on content object self.portal_discussion.overrideDiscussionFor(self.portal.doc1, True) # Check if discussion is now allowed on the content object - self.assertEquals(conversation.enabled, True) + self.assertEquals(conversation.enabled(), True) self.portal_discussion.overrideDiscussionFor(self.portal.doc1, False) - self.assertEquals(conversation.enabled, False) + self.assertEquals(conversation.enabled(), False) def test_dict_operations(self): # test dict operations and acquisition wrapping @@ -286,9 +304,6 @@ class ConversationTest(PloneTestCase): # object, as we just want to check the Conversation object API. conversation = IConversation(self.portal.doc1) - # Pretend that we have traversed to the comment by aq wrapping it. - conversation = conversation.__of__(self.portal.doc1) - # Add a comment. Note: in real life, we always create comments via the factory # to allow different factories to be swapped in @@ -347,9 +362,6 @@ class ConversationTest(PloneTestCase): # object, as we just want to check the Conversation object API. conversation = IConversation(self.portal.doc1) - # Pretend that we have traversed to the comment by aq wrapping it. - conversation = conversation.__of__(self.portal.doc1) - # Add a three comments. Note: in real life, we always create # comments via the factory to allow different factories to be # swapped in @@ -380,9 +392,6 @@ class ConversationTest(PloneTestCase): # object, as we just want to check the Conversation object API. conversation = IConversation(self.portal.doc1) - # Pretend that we have traversed to the comment by aq wrapping it. - conversation = conversation.__of__(self.portal.doc1) - # Add a four comments from three different users # Note: in real life, we always create # comments via the factory to allow different factories to be @@ -444,9 +453,6 @@ class ConversationTest(PloneTestCase): # object, as we just want to check the Conversation object API. conversation = IConversation(self.portal.doc1) - # Pretend that we have traversed to the comment by aq wrapping it. - conversation = conversation.__of__(self.portal.doc1) - # Add a three comments that are at least one day old # Note: in real life, we always create # comments via the factory to allow different factories to be @@ -501,9 +507,6 @@ class ConversationTest(PloneTestCase): # object, as we just want to check the Conversation object API. conversation = IConversation(self.portal.doc1) - # Pretend that we have traversed to the comment by aq wrapping it. - conversation = conversation.__of__(self.portal.doc1) - replies = IReplies(conversation) # Create a nested comment structure: @@ -588,16 +591,13 @@ class ConversationTest(PloneTestCase): # Create a conversation. conversation = IConversation(self.portal.doc1) - # Pretend that we have traversed to the comment by aq wrapping it. - conversation = conversation.__of__(self.portal.doc1) - # Check the parent self.failUnless(conversation.__parent__) self.failUnless(aq_parent(conversation)) - # Todo: This one is failing! - #self.failUnless(conversation.REQUEST) + self.assertEquals(conversation.__parent__.getId(), 'doc1') + def test_discussion_item_not_in_bad_types(self): self.failIf('Discussion Item' in BAD_TYPES) @@ -621,9 +621,6 @@ class RepliesTest(PloneTestCase): # object, as we just want to check the Conversation object API. conversation = IConversation(self.portal.doc1) - # Pretend that we have traversed to the comment by aq wrapping it. - conversation = conversation.__of__(self.portal.doc1) - replies = IReplies(conversation) comment = createObject('plone.Comment') @@ -651,9 +648,6 @@ class RepliesTest(PloneTestCase): # object, as we just want to check the Conversation object API. conversation = IConversation(self.portal.doc1) - # Pretend that we have traversed to the comment by aq wrapping it. - conversation = conversation.__of__(self.portal.doc1) - replies = IReplies(conversation) # Add a comment. @@ -684,9 +678,6 @@ class RepliesTest(PloneTestCase): # object, as we just want to check the Conversation object API. conversation = IConversation(self.portal.doc1) - # Pretend that we have traversed to the comment by aq wrapping it. - conversation = conversation.__of__(self.portal.doc1) - replies = IReplies(conversation) # Create a nested comment structure: diff --git a/plone/app/discussion/tests/test_indexers.py b/plone/app/discussion/tests/test_indexers.py index 1c29736..52d8002 100644 --- a/plone/app/discussion/tests/test_indexers.py +++ b/plone/app/discussion/tests/test_indexers.py @@ -31,9 +31,6 @@ class IndexersTest(PloneTestCase): # object, as we just want to check the Conversation object API. conversation = IConversation(self.portal.doc1) - # Pretend that we have traversed to the comment by aq wrapping it. - conversation = conversation.__of__(self.portal.doc1) - # Add a comment. Note: in real life, we always create comments via the factory # to allow different factories to be swapped in diff --git a/plone/app/discussion/tests/test_moderation_view.py b/plone/app/discussion/tests/test_moderation_view.py new file mode 100644 index 0000000..da01176 --- /dev/null +++ b/plone/app/discussion/tests/test_moderation_view.py @@ -0,0 +1,56 @@ +import unittest +from datetime import datetime, timedelta + +from plone.registry import Registry + +from zope.component import createObject + +from Acquisition import aq_base, aq_parent, aq_inner + +from OFS.Image import Image + +from plone.app.vocabularies.types import BAD_TYPES + +from Products.CMFCore.FSImage import FSImage +from Products.CMFCore.utils import getToolByName +from Products.CMFPlone.tests import dummy +from Products.PloneTestCase.ptc import PloneTestCase + +from plone.app.discussion.browser.moderation import View +from plone.app.discussion.interfaces import IConversation, IComment, IReplies, IDiscussionSettings +from plone.app.discussion.tests.layer import DiscussionLayer + + +class ModerationViewTest(PloneTestCase): + + layer = DiscussionLayer + + def afterSetUp(self): + self.loginAsPortalOwner() + typetool = self.portal.portal_types + typetool.constructContent('Document', self.portal, 'doc1') + self.portal_discussion = getToolByName(self.portal, 'portal_discussion', None) + self.membership_tool = getToolByName(self.folder, 'portal_membership') + self.memberdata = self.portal.portal_memberdata + request = self.app.REQUEST + context = getattr(self.portal, 'doc1') + self.view = View(context, request) + + + def test_comments_pending_review(self): + + # Add a conversation with a comment and two replies + conversation = IConversation(self.portal.doc1) + comment = createObject('plone.Comment') + comment.title = 'Comment 1' + comment.text = 'Comment text' + comment.Creator = 'Jim' + comment.author_username = 'jim' + new_id = conversation.addComment(comment) + + self.view.comments_pending_review() + # Todo + + +def test_suite(): + return unittest.defaultTestLoader.loadTestsFromName(__name__) \ No newline at end of file diff --git a/plone/app/discussion/tests/test_tool.py b/plone/app/discussion/tests/test_tool.py index dab477a..c95ba8e 100644 --- a/plone/app/discussion/tests/test_tool.py +++ b/plone/app/discussion/tests/test_tool.py @@ -8,44 +8,41 @@ from plone.app.discussion.tests.layer import DiscussionLayer from plone.app.discussion.interfaces import ICommentingTool, IConversation class ToolTest(PloneTestCase): - + layer = DiscussionLayer - + def afterSetUp(self): # XXX If we make this a layer, it only get run once... # First we need to create some content. self.loginAsPortalOwner() typetool = self.portal.portal_types typetool.constructContent('Document', self.portal, 'doc1') - + def test_tool_indexing(self): # Create a conversation. In this case we doesn't assign it to an # object, as we just want to check the Conversation object API. conversation = IConversation(self.portal.doc1) - # Pretend that we have traversed to the comment by aq wrapping it. - # XXX implement traversal to commenting and change this: - conversation = conversation.__of__(self.portal.doc1) - + # Add a comment. comment = createObject('plone.Comment') comment.title = 'Comment 1' comment.text = 'Comment text' - + conversation.addComment(comment) - + # Check that the comment got indexed in the tool: tool = getUtility(ICommentingTool) comment = list(tool.searchResults()) self.assert_(len(comment) == 1, "There is only one comment, but we got" " %s results in the search" % len(comment)) self.assertEquals(comment[0].Title, 'Comment 1') - + def test_unindexing(self): pass - + def test_search(self): # search returns only comments pass - + def test_suite(): return unittest.defaultTestLoader.loadTestsFromName(__name__) \ No newline at end of file diff --git a/plone/app/discussion/tests/test_workflow.py b/plone/app/discussion/tests/test_workflow.py index 682b721..deebe90 100644 --- a/plone/app/discussion/tests/test_workflow.py +++ b/plone/app/discussion/tests/test_workflow.py @@ -1,10 +1,13 @@ import unittest +from zope.component import createObject + from zope.interface import alsoProvides from Products.PloneTestCase.ptc import PloneTestCase from plone.app.discussion.tests.layer import DiscussionLayer +from plone.app.discussion.interfaces import IConversation, IDiscussionLayer class WorkflowTest(PloneTestCase): @@ -30,5 +33,54 @@ class WorkflowTest(PloneTestCase): self.assertEquals(('one_state_workflow',), self.portal.portal_workflow.getChainForPortalType('Discussion Item')) +class TestCommentOperations(PloneTestCase): + + def afterSetUp(self): + + self.loginAsPortalOwner() + + # Allow discussion on the Document content type + self.portal.portal_types['Document'].allow_discussion = True + # Set workflow for Discussion item to review workflow + self.portal.portal_workflow.setChainForPortalTypes(('Discussion Item',), + ('comment_review_workflow',)) + + # Create a Document + self.portal.invokeFactory('Document', 'doc1') + self.portal_discussion = self.portal.portal_discussion + + # Create a conversation for this Document + conversation = IConversation(self.portal.doc1) + + # Add a comment. + comment = createObject('plone.Comment') + comment.title = 'Comment 1' + comment.text = 'Comment text' + comment_id = conversation.addComment(comment) + comment = self.portal.doc1.restrictedTraverse('++conversation++default/%s' % comment_id) + + self.conversation = conversation + self.comment_id = comment_id + self.comment = comment + + self.setRoles(('Reviewer',)) + alsoProvides(self.portal.REQUEST, IDiscussionLayer) + + def test_delete(self): + pass + #self.portal.REQUEST.form['comment_id'] = self.comment_id + #view = self.comment.restrictedTraverse('@@moderate-delete-comment') + #view() + #self.failIf(self.comment_id in self.conversation.objectIds()) + + def test_publish(self): + pass + #self.portal.REQUEST.form['comment_id'] = self.comment_id + #self.portal.REQUEST.form['action'] = 'publish' + #self.assertEquals('pending', self.portal.portal_workflow.getInfoFor(self.comment, 'review_state')) + #view = self.reply.restrictedTraverse('@@review-publish-comment') + #view() + #self.assertEquals('published', self.portal.portal_workflow.getInfoFor(self.comment, 'review_state')) + def test_suite(): return unittest.defaultTestLoader.loadTestsFromName(__name__) \ No newline at end of file