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

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

Split up functional tests a bit.

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