Functional Browser Pages Test ============================= This test tests publishing aspects of browser pages. Let's register some: >>> import Products.Five.browser.tests >>> from Zope2.App import zcml >>> zcml.load_config("configure.zcml", Products.Five) >>> zcml.load_config('pages.zcml', package=Products.Five.browser.tests) Let's also add one of our stub objects to play with: >>> from Products.Five.tests.testing.simplecontent import manage_addSimpleContent >>> manage_addSimpleContent(self.folder, 'testoid', 'Testoid') Docstrings ---------- In Zope 2, objects normally have to have a docstring in order to be published. This crazy requirement luckily isn't true for zope.publisher, so it should be possible to write docstring-less view classes that are still published through ZPublisher. We see that even though the callables have no docstring, they are published nevertheless: >>> print http(r""" ... GET /test_folder_1_/testoid/nodoc-function HTTP/1.1 ... """) HTTP/1.1 200 OK ... No docstring >>> print http(r""" ... GET /test_folder_1_/testoid/nodoc-method HTTP/1.1 ... """) HTTP/1.1 200 OK ... No docstring >>> print http(r""" ... GET /test_folder_1_/testoid/nodoc-object HTTP/1.1 ... """) HTTP/1.1 200 OK ... No docstring Security -------- Browser pages need to be protected with a permission. Let's test those; we start by adding two users: >>> uf = self.folder.acl_users >>> _ignored = uf._doAddUser('viewer', 'secret', [], []) >>> _ignored = uf._doAddUser('manager', 'r00t', ['Manager'], []) >>> protected_view_names = [ ... 'eagle.txt', 'falcon.html', 'owl.html', 'flamingo.html', ... 'condor.html'] >>> >>> public_view_names = [ ... 'public_attribute_page', ... 'public_template_page', ... 'public_template_class_page', ... 'nodoc-method', 'nodoc-function', 'nodoc-object', ... 'dirpage1', 'dirpage2'] >>> >>> ViewManagementScreens = 'View management screens' As a normal user we shouldn't get to see those pages protected with the 'View management screens' permission. Thus we expect a 401 Unauthorized: >>> for view_name in protected_view_names: ... response = self.publish('/test_folder_1_/testoid/%s' % view_name, ... basic='viewer:secret') ... status = response.getStatus() ... self.assertTrue(status == 401, (status, 401, view_name)) Methods of views which were not explicitly declared as allowed should not be accessible TTW, even if we have the permission to render the view: >>> response = self.publish('/test_folder_1_/testoid/eagle.method/mouse', ... basic='viewer:secret') >>> self.assertEqual(response.getStatus(), 401) The same should apply for the user if he has all other permissions except 'View management screens': >>> permissions = self.folder.possible_permissions() >>> permissions.remove(ViewManagementScreens) >>> self.folder._addRole('Viewer') >>> self.folder.manage_role('Viewer', permissions) >>> self.folder.manage_addLocalRoles('viewer', ['Viewer']) >>> for view_name in protected_view_names: ... response = self.publish('/test_folder_1_/testoid/%s' % view_name, ... basic='viewer:secret') ... status = response.getStatus() ... self.assertTrue(status == 401, (status, 401, view_name)) If we grant 'View management screens' now, the protected views should become viewable: >>> self.folder.manage_role('Viewer', [ViewManagementScreens]) >>> for view_name in protected_view_names: ... response = self.publish('/test_folder_1_/testoid/%s' % view_name, ... basic='viewer:secret') ... status = response.getStatus() ... self.assertTrue(status == 200, (status, 200, view_name)) Managers should always be able to view anything, including proctected stuff: >>> for view_name in protected_view_names: ... response = self.publish('/test_folder_1_/testoid/%s' % view_name, ... basic='manager:r00t') ... self.assertEqual(response.getStatus(), 200) All public views should always be accessible by anyone: >>> for view_name in public_view_names: ... response = self.publish('/test_folder_1_/testoid/%s' % view_name) ... status = response.getStatus() ... self.assertTrue(status == 200, (status, 200, view_name)) Miscellaneous ------------- Zope 2 always wants objects in the traversal graph to have a __name__. That is also true for views, e.g. a view constructed from a simple class bearing only a __call__ method: >>> print http(r''' ... GET /test_folder_1_/testoid/callview.html HTTP/1.1 ... ''') HTTP/1.1 200 OK ... I was __call__()'ed or a __call__ object that's callable, such as a ViewPageTemplateFile: >>> print http(r''' ... GET /test_folder_1_/testoid/calltemplate.html HTTP/1.1 ... ''') HTTP/1.1 200 OK ...

The falcon has taken flight

Clean up -------- >>> from zope.component.testing import tearDown >>> tearDown()