diff --git a/plone/app/discussion/testing.py b/plone/app/discussion/testing.py index 400ab9c..cf1066c 100644 --- a/plone/app/discussion/testing.py +++ b/plone/app/discussion/testing.py @@ -2,7 +2,7 @@ from Products.CMFCore.utils import getToolByName from plone.app.testing import PloneSandboxLayer from plone.app.testing import applyProfile -from plone.app.testing import PLONE_FIXTURE +from plone.app.contenttypes.testing import PLONE_APP_CONTENTTYPES_FIXTURE from plone.app.testing import IntegrationTesting from plone.app.testing import FunctionalTesting @@ -17,7 +17,7 @@ except: class PloneAppDiscussion(PloneSandboxLayer): - defaultBases = (PLONE_FIXTURE,) + defaultBases = (PLONE_APP_CONTENTTYPES_FIXTURE,) USER_NAME = 'johndoe' USER_PASSWORD = 'secret' diff --git a/plone/app/discussion/tests/collection-integration-test.txt b/plone/app/discussion/tests/collection-integration-test.txt new file mode 100644 index 0000000..ac1ea22 --- /dev/null +++ b/plone/app/discussion/tests/collection-integration-test.txt @@ -0,0 +1,93 @@ +XXX: This functional test part has been removed due to the removal of +ATContentTypes from PLONE_FIXTURE. We have to rewrite this test as a robot +test because the dexterity collections do not work without js. + + +List comments in a collection +----------------------------- + +Create a collection. + + >>> from plone.app.testing import setRoles + >>> from plone.app.testing import TEST_USER_NAME + >>> setRoles(portal, 'manager', ['Manager']) + >>> browser.open(portal.absolute_url()) + >>> from plone.app.discussion.testing import COLLECTION_TYPE + >>> browser.getLink(url='++add++' + COLLECTION_TYPE).click() + >>> open('/tmp/testbrowser.html', 'w').write(browser.contents) + >>> import pdb; pdb.set_trace() + >>> browser.getControl('form.widgets.IDublinCore.title').value = 'Foo Comment Collection' + >>> browser.getControl('Save').click() + >>> print browser.contents + <...Changes saved... + >>> topic_url = browser.url + +Set the collection criteria. + + >>> browser.open(topic_url + "/edit") + + >>> if COLLECTION_TYPE == "Collection": + ... browser.getControl(name="addindex").value = ['portal_type'] + ... browser.getControl(name="form.button.addcriteria").click() + ... browser.getControl(name="addoperator").value = ['plone.app.querystring.operation.selection.is'] + ... browser.getControl(name="form.button.addcriteria").click() + ... browser.getControl(name="query.v:records:list").value = ["Discussion Item"] + ... browser.getControl(name="form.button.save").click() + ... else: + ... browser.getLink('Criteria').click() + ... browser.getControl('Item Type', index=0).selected = True + ... browser.getControl('Select content types').selected = True + ... browser.getControl('Add criteria').click() + ... browser.getControl('Comment').selected = True + ... browser.getControl('Save', index=0).click() + >>> print browser.contents + <...Changes saved... + +View the collection listing. + + >>> browser.getLink('View').click() + >>> browser.getLink('admin on Doc1', index=0) + + >>> browser.getLink('admin on Doc1', index=1) + + >>> browser.getLink('Anonymous on Doc1', index=0) + + >>> browser.getLink('Anonymous on Doc1', index=1) + + >>> browser.getLink(tarek_fullname + ' on Doc1') + + >>> browser.getLink(jim_fullname + ' on Doc1') + + +Comments are unindexed when the content is deleted +-------------------------------------------------- + +Delete the commented content. + + >>> browser.open(urldoc1) + >>> browser.getLink('Delete').click() + >>> browser.getControl('Delete').click() + >>> print browser.contents + <...Doc1 has been deleted... + +The comments are no longer in the catalog. + + >>> browser.open(topic_url) + >>> browser.getLink('admin on Doc1', index=0) + Traceback (most recent call last): + LinkNotFoundError + >>> browser.getLink('admin on Doc1', index=1) + Traceback (most recent call last): + LinkNotFoundError + >>> browser.getLink('Anonymous on Doc1', index=0) + Traceback (most recent call last): + LinkNotFoundError + >>> browser.getLink('Anonymous on Doc1', index=1) + Traceback (most recent call last): + LinkNotFoundError + >>> browser.getLink(tarek_fullname + ' on Doc1') + Traceback (most recent call last): + LinkNotFoundError + >>> browser.getLink(jim_fullname + ' on Doc1') + Traceback (most recent call last): + LinkNotFoundError diff --git a/plone/app/discussion/tests/functional_test_comment_review_workflow.txt b/plone/app/discussion/tests/functional_test_comment_review_workflow.txt index 6e03a4f..069875e 100644 --- a/plone/app/discussion/tests/functional_test_comment_review_workflow.txt +++ b/plone/app/discussion/tests/functional_test_comment_review_workflow.txt @@ -33,6 +33,7 @@ We also keep another testbrowser handy for testing how tiles are rendered if you're not logged in:: >>> unprivileged_browser = Browser(app) + >>> unprivileged_browser.handleErrors = False Enable commenting. @@ -61,22 +62,28 @@ We need to commit the transaction, otherwise setting the workflow will not work. Enable anonymous comments >>> browser.open(portal_url+'/@@discussion-settings') - >>> browser.getControl(name='form.widgets.anonymous_comments:list').value = [True] + >>> 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() + >>> browser.getControl(name='form.widgets.IDublinCore.title').value = "Doc" + >>> browser.getControl(name='form.widgets.IAllowDiscussion.allow_discussion:list').value = ['True'] + >>> browser.getControl('Save').click() >>> urldoc = browser.url Check that the form has been properly submitted >>> browser.url - 'http://nohost/plone/doc' + 'http://nohost/plone/doc/view' + +Make sure the document is published: + + >>> browser.getLink("Publish").click() + >>> 'Published' in browser.contents + True Post some comments as anonymous user: @@ -223,4 +230,3 @@ Make sure the catalog has been updated properly. >>> portal.portal_catalog.searchResults(id='doc', total_comments=0) [>> unprivileged_browser = Browser(app) + >>> browser_member = Browser(app) + >>> browser_user = Browser(app) Make sure we have a test user from the layer and it uses fancy characters: @@ -55,11 +57,17 @@ 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() + >>> browser.getControl(name='form.widgets.IDublinCore.title').value = "Doc1" + >>> browser.getControl(name='form.widgets.IAllowDiscussion.allow_discussion:list').value = ['True'] + >>> browser.getControl('Save').click() >>> urldoc1 = browser.url +Make sure the document is published: + + >>> browser.getLink("Publish").click() + >>> 'Published' in browser.contents + True + Check that the form has been properly submitted >>> browser.url @@ -115,20 +123,19 @@ Post a comment as user Login as user (without the 'Member' role). - >>> browser.open(portal_url + '/logout') - >>> browser.open(portal_url + '/login_form') - >>> browser.getControl(name='__ac_name').value = 'johndoe' - >>> browser.getControl(name='__ac_password').value = 'secret' - >>> browser.getControl(name='submit').click() + >>> browser_user.open(portal_url + '/login_form') + >>> browser_user.getControl(name='__ac_name').value = 'johndoe' + >>> browser_user.getControl(name='__ac_password').value = 'secret' + >>> browser_user.getControl(name='submit').click() Users without the 'Reply to item' permission will not see the comment form, because they don't have the 'Reply to item' permission. By default, this permission is only granted to the 'Member' role. - >>> 'form.widgets.text' in browser.contents + >>> 'form.widgets.text' in browser_user.contents False - >>> 'form.buttons.comment' in browser.contents + >>> 'form.buttons.comment' in browser_user.contents False @@ -137,25 +144,24 @@ Post a comment as member 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() + >>> browser_member.open(portal_url + '/login_form') + >>> browser_member.getControl(name='__ac_name').value = 'jim' + >>> browser_member.getControl(name='__ac_password').value = 'secret' + >>> browser_member.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') + >>> browser_member.open(urldoc1) + >>> browser_member.getControl(name='form.widgets.text').value = "Comment from Jim" + >>> submit = browser_member.getControl(name='form.buttons.comment') >>> submit.click() Check if the comment has been added properly. - >>> browser.contents + >>> browser_member.contents '...Jim Fult\xc3\xb8rn...says:...' - >>> "Comment from Jim" in browser.contents + >>> "Comment from Jim" in browser_member.contents True @@ -285,7 +291,6 @@ This is a regression test for http://dev.plone.org/plone/ticket/11157 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' @@ -293,100 +298,11 @@ Login as admin. Edit the content object. - >>> browser.open(urldoc1 + "/edit") - >>> browser.getControl(name='text').value = "Lorem ipsum" - >>> browser.getControl(name='form.button.save').click() + >>> browser.open("http://nohost/plone/doc1/edit") + >>> browser.getControl(name='form.widgets.text').value = "Lorem ipsum" + >>> browser.getControl('Save').click() Make sure the edit was successful. >>> 'Lorem ipsum' in browser.contents True - - -List comments in a collection ------------------------------ - -Create a collection. - - >>> from plone.app.testing import setRoles - >>> from plone.app.testing import TEST_USER_NAME - >>> setRoles(portal, 'manager', ['Manager']) - >>> browser.open(portal.absolute_url()) - >>> from plone.app.discussion.testing import COLLECTION_TYPE - >>> browser.getLink(url='createObject?type_name=' + COLLECTION_TYPE).click() - >>> browser.getControl('Title', index=0 - ... ).value = 'Foo Comment Collection' - >>> browser.getControl('Save').click() - >>> print browser.contents - <...Changes saved... - >>> topic_url = browser.url - -Set the collection criteria. - - >>> browser.open(topic_url + "/edit") - - >>> if COLLECTION_TYPE == "Collection": - ... browser.getControl(name="addindex").value = ['portal_type'] - ... browser.getControl(name="form.button.addcriteria").click() - ... browser.getControl(name="addoperator").value = ['plone.app.querystring.operation.selection.is'] - ... browser.getControl(name="form.button.addcriteria").click() - ... browser.getControl(name="query.v:records:list").value = ["Discussion Item"] - ... browser.getControl(name="form.button.save").click() - ... else: - ... browser.getLink('Criteria').click() - ... browser.getControl('Item Type', index=0).selected = True - ... browser.getControl('Select content types').selected = True - ... browser.getControl('Add criteria').click() - ... browser.getControl('Comment').selected = True - ... browser.getControl('Save', index=0).click() - >>> print browser.contents - <...Changes saved... - -View the collection listing. - - >>> browser.getLink('View').click() - >>> browser.getLink('admin on Doc1', index=0) - - >>> browser.getLink('admin on Doc1', index=1) - - >>> browser.getLink('Anonymous on Doc1', index=0) - - >>> browser.getLink('Anonymous on Doc1', index=1) - - >>> browser.getLink(tarek_fullname + ' on Doc1') - - >>> browser.getLink(jim_fullname + ' on Doc1') - - -Comments are unindexed when the content is deleted --------------------------------------------------- - -Delete the commented content. - - >>> browser.open(urldoc1) - >>> browser.getLink('Delete').click() - >>> browser.getControl('Delete').click() - >>> print browser.contents - <...Doc1 has been deleted... - -The comments are no longer in the catalog. - - >>> browser.open(topic_url) - >>> browser.getLink('admin on Doc1', index=0) - Traceback (most recent call last): - LinkNotFoundError - >>> browser.getLink('admin on Doc1', index=1) - Traceback (most recent call last): - LinkNotFoundError - >>> browser.getLink('Anonymous on Doc1', index=0) - Traceback (most recent call last): - LinkNotFoundError - >>> browser.getLink('Anonymous on Doc1', index=1) - Traceback (most recent call last): - LinkNotFoundError - >>> browser.getLink(tarek_fullname + ' on Doc1') - Traceback (most recent call last): - LinkNotFoundError - >>> browser.getLink(jim_fullname + ' on Doc1') - Traceback (most recent call last): - LinkNotFoundError diff --git a/plone/app/discussion/tests/test_comments_viewlet.py b/plone/app/discussion/tests/test_comments_viewlet.py index 8b742c8..9c3fb22 100644 --- a/plone/app/discussion/tests/test_comments_viewlet.py +++ b/plone/app/discussion/tests/test_comments_viewlet.py @@ -59,6 +59,8 @@ class TestCommentForm(unittest.TestCase): typetool = self.portal.portal_types typetool.constructContent('Document', self.portal, 'doc1') + wftool = getToolByName(self.portal, "portal_workflow") + wftool.doActionFor(self.portal.doc1, action='publish') self.discussionTool = getToolByName( self.portal, 'portal_discussion', @@ -536,7 +538,8 @@ class TestCommentsViewlet(unittest.TestCase): *time.gmtime(time.mktime(python_time.timetuple()))[:7] ) localized_time = self.viewlet.format_time(python_time) - self.assertEqual(localized_time, 'Feb 01, 2009 11:32 PM') + self.assertTrue( + localized_time in ['Feb 01, 2009 11:32 PM', '2009-02-01 23:32']) def test_suite(): diff --git a/plone/app/discussion/tests/test_conversation.py b/plone/app/discussion/tests/test_conversation.py index 58e7094..59bca9d 100644 --- a/plone/app/discussion/tests/test_conversation.py +++ b/plone/app/discussion/tests/test_conversation.py @@ -197,102 +197,16 @@ class ConversationTest(unittest.TestCase): self.assertEqual(len(tuple(conversation.getThreads())), 0) self.assertEqual(conversation.total_comments, 0) - def test_allow_discussion(self): - # This is not a real test! It's only there to understand the - # allow discussion attribute. Maybe we should remove this at - # some point. - - # 1) allow_discussion attribute: Every content object in Plone - # has a allow_discussion attribute. By default it is set to None. - - # Create a conversation. - IConversation(self.portal.doc1) - - # By default, discussion is disabled for all content types - portal_types = getToolByName(self.portal, 'portal_types') - for type in list(portal_types): - type_fti = getattr(portal_types, type) - if type not in BAD_TYPES: - if type != 'Discussion Item': - self.assertFalse(type_fti.allowDiscussion()) - - # By default, allow_discussion on newly created content objects is - # set to False - portal_discussion = getToolByName(self.portal, 'portal_discussion') - self.assertEqual( - portal_discussion.isDiscussionAllowedFor(self.portal.doc1), - False - ) - self.assertEqual( - self.portal.doc1.getTypeInfo().allowDiscussion(), - False - ) - - # The allow discussion flag is None by default - self.assertFalse(getattr(self.portal.doc1, 'allow_discussion', None)) - - # But isDiscussionAllowedFor, also checks if discussion is allowed on - # the content type. So we allow discussion on the Document content - # type and check if the Document object allows discussion now. - document_fti = getattr(portal_types, 'Document') - document_fti.manage_changeProperties(allow_discussion=True) - self.assertEqual( - portal_discussion.isDiscussionAllowedFor(self.portal.doc1), - True - ) - self.assertEqual( - self.portal.doc1.getTypeInfo().allowDiscussion(), - True - ) - - # We can also override the allow_discussion locally - self.portal_discussion.overrideDiscussionFor(self.portal.doc1, False) - # Check if the Document discussion is disabled - self.assertEqual( - portal_discussion.isDiscussionAllowedFor(self.portal.doc1), - False - ) - # Check that the local allow_discussion flag is now explicitly set to - # False - self.assertEqual( - getattr(self.portal.doc1, 'allow_discussion', None), - False - ) - - # Disallow discussion on the Document content type again - document_fti.manage_changeProperties(allow_discussion=False) - self.assertEqual( - portal_discussion.isDiscussionAllowedFor(self.portal.doc1), - False - ) - self.assertEqual( - self.portal.doc1.getTypeInfo().allowDiscussion(), - False - ) - - # Now we override allow_discussion again (True) for the Document - # content object - self.portal_discussion.overrideDiscussionFor(self.portal.doc1, True) - self.assertEqual( - portal_discussion.isDiscussionAllowedFor(self.portal.doc1), - True - ) - self.assertEqual( - getattr(self.portal.doc1, 'allow_discussion', None), - True - ) - def test_comments_enabled_on_doc_in_subfolder(self): typetool = self.portal.portal_types typetool.constructContent('Folder', self.portal, 'folder1') typetool.constructContent('Document', self.portal.folder1, 'doc2') folder = self.portal.folder1 - folder.allowDiscussion(False) - self.assertFalse(hasattr(aq_base(folder), 'allow_discussion')) - folder.allowDiscussion(True) + + folder.allow_discussion = True self.assertTrue(aq_base(folder).allow_discussion) - folder.allowDiscussion(False) + folder.allow_discussion = False self.assertFalse(aq_base(folder).allow_discussion) doc = self.portal.folder1.doc2 @@ -388,10 +302,11 @@ class ConversationTest(unittest.TestCase): self.assertEqual(conversation.enabled(), False) def test_allow_discussion_on_folder(self): - # The enabled method should always return False for the folder - # itself. + # The ATContentTypes based allow_discussion method did not allow to + # allow discussion on a folder. The dexerity behavior shipped with + # plone.app.contenttypes does not have this restriction any longer. - # Create a folderp + # Create a folder self.typetool.constructContent('Folder', self.portal, 'f1') f1 = self.portal.f1 # Usually we don't create a conversation on a folder @@ -405,39 +320,7 @@ class ConversationTest(unittest.TestCase): document_fti = getattr(portal_types, 'Folder') document_fti.manage_changeProperties(allow_discussion=True) - # Always return False - self.assertFalse(conversation.enabled()) - - def test_is_discussion_allowed_for_folder(self): - # 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 - self.typetool.constructContent('Document', f1, 'doc1') - doc1 = self.portal.f1.doc1 - doc1_conversation = doc1.restrictedTraverse('@@conversation_view') - - self.assertEqual(doc1_conversation.enabled(), False) - - # Allow commenting for the folder - self.portal_discussion.overrideDiscussionFor(f1, True) - - # Check if the content objects allows discussion - self.assertEqual(doc1_conversation.enabled(), True) - - # Turn commenting for the folder off - self.portal_discussion.overrideDiscussionFor(f1, False) - - # Check if content objects do not allow discussion anymore - self.assertEqual(doc1_conversation.enabled(), False) + self.assertTrue(conversation.enabled()) def test_is_discussion_allowed_on_content_object(self): # Allow discussion on a single content object diff --git a/setup.py b/setup.py index 52b646f..a3f5d8b 100644 --- a/setup.py +++ b/setup.py @@ -52,6 +52,7 @@ setup(name='plone.app.discussion', 'test': [ 'plone.app.testing', 'interlude', + 'plone.app.contenttypes', ] }, entry_points="""