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

Last change on this file since 6495 was 6487, checked in by Henrik Bettermann, 14 years ago

Add test for EditApplicantFull?-Page which is used by applicants. The tests pass but dozens of 'The following test left garbage' warnings appear.

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