From 5fb6968fcad4e40c25f6ae65a331f015bbd30ce0 Mon Sep 17 00:00:00 2001 From: Kees Hink Date: Fri, 10 May 2013 14:59:32 +0200 Subject: [PATCH] Add a test for Acquisition in comments. --- plone/app/discussion/testing.py | 4 + plone/app/discussion/tests/configure.zcml | 16 ++ plone/app/discussion/tests/profile/types.xml | 4 + .../profile/types/sample_content_type.xml | 47 ++++++ .../discussion/tests/profile/workflows.xml | 4 + .../definition.xml | 75 +++++++++ .../app/discussion/tests/test_acquisition.py | 145 ++++++++++++++++++ 7 files changed, 295 insertions(+) create mode 100644 plone/app/discussion/tests/configure.zcml create mode 100644 plone/app/discussion/tests/profile/types.xml create mode 100644 plone/app/discussion/tests/profile/types/sample_content_type.xml create mode 100644 plone/app/discussion/tests/profile/workflows.xml create mode 100644 plone/app/discussion/tests/profile/workflows/comment_workflow_acquired_view/definition.xml create mode 100644 plone/app/discussion/tests/test_acquisition.py diff --git a/plone/app/discussion/testing.py b/plone/app/discussion/testing.py index cf1066c..02b8fa3 100644 --- a/plone/app/discussion/testing.py +++ b/plone/app/discussion/testing.py @@ -35,10 +35,14 @@ class PloneAppDiscussion(PloneSandboxLayer): xmlconfig.file('configure.zcml', plone.app.discussion, context=configurationContext) + xmlconfig.file('configure.zcml', + plone.app.discussion.tests, + context=configurationContext) def setUpPloneSite(self, portal): # Install into Plone site using portal_setup applyProfile(portal, 'plone.app.discussion:default') + applyProfile(portal, 'plone.app.discussion.tests:testing') # Creates some users acl_users = getToolByName(portal, 'acl_users') diff --git a/plone/app/discussion/tests/configure.zcml b/plone/app/discussion/tests/configure.zcml new file mode 100644 index 0000000..ee79b95 --- /dev/null +++ b/plone/app/discussion/tests/configure.zcml @@ -0,0 +1,16 @@ + + + + + + + diff --git a/plone/app/discussion/tests/profile/types.xml b/plone/app/discussion/tests/profile/types.xml new file mode 100644 index 0000000..0aec569 --- /dev/null +++ b/plone/app/discussion/tests/profile/types.xml @@ -0,0 +1,4 @@ + + + + diff --git a/plone/app/discussion/tests/profile/types/sample_content_type.xml b/plone/app/discussion/tests/profile/types/sample_content_type.xml new file mode 100644 index 0000000..7869638 --- /dev/null +++ b/plone/app/discussion/tests/profile/types/sample_content_type.xml @@ -0,0 +1,47 @@ + + + + + sample_content_type + Sample Content + document_icon.png + True + True + + + True + + plone.dexterity.content.Item + + cmf.AddPortalContent + + + + + + view + False + + + + + + + + + + + + + + + + + + + diff --git a/plone/app/discussion/tests/profile/workflows.xml b/plone/app/discussion/tests/profile/workflows.xml new file mode 100644 index 0000000..500f444 --- /dev/null +++ b/plone/app/discussion/tests/profile/workflows.xml @@ -0,0 +1,4 @@ + + + + diff --git a/plone/app/discussion/tests/profile/workflows/comment_workflow_acquired_view/definition.xml b/plone/app/discussion/tests/profile/workflows/comment_workflow_acquired_view/definition.xml new file mode 100644 index 0000000..89a9fb2 --- /dev/null +++ b/plone/app/discussion/tests/profile/workflows/comment_workflow_acquired_view/definition.xml @@ -0,0 +1,75 @@ + + + Access contents information + Change portal events + Modify portal content + View + + Visible to everyone, editable by the owner. + + Anonymous + + + Editor + Manager + Owner + Site Administrator + + + Editor + Manager + Owner + Site Administrator + + + + + + Previous transition + + transition/getId|nothing + + + + + + The ID of the user who performed the previous transition + + user/getId + + + + + + Comment about the last transition + + python:state_change.kwargs.get('comment', '') + + + + + + Provides access to workflow history + + state_change/getHistory + + + Request review + Review portal content + + + + When the previous transition was performed + + state_change/getDateTime + + + + + diff --git a/plone/app/discussion/tests/test_acquisition.py b/plone/app/discussion/tests/test_acquisition.py new file mode 100644 index 0000000..31d5f81 --- /dev/null +++ b/plone/app/discussion/tests/test_acquisition.py @@ -0,0 +1,145 @@ +# -*- coding: utf-8 -*- +from Acquisition import aq_chain +from plone.app.discussion.testing import \ + PLONE_APP_DISCUSSION_INTEGRATION_TESTING +from plone.app.discussion.interfaces import IConversation +from plone.app.testing import TEST_USER_ID, setRoles +from Products.CMFCore.utils import getToolByName +from zope.component import createObject + +import unittest2 as unittest + + +dexterity_type_name = 'sample_content_type' +dexterity_object_id = 'instance-of-dexterity-type' +archetypes_object_id = 'instance-of-archetypes-type' +one_state_workflow = 'one_state_workflow' +comment_workflow_acquired_view = 'comment_workflow_acquired_view' + + +def _anonymousCanView(obj): + """Use rolesOfPermission() to sees if Anonymous has View permission on an + object""" + roles_of_view_permission = obj.rolesOfPermission("View") + # rolesOfPermission returns a list of dictionaries that have the key + # 'name' for role. + anon_views = [r for r in roles_of_view_permission + if r['name'] == 'Anonymous'] + # only one entry per role should be present + anon_view = anon_views[0] + # if this role has the permission, 'selected' is set to 'SELECTED' + return anon_view['selected'] == 'SELECTED' + + +class DexterityAcquisitionTest(unittest.TestCase): + """See test_view_permission.""" + + layer = PLONE_APP_DISCUSSION_INTEGRATION_TESTING + + def setUp(self): + self.portal = self.layer['portal'] + self.request = self.layer['request'] + setRoles(self.portal, TEST_USER_ID, ['Manager']) + self.wftool = getToolByName(self.portal, 'portal_workflow') + + # Use customized workflow for comments. + self.wftool.setChainForPortalTypes( + ['Discussion Item'], + (comment_workflow_acquired_view,), + ) + + # Use one_state_workflow for Document and sample_content_type, + # so they're always published. + self.wftool.setChainForPortalTypes( + ['Document', dexterity_type_name], + (one_state_workflow,), + ) + + # Create a dexterity item and add a comment. + self.portal.invokeFactory( + id=dexterity_object_id, + title='Instance Of Dexterity Type', + type_name=dexterity_type_name, + ) + self.dexterity_object = self.portal.get(dexterity_object_id) + dx_conversation = IConversation(self.dexterity_object) + self.dexterity_conversation = dx_conversation + comment1 = createObject('plone.Comment') + dx_conversation.addComment(comment1) + self.dexterity_comment = comment1 + + # Create an Archetypes item and add a comment. + self.portal.invokeFactory( + id=archetypes_object_id, + title='Instance Of Archetypes Type', + type_name='Document', + ) + self.archetypes_object = self.portal.get(archetypes_object_id) + at_conversation = IConversation(self.archetypes_object) + self.archetypes_conversation = at_conversation + comment2 = createObject('plone.Comment') + at_conversation.addComment(comment2) + self.archetypes_comment = comment2 + + def test_workflows_installed(self): + """Check that the new comment workflow has been installed properly. + (Just a test to check our test setup.) + """ + workflows = self.wftool.objectIds() + self.assertTrue('comment_workflow_acquired_view' in workflows) + + def test_workflows_applied(self): + """Check that all objects have the workflow that we expect. + (Just a test to check our test setup.)""" + self.assertEqual( + self.wftool.getChainFor(self.archetypes_object), + (one_state_workflow,) + ) + self.assertEqual( + self.wftool.getChainFor(self.dexterity_object), + (one_state_workflow,) + ) + self.assertEqual( + self.wftool.getChainFor(self.archetypes_comment), + (comment_workflow_acquired_view,) + ) + self.assertEqual( + self.wftool.getChainFor(self.dexterity_comment), + (comment_workflow_acquired_view,) + ) + + def test_view_permission(self): + """Test that if the View permission on Discussion Items is acquired, + Anonymous can view comments on published items.""" + + # Anonymous has View permission on commented objects. + self.assertTrue(_anonymousCanView(self.archetypes_object)) + self.assertTrue(_anonymousCanView(self.dexterity_object)) + + # Fails: Anonymous should therefore have View permission on the + # comments. + self.assertTrue(_anonymousCanView(self.archetypes_comment)) + self.assertTrue(_anonymousCanView(self.dexterity_comment)) + + def test_acquisition_chain(self): + """The acquisition chain for the comment should contain the same items + as that of the conversation. + + Note that the list returned by aq_inner has the innermost object + first.""" + + # Fails: list index out of range + at_comment_chain = aq_chain(self.archetypes_comment) + at_conversation_chain = aq_chain(self.archetypes_conversation) + for (index, item) in enumerate(at_conversation_chain): + self.assertEqual(item, at_comment_chain[index + 1]) + + # Fails: list index out of range + dx_comment_chain = aq_chain(self.dexterity_comment) + dx_conversation_chain = aq_chain(self.dexterity_conversation) + for (index, item) in enumerate(dx_conversation_chain): + self.assertEqual(item, dx_comment_chain[index + 1]) + + +def test_suite(): + return unittest.defaultTestLoader.loadTestsFromName(__name__)