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

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

Do not return the student_id when calling addStudent. The student_id is now set when a student is initiated.

  • Property svn:keywords set to Id
File size: 27.3 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 6845 2011-10-02 08:15:51Z 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
72        student = Student()
73        student.fullname = u'Anna Tester'
74        student.reg_number = u'123'
75        student.matric_number = u'234'
76        self.app['students'].addStudent(student)
77        self.student_id = student.student_id
78        self.student = self.app['students'][self.student_id]
79
80        # Set password
81        IUserAccount(
82            self.app['students'][self.student_id]).setPassword('spwd')
83
84        self.login_path = 'http://localhost/app/login'
85        self.container_path = 'http://localhost/app/students'
86        self.manage_container_path = self.container_path + '/@@manage'
87        self.add_student_path = self.container_path + '/addstudent'
88        self.student_path = self.container_path + '/' + self.student_id
89        self.manage_student_path = self.student_path + '/edit_base'
90        self.clearance_student_path = self.student_path + '/view_clearance'
91        self.personal_student_path = self.student_path + '/view_personal'
92        self.edit_clearance_student_path = self.student_path + '/edit_clearance'
93        self.edit_personal_student_path = self.student_path + '/edit_personal'
94
95        self.studycourse_student_path = self.student_path + '/studycourse'
96        self.payments_student_path = self.student_path + '/payments'
97        self.accommodation_student_path = self.student_path + '/accommodation'
98        self.history_student_path = self.student_path + '/history'
99
100        # Create 5 access codes with prefix'PWD'
101        pin_container = self.app['accesscodes']
102        pin_container.createBatch(
103            datetime.now(), 'some_userid', 'PWD', 9.99, 5)
104        pins = pin_container[pin_container.keys()[0]].values()
105        self.pwdpins = [x.representation for x in pins]
106        self.existing_pwdpin = self.pwdpins[0]
107        parts = self.existing_pwdpin.split('-')[1:]
108        self.existing_pwdseries, self.existing_pwdnumber = parts
109        # Create 5 access codes with prefix 'CLR'
110        pin_container.createBatch(
111            datetime.now(), 'some_userid', 'CLR', 9.99, 5)
112        pins = pin_container[pin_container.keys()[0]].values()
113        self.clrpins = [x.representation for x in pins]
114        self.existing_clrpin = self.clrpins[0]
115        self.existing_clrpin
116        parts = self.existing_clrpin.split('-')[1:]
117        self.existing_clrseries, self.existing_clrnumber = parts
118
119        # Populate university
120        self.certificate = createObject('waeup.Certificate')
121        self.certificate.code = 'CERT1'
122        self.certificate.application_category = 'basic'
123        self.certificate.start_level = 100
124        self.certificate.end_level = 500
125        self.app['faculties']['fac1'] = Faculty()
126        self.app['faculties']['fac1']['dep1'] = Department()
127        self.app['faculties']['fac1']['dep1'].certificates.addCertificate(
128            self.certificate)
129        self.course = createObject('waeup.Course')
130        self.course.code = 'COURSE1'
131        self.course.semester = 1
132        self.course.credits = 10
133        self.course.passmark = 40
134        self.app['faculties']['fac1']['dep1'].courses.addCourse(
135            self.course)
136        self.app['faculties']['fac1']['dep1'].certificates['CERT1'].addCourseRef(
137            self.course, level=100)
138
139        # Set study course attributes of test student
140        self.student['studycourse'].certificate = self.certificate
141        self.student['studycourse'].current_session = 2004
142        self.student['studycourse'].current_verdict = 'A'
143        self.student['studycourse'].current_level = 100
144
145        # Put the prepopulated site into test ZODB and prepare test
146        # browser
147        self.browser = Browser()
148        self.browser.handleErrors = False
149
150    def tearDown(self):
151        super(StudentsFullSetup, self).tearDown()
152        clearSite()
153        shutil.rmtree(self.dc_root)
154
155
156
157class StudentsContainerUITests(StudentsFullSetup):
158    # Tests for StudentsContainer class views and pages
159
160    layer = FunctionalLayer
161
162    def test_anonymous_access(self):
163        # Anonymous users can't access students containers
164        self.assertRaises(
165            Unauthorized, self.browser.open, self.container_path)
166        self.assertRaises(
167            Unauthorized, self.browser.open, self.manage_container_path)
168        return
169
170    def test_manage_access(self):
171        # Managers can access the view page of students
172        # containers and can perform actions
173        self.browser.addHeader('Authorization', 'Basic mgr:mgrpw')
174        self.browser.open(self.container_path)
175        self.assertEqual(self.browser.headers['Status'], '200 Ok')
176        self.assertEqual(self.browser.url, self.container_path)
177        self.browser.getLink("Manage student section").click()
178        self.assertEqual(self.browser.headers['Status'], '200 Ok')
179        self.assertEqual(self.browser.url, self.manage_container_path)
180        return
181
182    def test_add_search_delete_students(self):
183        # Managers can add search and remove students
184        self.browser.addHeader('Authorization', 'Basic mgr:mgrpw')
185        self.browser.open(self.manage_container_path)
186        self.browser.getLink("Add student").click()
187        self.assertEqual(self.browser.headers['Status'], '200 Ok')
188        self.assertEqual(self.browser.url, self.add_student_path)
189        self.browser.getControl(name="form.fullname").value = 'Bob Tester'
190        self.browser.getControl("Create student record").click()
191        self.assertTrue('Student record created' in self.browser.contents)
192
193        # Registration and matric numbers must be unique
194        self.browser.getLink("Manage").click()
195        self.browser.getControl(name="form.reg_number").value = '123'
196        self.browser.getControl("Save").click()
197        self.assertMatches('...Registration number exists...',
198                           self.browser.contents)
199        self.browser.getControl(name="form.reg_number").value = '789'
200        self.browser.getControl(name="form.matric_number").value = '234'
201        self.browser.getControl("Save").click()
202        self.assertMatches('...Matriculation number exists...',
203                           self.browser.contents)
204
205        self.browser.open(self.container_path)
206        self.browser.getControl("Search").click()
207        self.assertTrue('Empty search string' in self.browser.contents)
208        self.browser.getControl(name="searchtype").value = ['student_id']
209        self.browser.getControl(name="searchterm").value = self.student_id
210        self.browser.getControl("Search").click()
211        self.assertTrue('Anna Tester' in self.browser.contents)
212
213        self.browser.open(self.manage_container_path)
214        self.browser.getControl("Search").click()
215        self.assertTrue('Empty search string' in self.browser.contents)
216        self.browser.getControl(name="searchtype").value = ['fullname']
217        self.browser.getControl(name="searchterm").value = 'Anna Tester'
218        self.browser.getControl("Search").click()
219        self.assertTrue('Anna Tester' in self.browser.contents)
220        # The old searchterm will be used again
221        self.browser.getControl("Search").click()
222        self.assertTrue('Anna Tester' in self.browser.contents)
223
224        ctrl = self.browser.getControl(name='entries')
225        ctrl.getControl(value=self.student_id).selected = True
226        self.browser.getControl("Remove selected", index=0).click()
227        self.assertTrue('Successfully removed' in self.browser.contents)
228        self.browser.getControl(name="searchtype").value = ['student_id']
229        self.browser.getControl(name="searchterm").value = self.student_id
230        self.browser.getControl("Search").click()
231        self.assertTrue('No student found' in self.browser.contents)
232
233        self.browser.open(self.container_path)
234        self.browser.getControl(name="searchtype").value = ['student_id']
235        self.browser.getControl(name="searchterm").value = self.student_id
236        self.browser.getControl("Search").click()
237        self.assertTrue('No student found' in self.browser.contents)
238        return
239
240class StudentUITests(StudentsFullSetup):
241    # Tests for Student class views and pages
242
243    layer = FunctionalLayer
244
245    def test_manage_access(self):
246        # Managers can access the pages of students
247        # and can perform actions
248        self.browser.addHeader('Authorization', 'Basic mgr:mgrpw')
249
250        self.browser.open(self.student_path)
251        self.assertEqual(self.browser.headers['Status'], '200 Ok')
252        self.assertEqual(self.browser.url, self.student_path)
253        self.browser.getLink("Manage").click()
254        self.assertEqual(self.browser.headers['Status'], '200 Ok')
255        self.assertEqual(self.browser.url, self.manage_student_path)
256        # Managers can edit base data and fire transitions
257        self.browser.getControl(name="transition").value = ['admit']
258        self.browser.getControl(name="form.fullname").value = 'John Tester'
259        self.browser.getControl(name="form.reg_number").value = '345'
260        self.browser.getControl(name="password").value = 'secret'
261        self.browser.getControl(name="control_password").value = 'secret'
262        self.browser.getControl("Save").click()
263        self.assertMatches('...Form has been saved...',
264                           self.browser.contents)
265        self.browser.open(self.student_path)
266        self.browser.getLink("Clearance Data").click()
267        self.assertEqual(self.browser.headers['Status'], '200 Ok')
268        self.assertEqual(self.browser.url, self.clearance_student_path)
269        self.browser.getLink("Manage").click()
270        self.assertEqual(self.browser.headers['Status'], '200 Ok')
271        self.assertEqual(self.browser.url, self.edit_clearance_student_path)
272        self.browser.getControl(name="form.date_of_birth").value = '09/10/1961'
273        self.browser.getControl("Save").click()
274        self.assertMatches('...Form has been saved...',
275                           self.browser.contents)
276
277        self.browser.open(self.student_path)
278        self.browser.getLink("Personal Data").click()
279        self.assertEqual(self.browser.headers['Status'], '200 Ok')
280        self.assertEqual(self.browser.url, self.personal_student_path)
281        self.browser.getLink("Manage").click()
282        self.assertEqual(self.browser.headers['Status'], '200 Ok')
283        self.assertEqual(self.browser.url, self.edit_personal_student_path)
284        self.browser.getControl("Save").click()
285        self.assertMatches('...Form has been saved...',
286                           self.browser.contents)
287
288        # Managers can browse all subobjects
289        self.browser.open(self.student_path)
290        self.browser.getLink("Payments").click()
291        self.assertEqual(self.browser.headers['Status'], '200 Ok')
292        self.assertEqual(self.browser.url, self.payments_student_path)
293        self.browser.open(self.student_path)
294        self.browser.getLink("Accommodation").click()
295        self.assertEqual(self.browser.headers['Status'], '200 Ok')
296        self.assertEqual(self.browser.url, self.accommodation_student_path)
297        self.browser.open(self.student_path)
298        self.browser.getLink("History").click()
299        self.assertEqual(self.browser.headers['Status'], '200 Ok')
300        self.assertEqual(self.browser.url, self.history_student_path)
301        self.assertMatches('...Student admitted by zope.mgr...',
302                           self.browser.contents)
303        return
304
305    def test_manage_course_lists(self):
306        self.browser.addHeader('Authorization', 'Basic mgr:mgrpw')
307        self.browser.open(self.student_path)
308        self.browser.getLink("Study Course").click()
309        self.assertEqual(self.browser.headers['Status'], '200 Ok')
310        self.assertEqual(self.browser.url, self.studycourse_student_path)
311        self.browser.getLink("Manage").click()
312        self.assertTrue('Manage study course' in self.browser.contents)
313        # Before we can select a level, the certificate must be selected and saved
314        self.browser.getControl(name="form.certificate").value = ['CERT1']
315        self.browser.getControl(name="form.current_session").value = ['2004']
316        self.browser.getControl(name="form.current_verdict").value = ['A']
317        self.browser.getControl("Save").click()
318        # Now we can save also the current level which depends on start and end
319        # level of the certificate
320        self.browser.getControl(name="form.current_level").value = ['100']
321        self.browser.getControl("Save").click()
322        # Managers can add and remove any study level (course list)
323        self.browser.getControl(name="addlevel").value = ['100']
324        self.browser.getControl("Add study level").click()
325        self.assertMatches('...<span>100</span>...', self.browser.contents)
326        self.browser.getControl(name="val_id").value = ['100']
327        self.browser.getControl("Remove selected").click()
328        self.assertMatches('...Successfully removed...', self.browser.contents)
329        # Add again level again
330        self.browser.getControl(name="addlevel").value = ['100']
331        self.browser.getControl("Add study level").click()
332
333        # Managers can view and manage course lists
334        self.browser.getLink("100").click()
335        self.assertMatches('...: Study Level 100 (Year 1)...', self.browser.contents)
336        self.browser.getLink("Manage").click()
337        self.browser.getControl(name="form.level_session").value = ['2002']
338        self.browser.getControl("Save").click()
339        ctrl = self.browser.getControl(name='val_id')
340        ctrl.getControl(value='COURSE1').selected = True
341        self.browser.getControl("Remove selected", index=0).click()
342        self.assertTrue('Successfully removed' in self.browser.contents)
343        self.browser.getControl("Add course ticket").click()
344        self.browser.getControl(name="form.course").value = ['COURSE1']
345        self.browser.getControl("Add course ticket").click()
346        self.assertTrue('Successfully added' in self.browser.contents)
347        self.browser.getLink("COURSE1").click()
348        self.browser.getLink("Manage").click()
349        self.browser.getControl(name="form.score").value = '10'
350        self.browser.getControl("Save").click()
351        self.assertTrue('Form has been saved' in self.browser.contents)
352        return
353
354    def test_manage_workflow(self):
355        # Managers can pass through the whole workflow
356        self.browser.addHeader('Authorization', 'Basic mgr:mgrpw')
357        student = self.app['students'][self.student_id]
358        self.browser.open(self.manage_student_path)
359        self.assertTrue(student.clearance_locked)
360        self.browser.getControl(name="transition").value = ['admit']
361        self.browser.getControl("Save").click()
362        self.assertTrue(student.clearance_locked)
363        self.browser.getControl(name="transition").value = ['start_clearance']
364        self.browser.getControl("Save").click()
365        self.assertFalse(student.clearance_locked)
366        self.browser.getControl(name="transition").value = ['request_clearance']
367        self.browser.getControl("Save").click()
368        self.assertTrue(student.clearance_locked)
369        self.browser.getControl(name="transition").value = ['clear']
370        self.browser.getControl("Save").click()
371        self.browser.getControl(name="transition").value = ['pay_first_school_fee']
372        self.browser.getControl("Save").click()
373        self.browser.getControl(name="transition").value = ['reset6']
374        self.browser.getControl("Save").click()
375        # In state returning the pay_school_fee transition triggers some
376        # changes of attributes
377        self.browser.getControl(name="transition").value = ['pay_school_fee']
378        self.browser.getControl("Save").click()
379        self.assertEqual(student['studycourse'].current_session, 2005) # +1
380        self.assertEqual(student['studycourse'].current_level, 200) # +100
381        self.assertEqual(student['studycourse'].current_verdict, '0') # 0 = not set
382        self.assertEqual(student['studycourse'].previous_verdict, 'A')
383        self.browser.getControl(name="transition").value = ['register_courses']
384        self.browser.getControl("Save").click()
385        self.browser.getControl(name="transition").value = ['validate_courses']
386        self.browser.getControl("Save").click()
387        self.browser.getControl(name="transition").value = ['return']
388        self.browser.getControl("Save").click()
389        return
390
391    def test_student_change_password(self):
392        # Students can change the password
393        self.browser.open(self.login_path)
394        self.browser.getControl(name="form.login").value = self.student_id
395        self.browser.getControl(name="form.password").value = 'spwd'
396        self.browser.getControl("Login").click()
397        self.assertEqual(self.browser.url, self.student_path)
398        self.assertTrue('You logged in' in self.browser.contents)
399        # Change password
400        self.browser.getLink("Change password").click()
401        self.browser.getControl(name="form.password").value = 'new_password'
402        self.browser.getControl(
403            name="form.password_repeat").value = 'new_passssword'
404        self.browser.getControl("Save").click()
405        self.assertTrue('passwords do not match' in self.browser.contents)
406        self.browser.getControl(name="form.password").value = 'new_password'
407        self.browser.getControl(
408            name="form.password_repeat").value = 'new_password'
409        self.browser.getControl("Save").click()
410        self.assertTrue('Form has been saved' in self.browser.contents)
411        # We are still logged in. Changing the password hasn't thrown us out.
412        self.browser.getLink("My Data").click()
413        self.assertEqual(self.browser.url, self.student_path)
414        # We can logout
415        self.browser.getLink("Logout").click()
416        self.assertTrue('You have been logged out' in self.browser.contents)
417        self.assertEqual(self.browser.url, 'http://localhost/app')
418        # We can login again with the new password
419        self.browser.getLink("Login").click()
420        self.browser.open(self.login_path)
421        self.browser.getControl(name="form.login").value = self.student_id
422        self.browser.getControl(name="form.password").value = 'new_password'
423        self.browser.getControl("Login").click()
424        self.assertEqual(self.browser.url, self.student_path)
425        self.assertTrue('You logged in' in self.browser.contents)
426        return
427
428    def test_setpassword(self):
429        # Set password for first-time access
430        student = Student()
431        student.reg_number = u'123456'
432        student.fullname = u'Klaus Tester'
433        self.app['students'].addStudent(student)
434        setpassword_path = 'http://localhost/app/setpassword'
435        student_path = 'http://localhost/app/students/%s' % student.student_id
436        self.browser.open(setpassword_path)
437        self.browser.getControl(name="ac_series").value = self.existing_pwdseries
438        self.browser.getControl(name="ac_number").value = self.existing_pwdnumber
439        self.browser.getControl(name="reg_number").value = '223456'
440        self.browser.getControl("Show").click()
441        self.assertMatches('...No student found...',
442                           self.browser.contents)
443        self.browser.getControl(name="reg_number").value = '123456'
444        self.browser.getControl(name="ac_number").value = '999999'
445        self.browser.getControl("Show").click()
446        self.assertMatches('...Access code is invalid...',
447                           self.browser.contents)
448        self.browser.getControl(name="ac_number").value = self.existing_pwdnumber
449        self.browser.getControl("Show").click()
450        self.assertMatches('...Password has been set. Your Student Id is...',
451                           self.browser.contents)
452        self.browser.getControl("Show").click()
453        self.assertMatches(
454            '...Password has already been set. Your Student Id is...',
455            self.browser.contents)
456        existing_pwdpin = self.pwdpins[1]
457        parts = existing_pwdpin.split('-')[1:]
458        existing_pwdseries, existing_pwdnumber = parts
459        self.browser.getControl(name="ac_series").value = existing_pwdseries
460        self.browser.getControl(name="ac_number").value = existing_pwdnumber
461        self.browser.getControl(name="reg_number").value = '123456'
462        self.browser.getControl("Show").click()
463        self.assertMatches(
464            '...You are using the wrong Access Code...',
465            self.browser.contents)
466        # The student can login with the new credentials
467        self.browser.open(self.login_path)
468        self.browser.getControl(name="form.login").value = student.student_id
469        self.browser.getControl(
470            name="form.password").value = self.existing_pwdnumber
471        self.browser.getControl("Login").click()
472        self.assertEqual(self.browser.url, student_path)
473        self.assertTrue('You logged in' in self.browser.contents)
474        return
475
476    def test_student_access(self):
477        # Students can access their own objects
478        # and can perform actions
479        student = self.app['students'][self.student_id]
480        IWorkflowInfo(student).fireTransition('admit')
481        self.browser.open(self.login_path)
482        self.browser.getControl(name="form.login").value = self.student_id
483        self.browser.getControl(name="form.password").value = 'spwd'
484        self.browser.getControl("Login").click()
485        # Student can view the clearance data
486        self.browser.getLink("Clearance Data").click()
487        # Student can't open clearance edit form before starting clearance
488        self.browser.open(self.student_path + '/cedit')
489        self.assertMatches('...The requested form is locked...',
490                           self.browser.contents)
491        self.browser.getLink("Clearance Data").click()
492        self.browser.getLink("Start clearance").click()
493        self.browser.getControl(name="ac_series").value = self.existing_clrseries
494        self.browser.getControl(name="ac_number").value = self.existing_clrnumber
495        self.browser.getControl("Start clearance now").click()
496        self.assertMatches('...Clearance process has been started...',
497                           self.browser.contents)
498        self.browser.getControl(name="form.date_of_birth").value = '09/10/1961'
499        self.browser.getControl("Save", index=0).click()
500        # Student can view the clearance data
501        self.browser.getLink("Clearance Data").click()
502        # and go back to the edit form
503        self.browser.getLink("Edit").click()
504        self.browser.getControl("Save and request clearance").click()
505        self.browser.getControl(name="ac_series").value = self.existing_clrseries
506        self.browser.getControl(name="ac_number").value = self.existing_clrnumber
507        self.browser.getControl("Request clearance now").click()
508        self.assertMatches('...Clearance has been requested...',
509                           self.browser.contents)
510        # Student can't reopen clearance form after requesting clearance
511        self.browser.open(self.student_path + '/cedit')
512        self.assertMatches('...The requested form is locked...',
513                           self.browser.contents)
514        IWorkflowInfo(student).fireTransition('clear')
515        IWorkflowInfo(student).fireTransition('pay_first_school_fee')
516        # Students can add the current study level
517        self.browser.getLink("Study Course").click()
518        self.browser.getLink("Add course list").click()
519        self.assertMatches('...Add current level 100 (Year 1)...',
520                           self.browser.contents)
521        self.browser.getControl("Create course list now").click()
522        self.browser.getLink("100").click()
523        self.browser.getLink("Add and remove courses").click()
524        self.browser.getControl("Add course ticket").click()
525        self.browser.getControl(name="form.course").value = ['COURSE1']
526        self.browser.getControl("Add course ticket").click()
527        self.assertMatches('...The ticket exists...',
528                           self.browser.contents)
529        self.student['studycourse'].current_level = 200
530        self.browser.getLink("Study Course").click()
531        self.browser.getLink("Add course list").click()
532        self.assertMatches('...Add current level 200 (Year 2)...',
533                           self.browser.contents)
534        self.browser.getControl("Create course list now").click()
535        self.browser.getLink("200").click()
536        self.browser.getLink("Add and remove courses").click()
537        self.browser.getControl("Add course ticket").click()
538        self.browser.getControl(name="form.course").value = ['COURSE1']
539        self.browser.getControl("Add course ticket").click()
540        self.assertMatches('...Successfully added COURSE1...',
541                           self.browser.contents)
542        ctrl = self.browser.getControl(name='val_id')
543        ctrl.getControl(value='COURSE1').selected = True
544        self.browser.getControl("Remove selected", index=0).click()
545        self.assertTrue('Successfully removed' in self.browser.contents)
546        self.browser.getControl("Register course list").click()
547        self.assertTrue('Course list has been registered' in self.browser.contents)
548        self.assertEqual(self.student.state, 'courses registered')
549        return
Note: See TracBrowser for help on using the repository browser.