Views ===== Test view registration ---------------------- Test if view has been properly registered:: def test_delete_view_registered(self): try: getMultiAdapter( (self.portal.mi.se.tc, self.request), name="delete" ) except: self.fail("Delete view is not registered properly.") Test with getMultiAdapter ------------------------- Test:: def test_view_is_registered(self): # Get the view view = getMultiAdapter((self.portal, self.portal.REQUEST), name="create-user") # Put the view into the acquisition chain view = view.__of__(self.portal) # Call the view self.failUnless(view()) Test with restrictedTraverse ---------------------------- Test:: def test_view_is_registered(self): view = self.portal.restrictedTraverse('@@list-products') self.failUnless(view) self.assertEquals(view(), 'ListProductsView') Test view with parameter ------------------------ Test:: def test_autocomplete_tags_view_registered(self): self.request.set('term', 'foo') view = getMultiAdapter((self.portal, self.request), name="autocomplete-tags") view = view.__of__(self.portal) self.failUnless(view()) Test with restrictedTraverse and parameter ------------------------------------------ Test:: def test_view_with_restrictedTraverse_and_params(self): view = self.context.restrictedTraverse("comment-statistics-batch") view = view.__of__(self.context) view(query, base_number * i, base_number * (i + 1) - 1) Test if view is protected ------------------------- Test:: def test_view_is_protected(self): from AccessControl import Unauthorized self.logout() self.assertRaises(Unauthorized, self.portal.restrictedTraverse, '@@deploymentmanager') Test if object exists in folder ------------------------------- Test:: def test_object_in_folder(self): self.failIf('yoda' in self.portal.objectIds()) Test Redirect ------------- Test:: def test_component_view(self): self.portal.mi.sec.invokeFactory( "TextComponent", id="tx", title="Text Component 1", ) view = getMultiAdapter( (self.portal.mi.sec.tx, self.request), name="view" ) view = view.__of__(self.portal.mi.sec) view() self.assertEqual( self.request.response.headers['location'], 'http://nohost/plone/mi/sec' ) Test View HTML Output ===================== Test:: from lxml import html output = lxml.html.fromstring(view()) self.assertEqual(len(output.xpath("/html/body/div")), 1) Troubleshooting =============== KeyError: 'ACTUAL_URL':: def setUp(self): self.portal = self.layer['portal'] self.request = self.layer['request'] setRoles(self.portal, TEST_USER_ID, ['Manager']) self.portal.invokeFactory('Folder', 'test-folder') self.folder = self.portal['test-folder'] self.request.set('URL', self.folder.absolute_url()) self.request.set('ACTUAL_URL', self.folder.absolute_url()) def test_view(self): view = self.collection.restrictedTraverse('@@RSS') self.assertTrue(view()) self.assertEquals(view.request.response.status, 200) ComponentLookupError -------------------- If a view can not be looked up on a particular context, Plone will raise a ComponentLookupError (because views are multi-adapters), e.g.:: ComponentLookupError: ((, ), , 'recipes'):: This can be solved for instance by providing a browser layer that has been missing:: def setUp(self): self.request = self.layer['request'] from zope.interface import directlyProvides directlyProvides(self.request, IJungzeelandiaContenttypes) ... AttributeError: @@plone_portal_state ------------------------------------ Test View Methods ================= Test:: def test_method_sections(self): self.portal.mi.invokeFactory("Section", id="s1", title="Section 1") self.portal.mi.invokeFactory("Section", id="s2", title="Section 2") view = getMultiAdapter( (self.portal.mi, self.request), name="view" ) view = view.__of__(self.portal.mi) self.assertEqual(len(view.sections()), 2) self.assertEqual( [x.title for x in view.sections()] [u'Section 1', u'Section 2'] ) View Status Messages -------------------- Test:: def test_delete_comments_sets_status_message(self): view = getMultiAdapter( (self.portal.mi.se.tc, self.request), name="delete" ) view.__of__(self.portal.mi.se) view() self.assertEqual( IStatusMessage(self.request).show()[0].message, u'Item deleted' ) View Class:: class DeleteComponent(BrowserView): def __call__(self): section = aq_parent(self.context) section.manage_delObjects([self.context.id]) IStatusMessage(self.context.REQUEST).addStatusMessage( _("Item deleted"), type="info" ) self.request.response.redirect(section.absolute_url())