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

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

Increase test coverage.

  • Property svn:keywords set to Id
File size: 33.6 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 6914 2011-10-20 16:48:59Z 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
27import cStringIO
28from datetime import datetime
29from zope.component import createObject
30from zope.component.hooks import setSite, clearSite
31from zope.security.interfaces import Unauthorized
32from zope.testbrowser.testing import Browser
33from hurry.workflow.interfaces import IWorkflowInfo
34from waeup.sirp.testing import FunctionalLayer, FunctionalTestCase
35from waeup.sirp.app import University
36from waeup.sirp.students.student import Student
37from waeup.sirp.university.faculty import Faculty
38from waeup.sirp.university.department import Department
39from waeup.sirp.interfaces import IUserAccount
40
41PH_LEN = 2059  # Length of placeholder file
42
43def lookup_submit_value(name, value, browser):
44    """Find a button with a certain value."""
45    for num in range(0, 100):
46        try:
47            button = browser.getControl(name=name, index=num)
48            if button.value.endswith(value):
49                return button
50        except IndexError:
51            break
52    return None
53
54class StudentsFullSetup(FunctionalTestCase):
55    # A test case that only contains a setup and teardown
56    #
57    # Complete setup for students handlings is rather complex and
58    # requires lots of things created before we can start. This is a
59    # setup that does all this, creates a university, creates PINs,
60    # etc.  so that we do not have to bother with that in different
61    # test cases.
62
63    layer = FunctionalLayer
64
65    def setUp(self):
66        super(StudentsFullSetup, self).setUp()
67
68        # Setup a sample site for each test
69        app = University()
70        self.dc_root = tempfile.mkdtemp()
71        app['datacenter'].setStoragePath(self.dc_root)
72
73        # Prepopulate the ZODB...
74        self.getRootFolder()['app'] = app
75        # we add the site immediately after creation to the
76        # ZODB. Catalogs and other local utilities are not setup
77        # before that step.
78        self.app = self.getRootFolder()['app']
79        # Set site here. Some of the following setup code might need
80        # to access grok.getSite() and should get our new app then
81        setSite(app)
82
83        # Add student with subobjects
84        student = Student()
85        student.fullname = u'Anna Tester'
86        student.reg_number = u'123'
87        student.matric_number = u'234'
88        self.app['students'].addStudent(student)
89        self.student_id = student.student_id
90        self.student = self.app['students'][self.student_id]
91
92        # Set password
93        IUserAccount(
94            self.app['students'][self.student_id]).setPassword('spwd')
95
96        self.login_path = 'http://localhost/app/login'
97        self.container_path = 'http://localhost/app/students'
98        self.manage_container_path = self.container_path + '/@@manage'
99        self.add_student_path = self.container_path + '/addstudent'
100        self.student_path = self.container_path + '/' + self.student_id
101        self.manage_student_path = self.student_path + '/edit_base'
102        self.clearance_student_path = self.student_path + '/view_clearance'
103        self.personal_student_path = self.student_path + '/view_personal'
104        self.edit_clearance_student_path = self.student_path + '/edit_clearance'
105        self.edit_personal_student_path = self.student_path + '/edit_personal'
106
107        self.studycourse_student_path = self.student_path + '/studycourse'
108        self.payments_student_path = self.student_path + '/payments'
109        self.accommodation_student_path = self.student_path + '/accommodation'
110        self.history_student_path = self.student_path + '/history'
111
112        # Create 5 access codes with prefix'PWD'
113        pin_container = self.app['accesscodes']
114        pin_container.createBatch(
115            datetime.now(), 'some_userid', 'PWD', 9.99, 5)
116        pins = pin_container[pin_container.keys()[0]].values()
117        self.pwdpins = [x.representation for x in pins]
118        self.existing_pwdpin = self.pwdpins[0]
119        parts = self.existing_pwdpin.split('-')[1:]
120        self.existing_pwdseries, self.existing_pwdnumber = parts
121        # Create 5 access codes with prefix 'CLR'
122        pin_container.createBatch(
123            datetime.now(), 'some_userid', 'CLR', 9.99, 5)
124        pins = pin_container[pin_container.keys()[0]].values()
125        self.clrpins = [x.representation for x in pins]
126        self.existing_clrpin = self.clrpins[0]
127        self.existing_clrpin
128        parts = self.existing_clrpin.split('-')[1:]
129        self.existing_clrseries, self.existing_clrnumber = parts
130
131        # Populate university
132        self.certificate = createObject('waeup.Certificate')
133        self.certificate.code = u'CERT1'
134        self.certificate.application_category = 'basic'
135        self.certificate.study_mode = 'ug_ft'
136        self.certificate.start_level = 100
137        self.certificate.end_level = 500
138        self.app['faculties']['fac1'] = Faculty()
139        self.app['faculties']['fac1']['dep1'] = Department()
140        self.app['faculties']['fac1']['dep1'].certificates.addCertificate(
141            self.certificate)
142        self.course = createObject('waeup.Course')
143        self.course.code = 'COURSE1'
144        self.course.semester = 1
145        self.course.credits = 10
146        self.course.passmark = 40
147        self.app['faculties']['fac1']['dep1'].courses.addCourse(
148            self.course)
149        self.app['faculties']['fac1']['dep1'].certificates['CERT1'].addCourseRef(
150            self.course, level=100)
151
152        # Set study course attributes of test student
153        self.student['studycourse'].certificate = self.certificate
154        self.student['studycourse'].current_session = 2004
155        self.student['studycourse'].current_verdict = 'A'
156        self.student['studycourse'].current_level = 100
157
158        # Put the prepopulated site into test ZODB and prepare test
159        # browser
160        self.browser = Browser()
161        self.browser.handleErrors = False
162
163    def tearDown(self):
164        super(StudentsFullSetup, self).tearDown()
165        clearSite()
166        shutil.rmtree(self.dc_root)
167
168
169
170class StudentsContainerUITests(StudentsFullSetup):
171    # Tests for StudentsContainer class views and pages
172
173    layer = FunctionalLayer
174
175    def test_anonymous_access(self):
176        # Anonymous users can't access students containers
177        self.assertRaises(
178            Unauthorized, self.browser.open, self.container_path)
179        self.assertRaises(
180            Unauthorized, self.browser.open, self.manage_container_path)
181        return
182
183    def test_manage_access(self):
184        # Managers can access the view page of students
185        # containers and can perform actions
186        self.browser.addHeader('Authorization', 'Basic mgr:mgrpw')
187        self.browser.open(self.container_path)
188        self.assertEqual(self.browser.headers['Status'], '200 Ok')
189        self.assertEqual(self.browser.url, self.container_path)
190        self.browser.getLink("Manage student section").click()
191        self.assertEqual(self.browser.headers['Status'], '200 Ok')
192        self.assertEqual(self.browser.url, self.manage_container_path)
193        return
194
195    def test_add_search_delete_students(self):
196        # Managers can add search and remove students
197        self.browser.addHeader('Authorization', 'Basic mgr:mgrpw')
198        self.browser.open(self.manage_container_path)
199        self.browser.getLink("Add student").click()
200        self.assertEqual(self.browser.headers['Status'], '200 Ok')
201        self.assertEqual(self.browser.url, self.add_student_path)
202        self.browser.getControl(name="form.fullname").value = 'Bob Tester'
203        self.browser.getControl("Create student record").click()
204        self.assertTrue('Student record created' in self.browser.contents)
205
206        # Registration and matric numbers must be unique
207        self.browser.getLink("Manage").click()
208        self.browser.getControl(name="form.reg_number").value = '123'
209        self.browser.getControl("Save").click()
210        self.assertMatches('...Registration number exists...',
211                           self.browser.contents)
212        self.browser.getControl(name="form.reg_number").value = '789'
213        self.browser.getControl(name="form.matric_number").value = '234'
214        self.browser.getControl("Save").click()
215        self.assertMatches('...Matriculation number exists...',
216                           self.browser.contents)
217
218        self.browser.open(self.container_path)
219        self.browser.getControl("Search").click()
220        self.assertTrue('Empty search string' in self.browser.contents)
221        self.browser.getControl(name="searchtype").value = ['student_id']
222        self.browser.getControl(name="searchterm").value = self.student_id
223        self.browser.getControl("Search").click()
224        self.assertTrue('Anna Tester' in self.browser.contents)
225
226        self.browser.open(self.manage_container_path)
227        self.browser.getControl("Search").click()
228        self.assertTrue('Empty search string' in self.browser.contents)
229        self.browser.getControl(name="searchtype").value = ['fullname']
230        self.browser.getControl(name="searchterm").value = 'Anna Tester'
231        self.browser.getControl("Search").click()
232        self.assertTrue('Anna Tester' in self.browser.contents)
233        # The old searchterm will be used again
234        self.browser.getControl("Search").click()
235        self.assertTrue('Anna Tester' in self.browser.contents)
236
237        ctrl = self.browser.getControl(name='entries')
238        ctrl.getControl(value=self.student_id).selected = True
239        self.browser.getControl("Remove selected", index=0).click()
240        self.assertTrue('Successfully removed' in self.browser.contents)
241        self.browser.getControl(name="searchtype").value = ['student_id']
242        self.browser.getControl(name="searchterm").value = self.student_id
243        self.browser.getControl("Search").click()
244        self.assertTrue('No student found' in self.browser.contents)
245
246        self.browser.open(self.container_path)
247        self.browser.getControl(name="searchtype").value = ['student_id']
248        self.browser.getControl(name="searchterm").value = self.student_id
249        self.browser.getControl("Search").click()
250        self.assertTrue('No student found' in self.browser.contents)
251        return
252
253class StudentUITests(StudentsFullSetup):
254    # Tests for Student class views and pages
255
256    layer = FunctionalLayer
257
258    def test_manage_access(self):
259        # Managers can access the pages of students
260        # and can perform actions
261        self.browser.addHeader('Authorization', 'Basic mgr:mgrpw')
262
263        self.browser.open(self.student_path)
264        self.assertEqual(self.browser.headers['Status'], '200 Ok')
265        self.assertEqual(self.browser.url, self.student_path)
266        self.browser.getLink("Manage").click()
267        self.assertEqual(self.browser.headers['Status'], '200 Ok')
268        self.assertEqual(self.browser.url, self.manage_student_path)
269        # Managers can edit base data and fire transitions
270        self.browser.getControl(name="transition").value = ['admit']
271        self.browser.getControl(name="form.fullname").value = 'John Tester'
272        self.browser.getControl(name="form.reg_number").value = '345'
273        self.browser.getControl(name="password").value = 'secret'
274        self.browser.getControl(name="control_password").value = 'secret'
275        self.browser.getControl("Save").click()
276        self.assertMatches('...Form has been saved...',
277                           self.browser.contents)
278        self.browser.open(self.student_path)
279        self.browser.getLink("Clearance Data").click()
280        self.assertEqual(self.browser.headers['Status'], '200 Ok')
281        self.assertEqual(self.browser.url, self.clearance_student_path)
282        self.browser.getLink("Manage").click()
283        self.assertEqual(self.browser.headers['Status'], '200 Ok')
284        self.assertEqual(self.browser.url, self.edit_clearance_student_path)
285        self.browser.getControl(name="form.date_of_birth").value = '09/10/1961'
286        self.browser.getControl("Save").click()
287        self.assertMatches('...Form has been saved...',
288                           self.browser.contents)
289
290        self.browser.open(self.student_path)
291        self.browser.getLink("Personal Data").click()
292        self.assertEqual(self.browser.headers['Status'], '200 Ok')
293        self.assertEqual(self.browser.url, self.personal_student_path)
294        self.browser.getLink("Manage").click()
295        self.assertEqual(self.browser.headers['Status'], '200 Ok')
296        self.assertEqual(self.browser.url, self.edit_personal_student_path)
297        self.browser.getControl("Save").click()
298        self.assertMatches('...Form has been saved...',
299                           self.browser.contents)
300
301        # Managers can browse all subobjects
302        self.browser.open(self.student_path)
303        self.browser.getLink("Payments").click()
304        self.assertEqual(self.browser.headers['Status'], '200 Ok')
305        self.assertEqual(self.browser.url, self.payments_student_path)
306        self.browser.open(self.student_path)
307        self.browser.getLink("Accommodation").click()
308        self.assertEqual(self.browser.headers['Status'], '200 Ok')
309        self.assertEqual(self.browser.url, self.accommodation_student_path)
310        self.browser.open(self.student_path)
311        self.browser.getLink("History").click()
312        self.assertEqual(self.browser.headers['Status'], '200 Ok')
313        self.assertEqual(self.browser.url, self.history_student_path)
314        self.assertMatches('...Student admitted by zope.mgr...',
315                           self.browser.contents)
316        return
317
318    def test_manage_course_lists(self):
319        self.browser.addHeader('Authorization', 'Basic mgr:mgrpw')
320        self.browser.open(self.student_path)
321        self.browser.getLink("Study Course").click()
322        self.assertEqual(self.browser.headers['Status'], '200 Ok')
323        self.assertEqual(self.browser.url, self.studycourse_student_path)
324        self.browser.getLink("Manage").click()
325        self.assertTrue('Manage study course' in self.browser.contents)
326        # Before we can select a level, the certificate must be selected and saved
327        self.browser.getControl(name="form.certificate").value = ['CERT1']
328        self.browser.getControl(name="form.current_session").value = ['2004']
329        self.browser.getControl(name="form.current_verdict").value = ['A']
330        self.browser.getControl("Save").click()
331        # Now we can save also the current level which depends on start and end
332        # level of the certificate
333        self.browser.getControl(name="form.current_level").value = ['100']
334        self.browser.getControl("Save").click()
335        # Managers can add and remove any study level (course list)
336        self.browser.getControl(name="addlevel").value = ['100']
337        self.browser.getControl("Add study level").click()
338        self.assertMatches('...<span>100</span>...', self.browser.contents)
339        self.browser.getControl("Add study level").click()
340        self.assertMatches('...This level exists...', self.browser.contents)
341        self.browser.getControl("Remove selected").click()
342        self.assertMatches('...No study level selected...', self.browser.contents)
343        self.browser.getControl(name="val_id").value = ['100']
344        self.browser.getControl("Remove selected").click()
345        self.assertMatches('...Successfully removed...', self.browser.contents)
346        # Add level again
347        self.browser.getControl(name="addlevel").value = ['100']
348        self.browser.getControl("Add study level").click()
349        self.browser.getControl(name="addlevel").value = ['100']
350
351        # Managers can view and manage course lists
352        self.browser.getLink("100").click()
353        self.assertMatches('...: Study Level 100 (Year 1)...', self.browser.contents)
354        self.browser.getLink("Manage").click()
355        self.browser.getControl(name="form.level_session").value = ['2002']
356        self.browser.getControl("Save").click()
357        self.browser.getControl("Remove selected").click()
358        self.assertMatches('...No ticket selected...', self.browser.contents)
359        ctrl = self.browser.getControl(name='val_id')
360        ctrl.getControl(value='COURSE1').selected = True
361        self.browser.getControl("Remove selected", index=0).click()
362        self.assertTrue('Successfully removed' in self.browser.contents)
363        self.browser.getControl("Add course ticket").click()
364        self.browser.getControl(name="form.course").value = ['COURSE1']
365        self.browser.getControl("Add course ticket").click()
366        self.assertTrue('Successfully added' in self.browser.contents)
367        self.browser.getControl("Add course ticket").click()
368        self.browser.getControl(name="form.course").value = ['COURSE1']
369        self.browser.getControl("Add course ticket").click()
370        self.assertTrue('The ticket exists' in self.browser.contents)
371        self.browser.getControl("Cancel").click()
372        self.browser.getLink("COURSE1").click()
373        self.browser.getLink("Manage").click()
374        self.browser.getControl(name="form.score").value = '10'
375        self.browser.getControl("Save").click()
376        self.assertTrue('Form has been saved' in self.browser.contents)
377        return
378
379    def test_manage_workflow(self):
380        # Managers can pass through the whole workflow
381        self.browser.addHeader('Authorization', 'Basic mgr:mgrpw')
382        student = self.app['students'][self.student_id]
383        self.browser.open(self.manage_student_path)
384        self.assertTrue(student.clearance_locked)
385        self.browser.getControl(name="transition").value = ['admit']
386        self.browser.getControl("Save").click()
387        self.assertTrue(student.clearance_locked)
388        self.browser.getControl(name="transition").value = ['start_clearance']
389        self.browser.getControl("Save").click()
390        self.assertFalse(student.clearance_locked)
391        self.browser.getControl(name="transition").value = ['request_clearance']
392        self.browser.getControl("Save").click()
393        self.assertTrue(student.clearance_locked)
394        self.browser.getControl(name="transition").value = ['clear']
395        self.browser.getControl("Save").click()
396        self.browser.getControl(name="transition").value = ['pay_first_school_fee']
397        self.browser.getControl("Save").click()
398        self.browser.getControl(name="transition").value = ['reset6']
399        self.browser.getControl("Save").click()
400        # In state returning the pay_school_fee transition triggers some
401        # changes of attributes
402        self.browser.getControl(name="transition").value = ['pay_school_fee']
403        self.browser.getControl("Save").click()
404        self.assertEqual(student['studycourse'].current_session, 2005) # +1
405        self.assertEqual(student['studycourse'].current_level, 200) # +100
406        self.assertEqual(student['studycourse'].current_verdict, '0') # 0 = not set
407        self.assertEqual(student['studycourse'].previous_verdict, 'A')
408        self.browser.getControl(name="transition").value = ['register_courses']
409        self.browser.getControl("Save").click()
410        self.browser.getControl(name="transition").value = ['validate_courses']
411        self.browser.getControl("Save").click()
412        self.browser.getControl(name="transition").value = ['return']
413        self.browser.getControl("Save").click()
414        return
415
416    def test_manage_import(self):
417        # Managers can import student data files
418        datacenter_path = 'http://localhost/app/datacenter'
419        # Prepare a csv file for students
420        open('students.csv', 'wb').write(
421"""firstname,lastname,fullname,reg_number,date_of_birth,matric_number
422Aaren,Pieri,Aaren Pieri,1,1990-01-02,100000
423Claus,Finau,Claus Finau,2,1990-01-03,100001
424Brit,Berson,Brit Berson,3,1990-01-04,100001
425""")
426        self.browser.addHeader('Authorization', 'Basic mgr:mgrpw')
427        self.browser.open(datacenter_path)
428        self.browser.getLink('Upload CSV file').click()
429        filecontents = cStringIO.StringIO(open('students.csv', 'rb').read())
430        filewidget = self.browser.getControl(name='uploadfile:file')
431        filewidget.add_file(filecontents, 'text/plain', 'students.csv')
432        self.browser.getControl(name='SUBMIT').click()
433        self.browser.getLink('Batch processing').click()
434        button = lookup_submit_value(
435            'select', 'students_zope.mgr.csv', self.browser)
436        button.click()
437        importerselect = self.browser.getControl(name='importer')
438        modeselect = self.browser.getControl(name='mode')
439        importerselect.getControl('Student Importer').selected = True
440        modeselect.getControl(value='create').selected = True
441        self.browser.getControl('Proceed to step 3...').click()
442        self.assertTrue('Header fields OK' in self.browser.contents)
443        self.browser.getControl('Perform import...').click()
444        self.assertTrue('Processing of 1 rows failed' in self.browser.contents)
445        self.assertTrue('Successfully processed 2 rows' in self.browser.contents)
446        self.assertTrue('Batch processing finished' in self.browser.contents)
447        open('studycourses.csv', 'wb').write(
448"""reg_number,matric_number,certificate,current_session,current_level
4491,,CERT1,2008,100
450,100001,CERT1,2008,100
451,100002,CERT1,2008,100
452""")
453        self.browser.open(datacenter_path)
454        self.browser.getLink('Upload CSV file').click()
455        filecontents = cStringIO.StringIO(open('studycourses.csv', 'rb').read())
456        filewidget = self.browser.getControl(name='uploadfile:file')
457        filewidget.add_file(filecontents, 'text/plain', 'studycourses.csv')
458        self.browser.getControl(name='SUBMIT').click()
459        self.browser.getLink('Batch processing').click()
460        button = lookup_submit_value(
461            'select', 'studycourses_zope.mgr.csv', self.browser)
462        button.click()
463        importerselect = self.browser.getControl(name='importer')
464        modeselect = self.browser.getControl(name='mode')
465        importerselect.getControl(
466            'StudentStudyCourse Importer (update only)').selected = True
467        modeselect.getControl(value='create').selected = True
468        self.browser.getControl('Proceed to step 3...').click()
469        self.assertTrue('Update mode only' in self.browser.contents)
470        self.browser.getControl('Proceed to step 3...').click()
471        self.assertTrue('Header fields OK' in self.browser.contents)
472        self.browser.getControl('Perform import...').click()
473        self.assertTrue('Processing of 1 rows failed' in self.browser.contents)
474        self.assertTrue('Successfully processed 2 rows' in self.browser.contents)
475
476    def test_student_change_password(self):
477        # Students can change the password
478        self.browser.open(self.login_path)
479        self.browser.getControl(name="form.login").value = self.student_id
480        self.browser.getControl(name="form.password").value = 'spwd'
481        self.browser.getControl("Login").click()
482        self.assertEqual(self.browser.url, self.student_path)
483        self.assertTrue('You logged in' in self.browser.contents)
484        # Change password
485        self.browser.getLink("Change password").click()
486        self.browser.getControl(name="form.password").value = 'new_password'
487        self.browser.getControl(
488            name="form.password_repeat").value = 'new_passssword'
489        self.browser.getControl("Save").click()
490        self.assertTrue('passwords do not match' in self.browser.contents)
491        self.browser.getControl(name="form.password").value = 'new_password'
492        self.browser.getControl(
493            name="form.password_repeat").value = 'new_password'
494        self.browser.getControl("Save").click()
495        self.assertTrue('Form has been saved' in self.browser.contents)
496        # We are still logged in. Changing the password hasn't thrown us out.
497        self.browser.getLink("My Data").click()
498        self.assertEqual(self.browser.url, self.student_path)
499        # We can logout
500        self.browser.getLink("Logout").click()
501        self.assertTrue('You have been logged out' in self.browser.contents)
502        self.assertEqual(self.browser.url, 'http://localhost/app')
503        # We can login again with the new password
504        self.browser.getLink("Login").click()
505        self.browser.open(self.login_path)
506        self.browser.getControl(name="form.login").value = self.student_id
507        self.browser.getControl(name="form.password").value = 'new_password'
508        self.browser.getControl("Login").click()
509        self.assertEqual(self.browser.url, self.student_path)
510        self.assertTrue('You logged in' in self.browser.contents)
511        return
512
513    def test_setpassword(self):
514        # Set password for first-time access
515        student = Student()
516        student.reg_number = u'123456'
517        student.fullname = u'Klaus Tester'
518        self.app['students'].addStudent(student)
519        setpassword_path = 'http://localhost/app/setpassword'
520        student_path = 'http://localhost/app/students/%s' % student.student_id
521        self.browser.open(setpassword_path)
522        self.browser.getControl(name="ac_series").value = self.existing_pwdseries
523        self.browser.getControl(name="ac_number").value = self.existing_pwdnumber
524        self.browser.getControl(name="reg_number").value = '223456'
525        self.browser.getControl("Show").click()
526        self.assertMatches('...No student found...',
527                           self.browser.contents)
528        self.browser.getControl(name="reg_number").value = '123456'
529        self.browser.getControl(name="ac_number").value = '999999'
530        self.browser.getControl("Show").click()
531        self.assertMatches('...Access code is invalid...',
532                           self.browser.contents)
533        self.browser.getControl(name="ac_number").value = self.existing_pwdnumber
534        self.browser.getControl("Show").click()
535        self.assertMatches('...Password has been set. Your Student Id is...',
536                           self.browser.contents)
537        self.browser.getControl("Show").click()
538        self.assertMatches(
539            '...Password has already been set. Your Student Id is...',
540            self.browser.contents)
541        existing_pwdpin = self.pwdpins[1]
542        parts = existing_pwdpin.split('-')[1:]
543        existing_pwdseries, existing_pwdnumber = parts
544        self.browser.getControl(name="ac_series").value = existing_pwdseries
545        self.browser.getControl(name="ac_number").value = existing_pwdnumber
546        self.browser.getControl(name="reg_number").value = '123456'
547        self.browser.getControl("Show").click()
548        self.assertMatches(
549            '...You are using the wrong Access Code...',
550            self.browser.contents)
551        # The student can login with the new credentials
552        self.browser.open(self.login_path)
553        self.browser.getControl(name="form.login").value = student.student_id
554        self.browser.getControl(
555            name="form.password").value = self.existing_pwdnumber
556        self.browser.getControl("Login").click()
557        self.assertEqual(self.browser.url, student_path)
558        self.assertTrue('You logged in' in self.browser.contents)
559        return
560
561    def test_student_access(self):
562        # Students can access their own objects
563        # and can perform actions
564        student = self.app['students'][self.student_id]
565        IWorkflowInfo(student).fireTransition('admit')
566        self.browser.open(self.login_path)
567        self.browser.getControl(name="form.login").value = self.student_id
568        self.browser.getControl(name="form.password").value = 'spwd'
569        self.browser.getControl("Login").click()
570        # Student can view the clearance data
571        self.browser.getLink("Clearance Data").click()
572        # Student can't open clearance edit form before starting clearance
573        self.browser.open(self.student_path + '/cedit')
574        self.assertMatches('...The requested form is locked...',
575                           self.browser.contents)
576        self.browser.getLink("Clearance Data").click()
577        self.browser.getLink("Start clearance").click()
578        self.browser.getControl(name="ac_series").value = '3'
579        self.browser.getControl(name="ac_number").value = '4444444'
580        self.browser.getControl("Start clearance now").click()
581        self.assertMatches('...Access code is invalid...',
582                           self.browser.contents)
583        self.browser.getControl(name="ac_series").value = self.existing_clrseries
584        self.browser.getControl(name="ac_number").value = self.existing_clrnumber
585        self.browser.getControl("Start clearance now").click()
586        self.assertMatches('...Clearance process has been started...',
587                           self.browser.contents)
588        self.browser.getControl(name="form.date_of_birth").value = '09/10/1961'
589        self.browser.getControl("Save", index=0).click()
590        # Student can view the clearance data
591        self.browser.getLink("Clearance Data").click()
592        # and go back to the edit form
593        self.browser.getLink("Edit").click()
594        self.browser.getControl("Save and request clearance").click()
595        self.browser.getControl(name="ac_series").value = self.existing_clrseries
596        self.browser.getControl(name="ac_number").value = self.existing_clrnumber
597        self.browser.getControl("Request clearance now").click()
598        self.assertMatches('...Clearance has been requested...',
599                           self.browser.contents)
600        # Student can't reopen clearance form after requesting clearance
601        self.browser.open(self.student_path + '/cedit')
602        self.assertMatches('...The requested form is locked...',
603                           self.browser.contents)
604        # Student can't add study level if not in state 'school fee paid'
605        self.browser.open(self.student_path + '/studycourse/add')
606        self.assertMatches('...The requested form is locked...',
607                           self.browser.contents)
608        # ... and must be transferred first
609        IWorkflowInfo(student).fireTransition('clear')
610        IWorkflowInfo(student).fireTransition('pay_first_school_fee')
611        # Now students can add the current study level
612        self.browser.getLink("Study Course").click()
613        self.browser.getLink("Add course list").click()
614        self.assertMatches('...Add current level 100 (Year 1)...',
615                           self.browser.contents)
616        self.browser.getControl("Create course list now").click()
617        self.browser.getLink("100").click()
618        self.browser.getLink("Add and remove courses").click()
619        self.browser.getControl("Add course ticket").click()
620        self.browser.getControl(name="form.course").value = ['COURSE1']
621        self.browser.getControl("Add course ticket").click()
622        self.assertMatches('...The ticket exists...',
623                           self.browser.contents)
624        self.student['studycourse'].current_level = 200
625        self.browser.getLink("Study Course").click()
626        self.browser.getLink("Add course list").click()
627        self.assertMatches('...Add current level 200 (Year 2)...',
628                           self.browser.contents)
629        self.browser.getControl("Create course list now").click()
630        self.browser.getLink("200").click()
631        self.browser.getLink("Add and remove courses").click()
632        self.browser.getControl("Add course ticket").click()
633        self.browser.getControl(name="form.course").value = ['COURSE1']
634        self.browser.getControl("Add course ticket").click()
635        self.assertMatches('...Successfully added COURSE1...',
636                           self.browser.contents)
637        self.browser.getControl("Remove selected", index=0).click()
638        self.assertTrue('No ticket selected' in self.browser.contents)
639        ctrl = self.browser.getControl(name='val_id')
640        ctrl.getControl(value='COURSE1').selected = True
641        self.browser.getControl("Remove selected", index=0).click()
642        self.assertTrue('Successfully removed' in self.browser.contents)
643        self.browser.getControl("Register course list").click()
644        self.assertTrue('Course list has been registered' in self.browser.contents)
645        self.assertEqual(self.student.state, 'courses registered')
646        return
647
648    def test_manage_payments(self):
649        # Managers can add and remove online payment tickets
650        self.browser.addHeader('Authorization', 'Basic mgr:mgrpw')
651        self.browser.open(self.payments_student_path)
652        self.browser.getLink("Manage").click()
653        self.browser.getControl("Add online payment ticket").click()
654        self.browser.getControl("Create ticket").click()
655        self.assertMatches('...ticket created...',
656                           self.browser.contents)
657        ctrl = self.browser.getControl(name='val_id')
658        value = ctrl.options[0]
659        self.browser.getLink(value).click()
660        self.assertMatches('...Amount Authorized...',
661                           self.browser.contents)
662        self.browser.open(self.payments_student_path)
663        self.browser.getLink('Manage').click()
664        self.browser.getControl("Remove selected").click()
665        self.assertMatches('...No payment selected...', self.browser.contents)
666        ctrl = self.browser.getControl(name='val_id')
667        value = ctrl.options[0]
668        ctrl.getControl(value=value).selected = True
669        self.browser.getControl("Remove selected", index=0).click()
670        self.assertTrue('Successfully removed' in self.browser.contents)
Note: See TracBrowser for help on using the repository browser.