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

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

Increase coverage from 58% to 83%.

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