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

Last change on this file since 6484 was 6484, checked in by Henrik Bettermann, 13 years ago

Indeed the test passes now.

File size: 15.9 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.date_of_birth").value = '09/09/1988'
213        self.browser.getControl(name="form.lga").value = ['foreigner']
214        self.browser.getControl(name="form.sex").value = ['m']
215        self.browser.getControl("Save").click()
216        self.assertMatches('...Form has been saved...', self.browser.contents)
217        return
218
219class LoginTest(FunctionalTestCase):
220    # Here we check login view of applicants containers.
221    #
222    # Tests in here do only cover login attempts without any PINs
223    # created before.
224
225    layer = FunctionalLayer
226
227    def setUp(self):
228        super(LoginTest, self).setUp()
229
230        # Setup a sample site for each test
231        app = University()
232        self.dc_root = tempfile.mkdtemp()
233        app['datacenter'].setStoragePath(self.dc_root)
234        self.login_path = 'http://localhost/app/applicants/testapplicants/login'
235
236        # Add an applicants container where we can login (or not)
237        applicantscontainer = ApplicantsContainer()
238        applicantscontainer.ac_prefix = 'APP'
239        app['applicants']['testapplicants'] = applicantscontainer
240
241        # Put the prepopulated site into test ZODB and prepare test
242        # browser
243        self.getRootFolder()['app'] = app
244        self.browser = Browser()
245        self.browser.handleErrors = False
246
247    def tearDown(self):
248        super(LoginTest, self).tearDown()
249        shutil.rmtree(self.dc_root)
250
251    def test_anonymous_access(self):
252        # Anonymous users can access a login page
253        self.browser.open(self.login_path)
254        self.assertEqual(self.browser.headers['Status'], '200 Ok')
255        return
256
257    def test_anonymous_invalid_creds(self):
258        # Anonymous users giving invalid credentials stay at the page
259        self.browser.open(self.login_path)
260        # We do not give credentials but send the form as-is
261        submit = self.browser.getControl(name='SUBMIT')
262        submit.click()
263        # We are still at the same page...
264        self.assertEqual(self.browser.url, self.login_path)
265        self.assertEqual(self.browser.headers['Status'], '200 Ok')
266        return
267
268    def test_anonymous_invalid_creds_warning(self):
269        # Entering wrong credentials will yield a warning
270        self.browser.open(self.login_path)
271        # We do not give credentials but send the form as-is
272        submit = self.browser.getControl(name='SUBMIT')
273        submit.click()
274        self.assertTrue(
275            'Entered credentials are invalid' in self.browser.contents)
276        return
277
278    def test_manager_no_warnings(self):
279        # Browsing the login screen as a manager, won't raise warnings
280        # Authenticate ourself as manager
281        self.browser.addHeader('Authorization', 'Basic mgr:mgrpw')
282        self.browser.open(self.login_path)
283        # Submit the form w/o any credentials
284        self.browser.getControl(name="SUBMIT").click()
285        self.assertTrue(
286            'Entered credentials are invalid' not in self.browser.contents)
287        return
288
289    def test_manager_no_redirect(self):
290        # Browsing the login screen as a manager won't trigger a redirect
291        # Authenticate ourself as manager
292        self.browser.addHeader('Authorization', 'Basic mgr:mgrpw')
293        self.browser.open(self.login_path)
294        # Submit the form w/o any credentials
295        self.browser.getControl(name="SUBMIT").click()
296        self.assertEqual(self.browser.url, self.login_path)
297        return
298
299    def test_display_entered_values(self):
300        # After submit the entered values are displayed in the form
301        self.browser.open(self.login_path)
302        # Enter some value we can look for after submit
303        ac_series = self.browser.getControl(name="form.ac_series")
304        ac_series.value = '666'
305        self.browser.getControl(name="SUBMIT").click()
306        self.assertTrue('666' in self.browser.contents)
307        return
308
309class LoginTestWithPINs(LoginTest):
310    # Here we check login view of applicants containers with PINs provided.
311
312    # As setting up pins is time-consuming we only set them up when
313    # really needed (i.e. in this separate TestCase).
314
315    layer = FunctionalLayer
316
317    def setUp(self):
318        super(LoginTestWithPINs, self).setUp()
319
320        # Create 5 access codes with prefix'FOO' and cost 9.99 each
321        pin_container = self.getRootFolder()['app']['accesscodes']
322        pin_container.createBatch(
323            datetime.now(), 'some_userid', 'APP', 9.99, 5)
324        pins = pin_container[pin_container.keys()[0]].values()
325        self.pins = [x.representation for x in pins]
326        self.existing_pin = self.pins[0]
327        parts = self.existing_pin.split('-')[1:]
328        self.existing_series, self.existing_number = parts
329        self.browser.handleErrors = False
330
331    def tearDown(self):
332        super(LoginTestWithPINs, self).tearDown()
333
334    def test_anonymous_valid_login(self):
335        # If we enter valid credentials, we get to the applicants form
336        self.browser.open(self.login_path)
337        # Enter some value we can look for after submit
338        ac_series = self.browser.getControl(name="form.ac_series")
339        ac_series.value = self.existing_series
340        ac_number = self.browser.getControl(name="form.ac_number")
341        ac_number.value = self.existing_number
342        self.browser.getControl(name="SUBMIT").click()
343        # We should be redirected to applicants form.
344        self.assertTrue(self.browser.url != self.login_path)
345        return
346
347    def test_anonymous_invalid_login(self):
348        # If we enter wrong credentials we won't get far
349        self.browser.open(self.login_path)
350        # Enter some value we can look for after submit
351        ac_series = self.browser.getControl(name="form.ac_series")
352        ac_series.value = 'illegal series'
353        ac_number = self.browser.getControl(name="form.ac_number")
354        ac_number.value = 'invalid number'
355        self.browser.getControl(name="SUBMIT").click()
356        # We get a warning message
357        self.assertTrue(
358            'Entered credentials are invalid' in self.browser.contents)
359        # We stay at the login page (no redirect)
360        self.assertTrue(self.browser.url == self.login_path)
361        return
362
363
364def suite():
365    suite = unittest.TestSuite()
366    for testcase in [
367        ApplicantsUITests,
368        LoginTest,
369        LoginTestWithPINs,
370            ]:
371        suite.addTests(unittest.makeSuite(testcase))
372    return suite
373
374test_suite = suite
Note: See TracBrowser for help on using the repository browser.