Index: /main/waeup.ikoba/trunk/src/waeup/ikoba/permissions.py
===================================================================
--- /main/waeup.ikoba/trunk/src/waeup/ikoba/permissions.py	(revision 12071)
+++ /main/waeup.ikoba/trunk/src/waeup/ikoba/permissions.py	(revision 12072)
@@ -92,5 +92,5 @@
     grok.permissions('waeup.viewProducts')
 
-class ProductssManager(grok.Role):
+class ProductsManager(grok.Role):
     grok.name('waeup.ProductsManager')
     grok.title(u'Products Manager')
Index: /main/waeup.ikoba/trunk/src/waeup/ikoba/products/browser.py
===================================================================
--- /main/waeup.ikoba/trunk/src/waeup/ikoba/products/browser.py	(revision 12071)
+++ /main/waeup.ikoba/trunk/src/waeup/ikoba/products/browser.py	(revision 12072)
@@ -99,5 +99,5 @@
                        type='danger')
             return
-        delSubobjects(self, redirect='@@manage', tab='2')
+        delSubobjects(self, redirect='manage', tab='2')
         return
 
@@ -113,5 +113,5 @@
     @action(_('Add product'), validator=NullValidator)
     def addSubunit(self, **data):
-        self.redirect(self.url(self.context, '@@addproduct'))
+        self.redirect(self.url(self.context, 'addproduct'))
         return
 
@@ -142,5 +142,5 @@
         self.context.__parent__.logger.info(
             '%s - added: %s' % (ob_class, data['product_id']))
-        self.redirect(self.url(self.context, u'@@manage')+'#tab2')
+        self.redirect(self.url(self.context, u'manage')+'#tab2')
         return
 
Index: /main/waeup.ikoba/trunk/src/waeup/ikoba/products/tests/test_browser.py
===================================================================
--- /main/waeup.ikoba/trunk/src/waeup/ikoba/products/tests/test_browser.py	(revision 12071)
+++ /main/waeup.ikoba/trunk/src/waeup/ikoba/products/tests/test_browser.py	(revision 12072)
@@ -84,10 +84,26 @@
         setSite(app)
 
-
-        self.login_path = 'http://localhost/app/login'
-
+        # Add user
+        self.app['users'].addUser(name='john', password='johnpwd',
+                                  title='John Tester',
+                                  email='john@tester.de')
+
+        # Add some product
+        self.product = createObject('waeup.Product')
+        self.product.product_id = u'LIC'
+        self.product.title = u'Our License'
+        self.app['products'].addProduct(self.product)
+
+        # Add session configuration
         self.app['configuration'].carry_over = True
         configuration = createObject('waeup.SessionConfiguration')
+
         self.app['configuration'].addSessionConfiguration(configuration)
+        self.login_path = 'http://localhost/app/login'
+        self.container_path = 'http://localhost/app/products'
+        self.manage_container_path = self.container_path + '/manage'
+        self.add_product_path = self.container_path + '/addproduct'
+        self.product_path = self.container_path + '/LIC'
+        self.manage_product_path = self.container_path + '/LIC/manage'
 
         # Put the prepopulated site into test ZODB and prepare test
@@ -97,5 +113,97 @@
 
     def tearDown(self):
-        super(CustomersFullSetup, self).tearDown()
+        super(ProductssFullSetup, self).tearDown()
         clearSite()
         shutil.rmtree(self.dc_root)
+
+class ProductsContainerUITests(ProductssFullSetup):
+    # Tests for ProductsContainer class views and pages
+
+    layer = FunctionalLayer
+
+    def test_anonymous_access(self):
+        # Anonymous users can view products containers ...
+        self.browser.open(self.container_path)
+        self.assertEqual(self.browser.headers['Status'], '200 Ok')
+        # ... but not manage
+        self.assertRaises(
+            Unauthorized, self.browser.open, self.manage_container_path)
+        return
+
+    def test_manage_access(self):
+        # Managers can access the view page of products
+        # containers and can perform actions
+        self.browser.addHeader('Authorization', 'Basic mgr:mgrpw')
+        self.browser.open(self.container_path)
+        self.assertEqual(self.browser.headers['Status'], '200 Ok')
+        self.assertEqual(self.browser.url, self.container_path)
+        self.browser.getLink("Manage").click()
+        self.assertEqual(self.browser.headers['Status'], '200 Ok')
+        self.assertEqual(self.browser.url, self.manage_container_path)
+        return
+
+    def test_add_delete_products(self):
+        # Managers can add search and remove products
+        self.browser.addHeader('Authorization', 'Basic mgr:mgrpw')
+        self.browser.open(self.manage_container_path)
+        self.browser.getControl("Add product").click()
+        self.assertEqual(self.browser.headers['Status'], '200 Ok')
+        self.assertEqual(self.browser.url, self.add_product_path)
+        self.browser.getControl(name="form.product_id").value = 'bob'
+        self.browser.getControl(name="form.title").value = 'My product'
+        self.browser.getControl("Create product").click()
+        self.assertTrue('Product bob added' in self.browser.contents)
+        self.assertEqual(len(self.app['products'].keys()), 2)
+        self.assertEqual(self.app['products']['bob'].title, 'My product')
+        ctrl = self.browser.getControl(name='val_id')
+        ctrl.getControl(value='bob').selected = True
+        self.browser.getControl("Remove selected", index=0).click()
+        self.assertTrue('Successfully removed' in self.browser.contents)
+        self.assertEqual(len(self.app['products'].keys()), 1)
+
+
+class ProductsUITests(ProductssFullSetup):
+    # Tests for Products class views and pages
+
+    layer = FunctionalLayer
+
+    def test_anonymous_access(self):
+        # Anonymous users can access products ...
+        self.browser.open(self.product_path)
+        self.assertEqual(self.browser.headers['Status'], '200 Ok')
+        # ... but not manage products
+        self.assertRaises(
+            Unauthorized, self.browser.open, self.manage_product_path)
+        return
+
+    def test_manage_access(self):
+        # Managers can access the view page of products
+        # and can perform actions
+        self.browser.addHeader('Authorization', 'Basic mgr:mgrpw')
+        self.browser.open(self.product_path)
+        self.assertEqual(self.browser.headers['Status'], '200 Ok')
+        self.browser.getLink("Manage").click()
+        self.assertEqual(self.browser.headers['Status'], '200 Ok')
+        self.assertEqual(self.browser.url, self.manage_product_path)
+        self.browser.getControl(name="form.title").value = 'New license'
+        self.browser.getControl("Save").click()
+        self.assertEqual(self.app['products']['LIC'].title, 'New license')
+        # Managers can asign local roles
+        self.browser.getControl(name="user").value = ['john']
+        self.browser.getControl(
+            name="local_role").value = ['waeup.local.ProductManager']
+        self.browser.getControl("Add local role").click()
+        self.assertTrue('john|waeup.local.ProductManager' in self.browser.contents)
+        self.assertEqual(
+            self.app['users']['john'].getLocalRoles().get(
+                'waeup.local.ProductManager')[0],
+            self.product)
+        # If products is deleted also the local role disappears
+        self.browser.open(self.manage_container_path)
+        ctrl = self.browser.getControl(name='val_id')
+        ctrl.getControl(value='LIC').selected = True
+        self.browser.getControl("Remove selected", index=0).click()
+        self.assertEqual(
+            self.app['users']['john'].getLocalRoles().get('waeup.local.ProductManager'),
+            None)
+        return
