Index: main/waeup.sirp/trunk/src/waeup/sirp/applicants/tests/test_browser.py
===================================================================
--- main/waeup.sirp/trunk/src/waeup/sirp/applicants/tests/test_browser.py	(revision 6470)
+++ main/waeup.sirp/trunk/src/waeup/sirp/applicants/tests/test_browser.py	(revision 6479)
@@ -5,5 +5,5 @@
 ## $Id$
 ## 
-## Copyright (C) 2011 Uli Fouquet
+## Copyright (C) 2011 Uli Fouquet & Henrik Bettermann
 ## This program is free software; you can redistribute it and/or modify
 ## it under the terms of the GNU General Public License as published by
@@ -35,26 +35,28 @@
 from waeup.sirp.app import University
 from waeup.sirp.applicants.container import ApplicantsContainer
-
-class LoginTest(FunctionalTestCase):
-    # Here we check login view of applicants containers.
-    #
-    # Tests in here do only cover login attempts without any PINs
-    # created before.
+from waeup.sirp.applicants.applicants import Applicant
+
+
+class ApplicantsUITests(FunctionalTestCase):
+    # Tests for ApplicantsRoot class
 
     layer = FunctionalLayer
 
     def setUp(self):
-        super(LoginTest, self).setUp()
+        super(ApplicantsUITests, self).setUp()
 
         # Setup a sample site for each test
         app = University()
         self.dc_root = tempfile.mkdtemp()
-        app['datacenter'].setStoragePath(self.dc_root)
-        self.login_path = 'http://localhost/app/applicants/testapplicants/login'
-
-        # Add an applicants container where we can login (or not)
+        self.root_path = 'http://localhost/app/applicants/'
+        self.container_path = 'http://localhost/app/applicants/app2009/'
+
+        # Add an applicants container
         applicantscontainer = ApplicantsContainer()
         applicantscontainer.ac_prefix = 'APP'
-        app['applicants']['testapplicants'] = applicantscontainer
+        applicantscontainer.prefix = 'app'
+        applicantscontainer.year = 2009
+        applicantscontainer.application_category = 'basic'
+        app['applicants']['app2009'] = applicantscontainer
 
         # Put the prepopulated site into test ZODB and prepare test
@@ -63,77 +65,4 @@
         self.browser = Browser()
         self.browser.handleErrors = False
-
-    def tearDown(self):
-        super(LoginTest, self).tearDown()
-        shutil.rmtree(self.dc_root)
-
-    def test_anonymous_access(self):
-        # Anonymous users can access a login page
-        self.browser.open(self.login_path)
-        self.assertEqual(self.browser.headers['Status'], '200 Ok')
-        return
-
-    def test_anonymous_invalid_creds(self):
-        # Anonymous users giving invalid credentials stay at the page
-        self.browser.open(self.login_path)
-        # We do not give credentials but send the form as-is
-        submit = self.browser.getControl(name='SUBMIT')
-        submit.click()
-        # We are still at the same page...
-        self.assertEqual(self.browser.url, self.login_path)
-        self.assertEqual(self.browser.headers['Status'], '200 Ok')
-        return
-
-    def test_anonymous_invalid_creds_warning(self):
-        # Entering wrong credentials will yield a warning
-        self.browser.open(self.login_path)
-        # We do not give credentials but send the form as-is
-        submit = self.browser.getControl(name='SUBMIT')
-        submit.click()
-        self.assertTrue(
-            'Entered credentials are invalid' in self.browser.contents)
-        return
-
-    def test_manager_no_warnings(self):
-        # Browsing the login screen as a manager, won't raise warnings
-        # Authenticate ourself as manager
-        self.browser.addHeader('Authorization', 'Basic mgr:mgrpw')
-        self.browser.open(self.login_path)
-        # Submit the form w/o any credentials
-        self.browser.getControl(name="SUBMIT").click()
-        self.assertTrue(
-            'Entered credentials are invalid' not in self.browser.contents)
-        return
-
-    def test_manager_no_redirect(self):
-        # Browsing the login screen as a manager won't trigger a redirect
-        # Authenticate ourself as manager
-        self.browser.addHeader('Authorization', 'Basic mgr:mgrpw')
-        self.browser.open(self.login_path)
-        # Submit the form w/o any credentials
-        self.browser.getControl(name="SUBMIT").click()
-        self.assertEqual(self.browser.url, self.login_path)
-        return
-
-    def test_display_entered_values(self):
-        # After submit the entered values are displayed in the form
-        self.browser.open(self.login_path)
-        # Enter some value we can look for after submit
-        ac_series = self.browser.getControl(name="form.ac_series")
-        ac_series.value = '666'
-        self.browser.getControl(name="SUBMIT").click()
-        self.assertTrue('666' in self.browser.contents)
-        return
-
-class LoginTestWithPINs(LoginTest):
-    # Here we check login view of applicants containers with PINs provided.
-
-    # As setting up pins is time-consuming we only set them up when
-    # really needed (i.e. in this separate TestCase).
-
-    layer = FunctionalLayer
-
-    def setUp(self):
-        super(LoginTestWithPINs, self).setUp()
 
         # Create 5 access codes with prefix'FOO' and cost 9.99 each
