source: main/waeup.sirp/trunk/src/waeup/sirp/students/tests/test_browser.py @ 6764

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

Add functional workflow transition tests.

  • Property svn:keywords set to Id
File size: 17.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: test_browser.py 6763 2011-09-14 07:14:50Z henrik $
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 student-related UI components.
24"""
25import shutil
26import tempfile
27from datetime import datetime
28from zope.component import createObject
29from zope.component.hooks import setSite, clearSite
30from zope.security.interfaces import Unauthorized
31from zope.testbrowser.testing import Browser
32from waeup.sirp.testing import FunctionalLayer, FunctionalTestCase
33from waeup.sirp.app import University
34from waeup.sirp.students.student import Student
35from waeup.sirp.university.faculty import Faculty
36from waeup.sirp.university.department import Department
37from waeup.sirp.interfaces import IUserAccount
38
39PH_LEN = 2059  # Length of placeholder file
40
41class StudentsFullSetup(FunctionalTestCase):
42    # A test case that only contains a setup and teardown
43    #
44    # Complete setup for students handlings is rather complex and
45    # requires lots of things created before we can start. This is a
46    # setup that does all this, creates a university, creates PINs,
47    # etc.  so that we do not have to bother with that in different
48    # test cases.
49
50    layer = FunctionalLayer
51
52    def setUp(self):
53        super(StudentsFullSetup, self).setUp()
54
55        # Setup a sample site for each test
56        app = University()
57        self.dc_root = tempfile.mkdtemp()
58        app['datacenter'].setStoragePath(self.dc_root)
59
60        # Prepopulate the ZODB...
61        self.getRootFolder()['app'] = app
62        # we add the site immediately after creation to the
63        # ZODB. Catalogs and other local utilities are not setup
64        # before that step.
65        self.app = self.getRootFolder()['app']
66        # Set site here. Some of the following setup code might need
67        # to access grok.getSite() and should get our new app then
68        setSite(app)
69
70        # Add student with subobjects (done by addStudent)
71        student = Student()
72        student.name = u'Anna Tester'
73        student.reg_number = u'123'
74        student.matric_number = u'234'
75        self.test_student_id = self.app['students'].addStudent(student)
76        # Set password
77        IUserAccount(
78            self.app['students'][self.test_student_id]).setPassword('spwd')
79
80        self.login_path = 'http://localhost/app/login'
81        self.container_path = 'http://localhost/app/students'
82        self.manage_container_path = self.container_path + '/@@manage'
83        self.add_student_path = self.container_path + '/addstudent'
84        self.student_path = self.container_path + '/' + self.test_student_id
85        self.manage_student_path = self.student_path + '/edit_base'
86        self.clearance_student_path = self.student_path + '/view_clearance'
87        self.personal_student_path = self.student_path + '/view_personal'
88        self.edit_clearance_student_path = self.student_path + '/edit_clearance'
89        self.edit_personal_student_path = self.student_path + '/edit_personal'
90
91        self.studycourse_student_path = self.student_path + '/studycourse'
92        self.payments_student_path = self.student_path + '/payments'
93        self.accommodation_student_path = self.student_path + '/accommodation'
94        self.history_student_path = self.student_path + '/history'
95
96        # Create 5 access codes with prefix'PWD' and cost 9.99 each
97        pin_container = self.app['accesscodes']
98        pin_container.createBatch(
99            datetime.now(), 'some_userid', 'PWD', 9.99, 5)
100        pins = pin_container[pin_container.keys()[0]].values()
101        self.pins = [x.representation for x in pins]
102        self.existing_pin = self.pins[0]
103        parts = self.existing_pin.split('-')[1:]
104        self.existing_series, self.existing_number = parts
105
106        # Populate university
107        certificate = createObject('waeup.Certificate')
108        certificate.code = 'CERT1'
109        certificate.application_category = 'basic'
110        certificate.start_level = 100
111        certificate.end_level = 500
112        self.app['faculties']['fac1'] = Faculty()
113        self.app['faculties']['fac1']['dep1'] = Department()
114        self.app['faculties']['fac1']['dep1'].certificates.addCertificate(
115            certificate)
116
117        # Put the prepopulated site into test ZODB and prepare test
118        # browser
119        self.browser = Browser()
120        self.browser.handleErrors = False
121
122    def tearDown(self):
123        super(StudentsFullSetup, self).tearDown()
124        clearSite()
125        shutil.rmtree(self.dc_root)
126
127
128
129class StudentsContainerUITests(StudentsFullSetup):
130    # Tests for StudentsContainer class views and pages
131
132    layer = FunctionalLayer
133
134    def test_anonymous_access(self):
135        # Anonymous users can't access students containers
136        self.assertRaises(
137            Unauthorized, self.browser.open, self.container_path)
138        self.assertRaises(
139            Unauthorized, self.browser.open, self.manage_container_path)
140        return
141
142    def test_manage_access(self):
143        # Managers can access the view page of students
144        # containers and can perform actions
145        self.browser.addHeader('Authorization', 'Basic mgr:mgrpw')
146        self.browser.open(self.container_path)
147        self.assertEqual(self.browser.headers['Status'], '200 Ok')
148        self.assertEqual(self.browser.url, self.container_path)
149        self.browser.getLink("Manage student section").click()
150        self.assertEqual(self.browser.headers['Status'], '200 Ok')
151        self.assertEqual(self.browser.url, self.manage_container_path)
152        return
153
154    def test_add_search_delete_students(self):
155        # Managers can add search and remove students
156        self.browser.addHeader('Authorization', 'Basic mgr:mgrpw')
157        self.browser.open(self.manage_container_path)
158        self.browser.getLink("Add student").click()
159        self.assertEqual(self.browser.headers['Status'], '200 Ok')
160        self.assertEqual(self.browser.url, self.add_student_path)
161        self.browser.getControl(name="form.name").value = 'Bob Tester'
162        self.browser.getControl("Create student record").click()
163        self.assertTrue('Student record created' in self.browser.contents)
164
165        # Registration numbers must be unique
166        self.browser.getLink("Manage").click()
167        self.browser.getControl(name="form.reg_number").value = '123'
168        self.browser.getControl("Save").click()
169        self.assertMatches('...value already exists in catalog...',
170                           self.browser.contents)
171
172        self.browser.open(self.container_path)
173        self.browser.getControl("Search").click()
174        self.assertTrue('Empty search string' in self.browser.contents)
175        self.browser.getControl(name="searchtype").value = ['student_id']
176        self.browser.getControl(name="searchterm").value = self.test_student_id
177        self.browser.getControl("Search").click()
178        self.assertTrue('Anna Tester' in self.browser.contents)
179
180        self.browser.open(self.manage_container_path)
181        self.browser.getControl("Search").click()
182        self.assertTrue('Empty search string' in self.browser.contents)
183        self.browser.getControl(name="searchtype").value = ['name']
184        self.browser.getControl(name="searchterm").value = 'Anna Tester'
185        self.browser.getControl("Search").click()
186        self.assertTrue('Anna Tester' in self.browser.contents)
187        # The old searchterm will be used again
188        self.browser.getControl("Search").click()
189        self.assertTrue('Anna Tester' in self.browser.contents)
190
191        ctrl = self.browser.getControl(name='entries')
192        ctrl.getControl(value=self.test_student_id).selected = True
193        self.browser.getControl("Remove selected", index=0).click()
194        self.assertTrue('Successfully removed' in self.browser.contents)
195        self.browser.getControl(name="searchtype").value = ['student_id']
196        self.browser.getControl(name="searchterm").value = self.test_student_id
197        self.browser.getControl("Search").click()
198        self.assertTrue('No student found' in self.browser.contents)
199
200        self.browser.open(self.container_path)
201        self.browser.getControl(name="searchtype").value = ['student_id']
202        self.browser.getControl(name="searchterm").value = self.test_student_id
203        self.browser.getControl("Search").click()
204        self.assertTrue('No student found' in self.browser.contents)
205
206class StudentUITests(StudentsFullSetup):
207    # Tests for Student class views and pages
208
209    layer = FunctionalLayer
210
211    def test_manage_access(self):
212        # Managers can access the pages of students
213        # and can perform actions
214        self.browser.addHeader('Authorization', 'Basic mgr:mgrpw')
215
216        self.browser.open(self.student_path)
217        self.assertEqual(self.browser.headers['Status'], '200 Ok')
218        self.assertEqual(self.browser.url, self.student_path)
219        self.browser.getLink("Manage").click()
220        self.assertEqual(self.browser.headers['Status'], '200 Ok')
221        self.assertEqual(self.browser.url, self.manage_student_path)
222        # Managers can edit base data and fire transitions
223        self.browser.getControl(name="transition").value = ['admit']
224        self.browser.getControl(name="form.name").value = 'John Tester'
225        self.browser.getControl(name="form.reg_number").value = '123'
226        self.browser.getControl(name="password").value = 'secret'
227        self.browser.getControl(name="control_password").value = 'secret'
228        self.browser.getControl("Save").click()
229        self.assertMatches('...Form has been saved...',
230                           self.browser.contents)
231        self.browser.open(self.student_path)
232        self.browser.getLink("Clearance Data").click()
233        self.assertEqual(self.browser.headers['Status'], '200 Ok')
234        self.assertEqual(self.browser.url, self.clearance_student_path)
235        self.browser.getLink("Manage").click()
236        self.assertEqual(self.browser.headers['Status'], '200 Ok')
237        self.assertEqual(self.browser.url, self.edit_clearance_student_path)
238
239        self.browser.open(self.student_path)
240        self.browser.getLink("Personal Data").click()
241        self.assertEqual(self.browser.headers['Status'], '200 Ok')
242        self.assertEqual(self.browser.url, self.personal_student_path)
243        self.browser.getLink("Manage").click()
244        self.assertEqual(self.browser.headers['Status'], '200 Ok')
245        self.assertEqual(self.browser.url, self.edit_personal_student_path)
246
247        self.browser.open(self.student_path)
248        self.browser.getLink("Study Course").click()
249        self.assertEqual(self.browser.headers['Status'], '200 Ok')
250        self.assertEqual(self.browser.url, self.studycourse_student_path)
251        self.browser.getLink("Manage").click()
252        self.assertTrue('Manage study course' in self.browser.contents)
253        # Before we can select a level, the certificate must be selected and saved
254        self.browser.getControl(name="form.certificate").value = ['CERT1']
255        self.browser.getControl(name="form.current_session").value = ['2004']
256        self.browser.getControl(name="form.current_verdict").value = ['A']
257        self.browser.getControl("Save").click()
258        # Now we can save also the current level which depends on start and end
259        # level of the certificate
260        self.browser.getControl(name="form.current_level").value = ['100']
261        self.browser.getControl("Save").click()
262
263        self.browser.open(self.student_path)
264        self.browser.getLink("Payments").click()
265        self.assertEqual(self.browser.headers['Status'], '200 Ok')
266        self.assertEqual(self.browser.url, self.payments_student_path)
267
268        self.browser.open(self.student_path)
269        self.browser.getLink("Accommodation").click()
270        self.assertEqual(self.browser.headers['Status'], '200 Ok')
271        self.assertEqual(self.browser.url, self.accommodation_student_path)
272
273        self.browser.open(self.student_path)
274        self.browser.getLink("History").click()
275        self.assertEqual(self.browser.headers['Status'], '200 Ok')
276        self.assertEqual(self.browser.url, self.history_student_path)
277        self.assertMatches('...Student admitted by zope.mgr...',
278                           self.browser.contents)
279
280        # Managers can pass through the whole workflow
281        student = self.app['students'][self.test_student_id]
282        self.browser.open(self.manage_student_path)
283        self.assertTrue(student.clearance_locked)
284        self.browser.getControl(name="transition").value = ['start_clearance']
285        self.browser.getControl("Save").click()
286        self.assertFalse(student.clearance_locked)
287        self.browser.getControl(name="transition").value = ['request_clearance']
288        self.browser.getControl("Save").click()
289        self.assertTrue(student.clearance_locked)
290        self.browser.getControl(name="transition").value = ['clear']
291        self.browser.getControl("Save").click()
292        self.browser.getControl(name="transition").value = ['pay_first_school_fee']
293        self.browser.getControl("Save").click()
294        self.browser.getControl(name="transition").value = ['reset6']
295        self.browser.getControl("Save").click()
296        # The pay_school_fee transition triggers some changes
297        self.browser.getControl(name="transition").value = ['pay_school_fee']
298        self.browser.getControl("Save").click()
299        self.assertEqual(student['studycourse'].current_session, 2005) # was 2004
300        self.assertEqual(student['studycourse'].current_level, 200) # was 100
301        self.assertEqual(student['studycourse'].current_verdict, '') # was 'A'
302        self.assertEqual(student['studycourse'].previous_verdict, 'A') # was empty
303        return
304
305    def test_student_access(self):
306        # Students can access their own objects
307        # and can perform actions
308        self.browser.open(self.login_path)
309        self.browser.getControl(name="form.login").value = self.test_student_id
310        self.browser.getControl(name="form.password").value = 'spwd'
311        self.browser.getControl("Login").click()
312        self.assertEqual(self.browser.url, self.student_path)
313        self.assertTrue('You logged in' in self.browser.contents)
314        # Change password
315        self.browser.getLink("Change password").click()
316        self.browser.getControl(name="form.password").value = 'new_password'
317        self.browser.getControl(
318            name="form.password_repeat").value = 'new_password'
319        self.browser.getControl("Save").click()
320        self.assertTrue('Form has been saved' in self.browser.contents)
321        # We are still logged in. Changing the password hasn't thrown us out.
322        self.browser.getLink("My Data").click()
323        self.assertEqual(self.browser.url, self.student_path)
324        # We can logout
325        self.browser.getLink("Logout").click()
326        self.assertTrue('You have been logged out' in self.browser.contents)
327        self.assertEqual(self.browser.url, 'http://localhost/app')
328        # We can login again with the new password
329        self.browser.getLink("Login").click()
330        self.browser.open(self.login_path)
331        self.browser.getControl(name="form.login").value = self.test_student_id
332        self.browser.getControl(name="form.password").value = 'new_password'
333        self.browser.getControl("Login").click()
334        self.assertEqual(self.browser.url, self.student_path)
335        self.assertTrue('You logged in' in self.browser.contents)
336        return
337
338    def test_setpassword(self):
339        # Set password for first-time access
340        # Add student with subobjects (done by addStudent)
341        student = Student()
342        student.reg_number = u'123456'
343        student.name = u'Klaus Tester'
344        test_student_id = self.app['students'].addStudent(student)
345        setpassword_path = 'http://localhost/app/setpassword'
346        student_path = 'http://localhost/app/students/%s' % test_student_id
347        self.browser.open(setpassword_path)
348        self.browser.getControl(name="ac_series").value = self.existing_series
349        self.browser.getControl(name="ac_number").value = self.existing_number
350        self.browser.getControl(name="reg_number").value = '123456'
351        self.browser.getControl("Show").click()
352        self.assertMatches('...Password has been set. Your Student Id is...',
353                           self.browser.contents)
354        # The student can login with the new credentials
355        self.browser.open(self.login_path)
356        self.browser.getControl(name="form.login").value = test_student_id
357        self.browser.getControl(
358            name="form.password").value = self.existing_number
359        self.browser.getControl("Login").click()
360        self.assertEqual(self.browser.url, student_path)
361        self.assertTrue('You logged in' in self.browser.contents)
362        return
Note: See TracBrowser for help on using the repository browser.