source: main/waeup.sirp/trunk/src/waeup/sirp/applicants/tests/test_browser.py @ 6483

Last change on this file since 6483 was 6483, checked in by uli, 13 years ago

Make browser tests setup work again, finally. I cannot tell, what the
main reason for the problems was. One point was definitely, that the
site object (self.app) was put too late into ZODB. A site must have
been added to the ZODB to have catalogs available, because catalogs
are local utilities and local utilities are set up (event-triggered)
when an associated site is added to the ZODB.

File size: 16.0 KB
Line 
1##
2## test_browser.py
3## Login : <uli@pu.smp.net>
4## Started on  Tue Mar 29 11:31:11 2011 Uli Fouquet
5## $Id$
6##
7## Copyright (C) 2011 Uli Fouquet & Henrik Bettermann
8## This program is free software; you can redistribute it and/or modify
9## it under the terms of the GNU General Public License as published by
10## the Free Software Foundation; either version 2 of the License, or
11## (at your option) any later version.
12##
13## This program is distributed in the hope that it will be useful,
14## but WITHOUT ANY WARRANTY; without even the implied warranty of
15## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16## GNU General Public License for more details.
17##
18## You should have received a copy of the GNU General Public License
19## along with this program; if not, write to the Free Software
20## Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
21##
22"""
23Test the applicant-related UI components.
24"""
25import shutil
26import tempfile
27import unittest
28from datetime import datetime
29from zope.app.testing.functional import FunctionalTestCase
30from zope.app.testing.functional import HTTPCaller as http
31from zope.component import createObject
32from zope.component.hooks import setSite, clearSite
33from zope.security.interfaces import Unauthorized
34from zope.testbrowser.testing import Browser
35from waeup.sirp.testing import FunctionalLayer
36from waeup.sirp.app import University
37from waeup.sirp.applicants.container import ApplicantsContainer
38from waeup.sirp.applicants.applicants import Applicant
39from waeup.sirp.university.faculty import Faculty
40from waeup.sirp.university.department import Department
41from waeup.sirp.university.certificate import Certificate
42from waeup.sirp.university.certificatecontainer import CertificateContainer
43
44class ApplicantsUITests(FunctionalTestCase):
45    # Tests for ApplicantsRoot class
46
47    layer = FunctionalLayer
48
49    def setUp(self):
50        super(ApplicantsUITests, self).setUp()
51
52        # Setup a sample site for each test
53        app = University()
54        self.dc_root = tempfile.mkdtemp()
55        app['datacenter'].setStoragePath(self.dc_root)
56
57        # Prepopulate the ZODB...
58        self.getRootFolder()['app'] = app
59        # we add the site immediately after creation to the
60        # ZODB. Catalogs and other local utilities are not setup
61        # before that step.
62        self.app = self.getRootFolder()['app']
63        # Set site here. Some of the following setup code might need
64        # to access grok.getSite() and should get our new app then
65        setSite(app)
66
67        self.root_path = 'http://localhost/app/applicants/'
68        self.container_path = 'http://localhost/app/applicants/app2009/'
69
70        # Add an applicants container
71        applicantscontainer = ApplicantsContainer()
72        applicantscontainer.ac_prefix = 'APP'
73        applicantscontainer.prefix = 'app'
74        applicantscontainer.year = 2009
75        applicantscontainer.application_category = 'basic'
76        self.app['applicants']['app2009'] = applicantscontainer
77
78        # Populate university
79        certificate = createObject('waeup.Certificate')
80        certificate.code = 'CERT1'
81        certificate.application_category = 'basic'
82        self.app['faculties']['fac1'] = Faculty()
83        self.app['faculties']['fac1']['dep1'] = Department()
84        self.app['faculties']['fac1']['dep1'].certificates.addCertificate(
85            certificate)
86
87        # Put the prepopulated site into test ZODB and prepare test
88        # browser
89        self.browser = Browser()
90        self.browser.handleErrors = False
91
92        # Create 5 access codes with prefix'FOO' and cost 9.99 each
93        pin_container = self.app['accesscodes']
94        pin_container.createBatch(
95            datetime.now(), 'some_userid', 'APP', 9.99, 5)
96        pins = pin_container[pin_container.keys()[0]].values()
97        self.pins = [x.representation for x in pins]
98        self.existing_pin = self.pins[0]
99        parts = self.existing_pin.split('-')[1:]
100        self.existing_series, self.existing_number = parts
101
102        # Add an applicant
103        self.applicant = Applicant()
104        self.pin_applicant = unicode(self.pins[1])
105        self.applicant.access_code = self.pin_applicant
106        app['applicants']['app2009'][self.pin_applicant] = self.applicant
107        return
108
109    def tearDown(self):
110        super(ApplicantsUITests, self).tearDown()
111        clearSite()
112        shutil.rmtree(self.dc_root)
113
114    def test_anonymous_access(self):
115        # Anonymous users can access applicants root and applicants containers
116        self.browser.open(self.root_path)
117        self.assertEqual(self.browser.headers['Status'], '200 Ok')
118        self.assertFalse(
119            'Manage' in self.browser.contents)
120        self.browser.open(self.container_path)
121        self.assertEqual(self.browser.headers['Status'], '200 Ok')
122        self.assertFalse(
123            'Manage' in self.browser.contents)
124        return
125
126    def test_manage_cert_access(self):
127        # Managers can access CERT1
128        cert_path = 'http://localhost/app/faculties/fac1/dep1/certificates/CERT1'
129        self.browser.addHeader('Authorization', 'Basic mgr:mgrpw')
130        self.browser.open(cert_path)
131        self.assertEqual(self.browser.headers['Status'], '200 Ok')
132
133    def test_manage_access(self):
134        # Managers can access the manage pages of applicants root and
135        # applicants containers
136        self.browser.addHeader('Authorization', 'Basic mgr:mgrpw')
137        self.browser.open(self.root_path)
138        self.assertTrue(
139            'Manage application section' in self.browser.contents)
140        self.manage_root_path = self.root_path + '/@@manage'
141        self.manage_container_path = self.container_path + '/@@manage'
142        self.browser.open(self.manage_root_path)
143        self.assertEqual(self.browser.headers['Status'], '200 Ok')
144        self.assertEqual(self.browser.url, self.manage_root_path)
145        self.browser.open(self.manage_container_path)
146        self.assertEqual(self.browser.headers['Status'], '200 Ok')
147        self.assertEqual(self.browser.url, self.manage_container_path)
148        return
149
150    def test_add_delete_container(self):
151        # Managers can add and delete applicants containers
152        self.browser.addHeader('Authorization', 'Basic mgr:mgrpw')
153        self.browser.open(self.root_path)
154        self.add_container_path = self.root_path + '/@@add'
155        self.browser.open(self.add_container_path)
156        self.assertEqual(self.browser.headers['Status'], '200 Ok')
157        self.assertEqual(self.browser.url, self.add_container_path)
158        self.browser.getControl(name="form.prefix").value = ['app']
159        self.browser.getControl("Add applicants container").click()
160        self.assertTrue(
161            'There were errors' in self.browser.contents)
162        self.browser.getControl(name="form.prefix").value = ['app']
163        self.browser.getControl(name="form.year").value = ['2010']
164        self.browser.getControl(name="form.provider").value = [
165            'waeup.sirp.applicants.ApplicantsContainer']
166        self.browser.getControl(name="form.ac_prefix").value = ['APP']
167        self.browser.getControl(name="form.application_category").value = ['basic']
168        self.browser.getControl("Add applicants container").click()
169        self.assertTrue('Added:' in self.browser.contents)
170        ctrl = self.browser.getControl(name='val_id')
171        ctrl.getControl(value='app2010').selected = True
172        self.browser.getControl("Remove selected", index=0).click()
173        self.assertTrue('Successfully removed:' in self.browser.contents)
174        return
175
176    def test_add_delete_applicants(self):
177        # Managers can add and delete applicants
178        self.browser.addHeader('Authorization', 'Basic mgr:mgrpw')
179        self.add_applicant_path = self.container_path + '/addapplicant'
180        self.container_manage_path = self.container_path + '/@@manage'
181        self.browser.open(self.add_applicant_path)
182        self.assertEqual(self.browser.headers['Status'], '200 Ok')
183        self.assertEqual(self.browser.url, self.add_applicant_path)
184        self.browser.getControl(name="form.ac_series").value = self.existing_series
185        self.browser.getControl(name="form.ac_number").value = self.existing_number
186        self.browser.getControl("Create application record").click()
187        self.assertTrue('Application initialized' in self.browser.contents)
188        self.browser.open(self.container_manage_path)
189        self.assertEqual(self.browser.headers['Status'], '200 Ok')
190        ctrl = self.browser.getControl(name='val_id')
191        ctrl.getControl(value=self.existing_pin).selected = True
192        self.browser.getControl("Remove selected", index=0).click()
193        self.assertTrue('Successfully removed:' in self.browser.contents)
194        return
195
196    def test_manage_applicant(self):
197        # Managers can manage applicants
198        self.browser.addHeader('Authorization', 'Basic mgr:mgrpw')
199        self.applicant_path = 'http://localhost/app/applicants/app2009/%s' % self.pin_applicant
200        self.applicant_view_path = self.applicant_path + '/index'
201        self.applicant_manage_path = self.applicant_path + '/edit_full'
202        self.applicant_slip_path = self.applicant_path + '/application_slip.pdf'
203        self.browser.open(self.applicant_view_path)
204        self.assertEqual(self.browser.headers['Status'], '200 Ok')
205        self.browser.open(self.applicant_slip_path)
206        self.assertEqual(self.browser.headers['Status'], '200 Ok')
207        self.assertEqual(self.browser.headers['Content-Type'], 'application/pdf')
208        self.browser.open(self.applicant_manage_path)
209        self.assertEqual(self.browser.headers['Status'], '200 Ok')
210        self.browser.getControl(name="form.firstname").value = 'John'
211        self.browser.getControl(name="form.lastname").value = 'Tester'
212        self.browser.getControl(name="form.course1").value = ['CERT1']
213        self.browser.getControl(name="form.date_of_birth").value = 'Jonathan'
214        self.browser.getControl(name="form.lga").value = ['foreigner']
215        self.browser.getControl(name="form.sex").value = ['m']
216        self.browser.getControl("Save").click()
217        self.assertTrue('Required input is missing' in self.browser.contents)
218        return
219
220class LoginTest(FunctionalTestCase):
221    # Here we check login view of applicants containers.
222    #
223    # Tests in here do only cover login attempts without any PINs
224    # created before.
225
226    layer = FunctionalLayer
227
228    def setUp(self):
229        super(LoginTest, self).setUp()
230
231        # Setup a sample site for each test
232        app = University()
233        self.dc_root = tempfile.mkdtemp()
234        app['datacenter'].setStoragePath(self.dc_root)
235        self.login_path = 'http://localhost/app/applicants/testapplicants/login'
236
237        # Add an applicants container where we can login (or not)
238        applicantscontainer = ApplicantsContainer()
239        applicantscontainer.ac_prefix = 'APP'
240        app['applicants']['testapplicants'] = applicantscontainer
241
242        # Put the prepopulated site into test ZODB and prepare test
243        # browser
244        self.getRootFolder()['app'] = app
245        self.browser = Browser()
246        self.browser.handleErrors = False
247
248    def tearDown(self):
249        super(LoginTest, self).tearDown()
250        shutil.rmtree(self.dc_root)
251
252    def test_anonymous_access(self):
253        # Anonymous users can access a login page
254        self.browser.open(self.login_path)
255        self.assertEqual(self.browser.headers['Status'], '200 Ok')
256        return
257
258    def test_anonymous_invalid_creds(self):
259        # Anonymous users giving invalid credentials stay at the page
260        self.browser.open(self.login_path)
261        # We do not give credentials but send the form as-is
262        submit = self.browser.getControl(name='SUBMIT')
263        submit.click()
264        # We are still at the same page...
265        self.assertEqual(self.browser.url, self.login_path)
266        self.assertEqual(self.browser.headers['Status'], '200 Ok')
267        return
268
269    def test_anonymous_invalid_creds_warning(self):
270        # Entering wrong credentials will yield a warning
271        self.browser.open(self.login_path)
272        # We do not give credentials but send the form as-is
273        submit = self.browser.getControl(name='SUBMIT')
274        submit.click()
275        self.assertTrue(
276            'Entered credentials are invalid' in self.browser.contents)
277        return
278
279    def test_manager_no_warnings(self):
280        # Browsing the login screen as a manager, won't raise warnings
281        # Authenticate ourself as manager
282        self.browser.addHeader('Authorization', 'Basic mgr:mgrpw')
283        self.browser.open(self.login_path)
284        # Submit the form w/o any credentials
285        self.browser.getControl(name="SUBMIT").click()
286        self.assertTrue(
287            'Entered credentials are invalid' not in self.browser.contents)
288        return
289
290    def test_manager_no_redirect(self):
291        # Browsing the login screen as a manager won't trigger a redirect
292        # Authenticate ourself as manager
293        self.browser.addHeader('Authorization', 'Basic mgr:mgrpw')
294        self.browser.open(self.login_path)
295        # Submit the form w/o any credentials
296        self.browser.getControl(name="SUBMIT").click()
297        self.assertEqual(self.browser.url, self.login_path)
298        return
299
300    def test_display_entered_values(self):
301        # After submit the entered values are displayed in the form
302        self.browser.open(self.login_path)
303        # Enter some value we can look for after submit
304        ac_series = self.browser.getControl(name="form.ac_series")
305        ac_series.value = '666'
306        self.browser.getControl(name="SUBMIT").click()
307        self.assertTrue('666' in self.browser.contents)
308        return
309
310class LoginTestWithPINs(LoginTest):
311    # Here we check login view of applicants containers with PINs provided.
312
313    # As setting up pins is time-consuming we only set them up when
314    # really needed (i.e. in this separate TestCase).
315
316    layer = FunctionalLayer
317
318    def setUp(self):
319        super(LoginTestWithPINs, self).setUp()
320
321        # Create 5 access codes with prefix'FOO' and cost 9.99 each
322        pin_container = self.getRootFolder()['app']['accesscodes']
323        pin_container.createBatch(
324            datetime.now(), 'some_userid', 'APP', 9.99, 5)
325        pins = pin_container[pin_container.keys()[0]].values()
326        self.pins = [x.representation for x in pins]
327        self.existing_pin = self.pins[0]
328        parts = self.existing_pin.split('-')[1:]
329        self.existing_series, self.existing_number = parts
330        self.browser.handleErrors = False
331
332    def tearDown(self):
333        super(LoginTestWithPINs, self).tearDown()
334
335    def test_anonymous_valid_login(self):
336        # If we enter valid credentials, we get to the applicants form
337        self.browser.open(self.login_path)
338        # Enter some value we can look for after submit
339        ac_series = self.browser.getControl(name="form.ac_series")
340        ac_series.value = self.existing_series
341        ac_number = self.browser.getControl(name="form.ac_number")
342        ac_number.value = self.existing_number
343        self.browser.getControl(name="SUBMIT").click()
344        # We should be redirected to applicants form.
345        self.assertTrue(self.browser.url != self.login_path)
346        return
347
348    def test_anonymous_invalid_login(self):
349        # If we enter wrong credentials we won't get far
350        self.browser.open(self.login_path)
351        # Enter some value we can look for after submit
352        ac_series = self.browser.getControl(name="form.ac_series")
353        ac_series.value = 'illegal series'
354        ac_number = self.browser.getControl(name="form.ac_number")
355        ac_number.value = 'invalid number'
356        self.browser.getControl(name="SUBMIT").click()
357        # We get a warning message
358        self.assertTrue(
359            'Entered credentials are invalid' in self.browser.contents)
360        # We stay at the login page (no redirect)
361        self.assertTrue(self.browser.url == self.login_path)
362        return
363
364
365def suite():
366    suite = unittest.TestSuite()
367    for testcase in [
368        ApplicantsUITests,
369        LoginTest,
370        LoginTestWithPINs,
371            ]:
372        suite.addTests(unittest.makeSuite(testcase))
373    return suite
374
375test_suite = suite
Note: See TracBrowser for help on using the repository browser.