@@ -148,4 +77,219 @@
         self.browser.handleErrors = False
 
+        # Add an applicant
+        applicant = Applicant()
+        self.pin_applicant = unicode(self.pins[1])
+        applicant.access_code = self.pin_applicant
+        app['applicants']['app2009'][self.pin_applicant] = applicant
+
+    def tearDown(self):
+        super(ApplicantsUITests, self).tearDown()
+        shutil.rmtree(self.dc_root)
+
+    def test_anonymous_access(self):
+        # Anonymous users can access applicants root and applicants containers
+        self.browser.open(self.root_path)
+        self.assertEqual(self.browser.headers['Status'], '200 Ok')
+        self.assertFalse(
+            'Manage' in self.browser.contents)
+        self.browser.open(self.container_path)
+        self.assertEqual(self.browser.headers['Status'], '200 Ok')
+        self.assertFalse(
+            'Manage' in self.browser.contents)
+        return
+
+    def test_manage_access(self):
+        # Managers can access the manage pages of applicants root and
+        # applicants containers
+        self.browser.addHeader('Authorization', 'Basic mgr:mgrpw')
+        self.browser.open(self.root_path)
+        self.assertTrue(
+            'Manage application section' in self.browser.contents)
+        self.manage_root_path = self.root_path + '/@@manage'
+        self.manage_container_path = self.container_path + '/@@manage'
+        self.browser.open(self.manage_root_path)
+        self.assertEqual(self.browser.headers['Status'], '200 Ok')
+        self.assertEqual(self.browser.url, self.manage_root_path)
+        self.browser.open(self.manage_container_path)
+        self.assertEqual(self.browser.headers['Status'], '200 Ok')
+        self.assertEqual(self.browser.url, self.manage_container_path)
+        return
+
+    def test_add_delete_container(self):
+        # Managers can add and delete applicants containers
+        self.browser.addHeader('Authorization', 'Basic mgr:mgrpw')
+        self.browser.open(self.root_path)
+        self.add_container_path = self.root_path + '/@@add'
+        self.browser.open(self.add_container_path)
+        self.assertEqual(self.browser.headers['Status'], '200 Ok')
+        self.assertEqual(self.browser.url, self.add_container_path)
+        self.browser.getControl(name="form.prefix").value = ['app']
+        self.browser.getControl("Add applicants container").click()
+        self.assertTrue(
+            'There were errors' in self.browser.contents)
+        self.browser.getControl(name="form.prefix").value = ['app']
+        self.browser.getControl(name="form.year").value = ['2010']
+        self.browser.getControl(name="form.provider").value = ['waeup.sirp.applicants.ApplicantsContainer']
+        self.browser.getControl(name="form.ac_prefix").value = ['APP']
+        self.browser.getControl(name="form.application_category").value = ['basic']
+        self.browser.getControl("Add applicants container").click()
+        self.assertTrue('Added:' in self.browser.contents)
+        ctrl = self.browser.getControl(name='val_id')
+        ctrl.getControl(value='app2010').selected = True
+        self.browser.getControl("Remove selected", index=0).click()
+        self.assertTrue('Successfully removed:' in self.browser.contents)
+        return
+
+    def test_add_delete_applicants(self):
+        # Managers can add and delete applicants
+        self.browser.addHeader('Authorization', 'Basic mgr:mgrpw')
+        self.add_applicant_path = self.container_path + '/addapplicant'
+        self.container_manage_path = self.container_path + '/@@manage'
+        self.browser.open(self.add_applicant_path)
+        self.assertEqual(self.browser.headers['Status'], '200 Ok')
+        self.assertEqual(self.browser.url, self.add_applicant_path)
+        self.browser.getControl(name="form.ac_series").value = self.existing_series
+        self.browser.getControl(name="form.ac_number").value = self.existing_number
+        self.browser.getControl("Create application record").click()
+        self.assertTrue('Application initialized' in self.browser.contents)
+        self.browser.open(self.container_manage_path)
+        self.assertEqual(self.browser.headers['Status'], '200 Ok')
+        ctrl = self.browser.getControl(name='val_id')
+        ctrl.getControl(value=self.existing_pin).selected = True
+        self.browser.getControl("Remove selected", index=0).click()
+        self.assertTrue('Successfully removed:' in self.browser.contents)
+        return
+
+    def test_manage_applicant(self):
+        # Managers can manage applicants
+        self.browser.addHeader('Authorization', 'Basic mgr:mgrpw')
+        self.applicant_path = 'http://localhost/app/applicants/app2009/%s' % self.pin_applicant
+        self.applicant_view_path = self.applicant_path + '/index'
+        self.applicant_manage_path = self.applicant_path + '/edit_full'
+        self.applicant_slip_path = self.applicant_path + '/application_slip.pdf'
+        self.browser.open(self.applicant_view_path)
+        self.assertEqual(self.browser.headers['Status'], '200 Ok')
+        self.browser.open(self.applicant_slip_path)
+        self.assertEqual(self.browser.headers['Status'], '200 Ok')
+        self.assertEqual(self.browser.headers['Content-Type'], 'application/pdf')
+        self.browser.open(self.applicant_manage_path)
+        self.assertEqual(self.browser.headers['Status'], '200 Ok')
+        self.browser.getControl(name="form.firstname").value = 'Jonathan'
+        self.browser.getControl("Save").click()
+        self.assertTrue('Required input is missing' in self.browser.contents)
+        return
+
+class LoginTest(FunctionalTestCase):
+    # Here we check login view of applicants containers.
+    #
+    # Tests in here do only cover login attempts without any PINs
+    # created before.
+
+    layer = FunctionalLayer
+
+    def setUp(self):
+        super(LoginTest, self).setUp()
+
+        # Setup a sample site for each test
+        app = University()
+        self.dc_root = tempfile.mkdtemp()
+        app['datacenter'].setStoragePath(self.dc_root)
+        self.login_path = 'http://localhost/app/applicants/testapplicants/login'
+
+        # Add an applicants container where we can login (or not)
+        applicantscontainer = ApplicantsContainer()
+        applicantscontainer.ac_prefix = 'APP'
+        app['applicants']['testapplicants'] = applicantscontainer
+
+        # Put the prepopulated site into test ZODB and prepare test
+        # browser
+        self.getRootFolder()['app'] = app
+        self.browser = Browser()
+        self.browser.handleErrors = False
+
+    def tearDown(self):
+        super(LoginTest, self).tearDown()
+        shutil.rmtree(self.dc_root)
+
+    def test_anonymous_access(self):
+        # Anonymous users can access a login page
+        self.browser.open(self.login_path)
+        self.assertEqual(self.browser.headers['Status'], '200 Ok')
+        return
+
+    def test_anonymous_invalid_creds(self):
+        # Anonymous users giving invalid credentials stay at the page
+        self.browser.open(self.login_path)
+        # We do not give credentials but send the form as-is
+        submit = self.browser.getControl(name='SUBMIT')
+        submit.click()
+        # We are still at the same page...
+        self.assertEqual(self.browser.url, self.login_path)
+        self.assertEqual(self.browser.headers['Status'], '200 Ok')
+        return
+
+    def test_anonymous_invalid_creds_warning(self):
+        # Entering wrong credentials will yield a warning
+        self.browser.open(self.login_path)
+        # We do not give credentials but send the form as-is
+        submit = self.browser.getControl(name='SUBMIT')
+        submit.click()
+        self.assertTrue(
+            'Entered credentials are invalid' in self.browser.contents)
+        return
+
+    def test_manager_no_warnings(self):
+        # Browsing the login screen as a manager, won't raise warnings
+        # Authenticate ourself as manager
+        self.browser.addHeader('Authorization', 'Basic mgr:mgrpw')
+        self.browser.open(self.login_path)
+        # Submit the form w/o any credentials
+        self.browser.getControl(name="SUBMIT").click()
+        self.assertTrue(
+            'Entered credentials are invalid' not in self.browser.contents)
+        return
+
+    def test_manager_no_redirect(self):
+        # Browsing the login screen as a manager won't trigger a redirect
+        # Authenticate ourself as manager
+        self.browser.addHeader('Authorization', 'Basic mgr:mgrpw')
+        self.browser.open(self.login_path)
+        # Submit the form w/o any credentials
+        self.browser.getControl(name="SUBMIT").click()
+        self.assertEqual(self.browser.url, self.login_path)
+        return
+
+    def test_display_entered_values(self):
+        # After submit the entered values are displayed in the form
+        self.browser.open(self.login_path)
+        # Enter some value we can look for after submit
+        ac_series = self.browser.getControl(name="form.ac_series")
+        ac_series.value = '666'
+        self.browser.getControl(name="SUBMIT").click()
+        self.assertTrue('666' in self.browser.contents)
+        return
+
+class LoginTestWithPINs(LoginTest):
+    # Here we check login view of applicants containers with PINs provided.
+
+    # As setting up pins is time-consuming we only set them up when
+    # really needed (i.e. in this separate TestCase).
+
+    layer = FunctionalLayer
+
+    def setUp(self):
+        super(LoginTestWithPINs, self).setUp()
+
+        # Create 5 access codes with prefix'FOO' and cost 9.99 each
+        pin_container = self.getRootFolder()['app']['accesscodes']
+        pin_container.createBatch(
+            datetime.now(), 'some_userid', 'APP', 9.99, 5)
+        pins = pin_container[pin_container.keys()[0]].values()
+        self.pins = [x.representation for x in pins]
+        self.existing_pin = self.pins[0]
+        parts = self.existing_pin.split('-')[1:]
+        self.existing_series, self.existing_number = parts
+        self.browser.handleErrors = False
+
     def tearDown(self):
         super(LoginTestWithPINs, self).tearDown()
@@ -184,4 +328,5 @@
     suite = unittest.TestSuite()
     for testcase in [
+        ApplicantsUITests,
         LoginTest,
         LoginTestWithPINs,
