source: main/waeup.aaue/trunk/src/waeup/aaue/students/tests/test_browser.py @ 13778

Last change on this file since 13778 was 13770, checked in by Henrik Bettermann, 9 years ago

Customize ICourseTicket. Add field 'ca'.

Customize EditScoresPage?, CourseTicketManageFormPage?, CourseTicketDisplayFormPage? and editscorespage.pt accordingly.

  • Property svn:keywords set to Id
File size: 35.5 KB
Line 
1## $Id: test_browser.py 13770 2016-03-08 17:21:35Z henrik $
2##
3## Copyright (C) 2011 Uli Fouquet & Henrik Bettermann
4## This program is free software; you can redistribute it and/or modify
5## it under the terms of the GNU General Public License as published by
6## the Free Software Foundation; either version 2 of the License, or
7## (at your option) any later version.
8##
9## This program is distributed in the hope that it will be useful,
10## but WITHOUT ANY WARRANTY; without even the implied warranty of
11## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12## GNU General Public License for more details.
13##
14## You should have received a copy of the GNU General Public License
15## along with this program; if not, write to the Free Software
16## Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17##
18import os
19import shutil
20import tempfile
21import pytz
22import grok
23from hurry.workflow.interfaces import IWorkflowInfo, IWorkflowState
24from zope.securitypolicy.interfaces import IPrincipalRoleManager
25from datetime import datetime, timedelta, date
26from mechanize import LinkNotFoundError
27from hurry.workflow.interfaces import IWorkflowState
28from zope.event import notify
29from zope.component.hooks import setSite, clearSite
30from zope.component import getUtility, createObject, queryUtility
31from zope.catalog.interfaces import ICatalog
32from waeup.kofa.app import University
33from waeup.kofa.students.tests.test_browser import StudentsFullSetup
34from waeup.kofa.students.accommodation import BedTicket
35from waeup.kofa.testing import FunctionalTestCase
36from waeup.kofa.authentication import LocalRoleSetEvent
37from waeup.kofa.browser.tests.test_pdf import samples_dir
38from waeup.aaue.testing import FunctionalLayer
39
40SAMPLE_IMAGE = os.path.join(os.path.dirname(__file__), 'test_image.jpg')
41
42
43class StudentProcessorTest(FunctionalTestCase):
44    """Perform some batching tests.
45    """
46
47    layer = FunctionalLayer
48
49    def setUp(self):
50        super(StudentProcessorTest, self).setUp()
51        # Setup a sample site for each test
52        app = University()
53        self.dc_root = tempfile.mkdtemp()
54        app['datacenter'].setStoragePath(self.dc_root)
55
56        # Prepopulate the ZODB...
57        self.getRootFolder()['app'] = app
58        # we add the site immediately after creation to the
59        # ZODB. Catalogs and other local utilities are not setup
60        # before that step.
61        self.app = self.getRootFolder()['app']
62        # Set site here. Some of the following setup code might need
63        # to access grok.getSite() and should get our new app then
64        setSite(app)
65
66
67    def tearDown(self):
68        super(StudentProcessorTest, self).tearDown()
69        shutil.rmtree(self.workdir)
70        shutil.rmtree(self.dc_root)
71        clearSite()
72        return
73
74class OfficerUITests(StudentsFullSetup):
75    # Tests for Student class views and pages
76
77    layer = FunctionalLayer
78
79    def test_gpa_calculation(self):
80        studylevel = createObject(u'waeup.StudentStudyLevel')
81        studylevel.level = 100
82        studylevel.level_session = 2005
83        self.student['studycourse'].entry_mode = 'ug_ft'
84        self.student['studycourse'].addStudentStudyLevel(
85            self.certificate, studylevel)
86        # First course has been added automatically.
87        # Set score.
88        studylevel['COURSE1'].score = 55
89        # GPA is 3.0.
90        self.assertEqual(studylevel.gpa_params[0], 3.0)
91        courseticket = createObject('waeup.CourseTicket')
92        courseticket.code = 'ANYCODE'
93        courseticket.title = u'Any TITLE'
94        courseticket.credits = 13
95        courseticket.score = 66
96        courseticket.semester = 1
97        courseticket.dcode = u'ANYDCODE'
98        courseticket.fcode = u'ANYFCODE'
99        studylevel['COURSE2'] = courseticket
100        # total credits
101        self.assertEqual(self.student['studycourse']['100'].gpa_params[1], 23)
102        # weigheted credits = 3 * 10 + 4 * 13
103        self.assertEqual(self.student['studycourse']['100'].gpa_params[2], 82.0)
104        # sgpa = 82 / 23
105        self.assertEqual(self.student['studycourse']['100'].gpa_params[0], 3.565)
106        return
107
108    def test_manage_payments(self):
109        # Add missing configuration data
110        self.app['configuration']['2004'].gown_fee = 150.0
111        self.app['configuration']['2004'].transfer_fee = 90.0
112        self.app['configuration']['2004'].booking_fee = 150.0
113        self.app['configuration']['2004'].maint_fee = 180.0
114        self.app['configuration']['2004'].late_fee = 80.0
115
116        # Managers can add online payment tickets
117        self.browser.addHeader('Authorization', 'Basic mgr:mgrpw')
118        self.browser.open(self.payments_path)
119        self.browser.getLink("Add current session payment ticket").click()
120        self.browser.getControl(name="form.p_category").value = ['schoolfee_incl']
121        self.browser.getControl("Create ticket").click()
122        self.assertMatches('...Wrong state...',
123                           self.browser.contents)
124        IWorkflowState(self.student).setState('cleared')
125        self.browser.open(self.payments_path + '/addop')
126        self.browser.getControl("Create ticket").click()
127        self.assertMatches('...Amount could not be determined...',
128                           self.browser.contents)
129        #self.browser.getControl(name="form.p_category").value = ['schoolfee']
130        # Accepotance fee must be paid first
131        #self.browser.getControl("Create ticket").click()
132        #self.assertMatches('...Please pay acceptance fee first...',
133        #                   self.browser.contents)
134        self.app['configuration']['2004'].clearance_fee = 666.0
135        self.browser.getControl(name="form.p_category").value = ['clearance_incl']
136        self.browser.getControl("Create ticket").click()
137        ctrl = self.browser.getControl(name='val_id')
138        cpt_value = ctrl.options[0]
139        # School fee payment ticket can be added ...
140        self.student['studycourse'].certificate.school_fee_1 = 6666.0
141        self.student.nationality = u'NG'
142        self.browser.open(self.payments_path + '/addop')
143        self.browser.getControl(name="form.p_category").value = ['schoolfee_incl']
144        self.browser.getControl("Create ticket").click()
145        self.assertMatches('...ticket created...',
146                           self.browser.contents)
147        # ... but not paid through the query_history page.
148        ctrl = self.browser.getControl(name='val_id')
149        sfpt_value = ctrl.options[1]
150        self.student['studycourse'].entry_session = 2013
151        self.browser.open(self.payments_path + '/' + sfpt_value)
152        self.browser.getLink("Query eTranzact History").click()
153        self.assertMatches('...alert-danger">Please pay acceptance fee first...',
154                           self.browser.contents)
155        # If clearance/acceptance fee is paid ...
156        self.student['payments'][cpt_value].approveStudentPayment()
157        self.browser.getLink("Query eTranzact History").click()
158        # ... query_history page is accessible.
159        self.assertMatches(
160            '...<h1 class="kofa-content-label">Requery eTranzact History</h1>...',
161            self.browser.contents)
162        # Managers can open school fee payment slip
163        self.browser.open(self.payments_path + '/' + sfpt_value)
164        self.browser.getLink("Download payment slip").click()
165        self.assertEqual(self.browser.headers['Status'], '200 Ok')
166        self.assertEqual(self.browser.headers['Content-Type'], 'application/pdf')
167        # If school fee ticket is paid, the student is automatically set to
168        # school fee paid...
169        ticket = self.student['payments'][sfpt_value].approveStudentPayment()
170        self.assertEqual(self.student.state, 'school fee paid')
171        # ... no further school fee ticket can be added.
172        self.browser.open(self.payments_path + '/addop')
173        self.browser.getControl(name="form.p_category").value = ['schoolfee_incl']
174        self.browser.getControl("Create ticket").click()
175        self.assertMatches('...Wrong state...',
176                           self.browser.contents)
177        self.browser.open(self.payments_path + '/addop')
178        self.browser.getControl(name="form.p_category").value = ['late_registration']
179        self.browser.getControl("Create ticket").click()
180        self.assertMatches('...ticket created...',
181                           self.browser.contents)
182        return
183
184    def test_for_instalment_payments(self):
185        self.student['studycourse'].certificate.school_fee_1 = 6666.0
186        self.app['configuration']['2004'].union_fee = 1250.0
187        self.app['configuration']['2004'].welfare_fee = 750.0
188        self.student.nationality = u'NG'
189        self.browser.addHeader('Authorization', 'Basic mgr:mgrpw')
190        self.browser.open(self.payments_path + '/addop')
191        self.browser.getControl(name="form.p_category").value = ['schoolfee_1']
192        self.browser.getControl("Create ticket").click()
193        self.assertTrue(
194            'Wrong state. Only students in state \'cleared\' are allowed to pay by instalments'
195            in self.browser.contents)
196        IWorkflowState(self.student).setState('cleared')
197        self.browser.open(self.payments_path + '/addop')
198        self.browser.getControl(name="form.p_category").value = ['schoolfee_1']
199        self.browser.getControl("Create ticket").click()
200        self.assertTrue('ticket created' in self.browser.contents)
201        # We can't add the 2nd instalment ticket because the
202        # first one has not yet been approved.
203        #self.browser.open(self.payments_path + '/addop')
204        #self.browser.getControl(name="form.p_category").value = ['schoolfee_2']
205        #self.browser.getControl("Create ticket").click()
206        #self.assertMatches('...1st school fee instalment has not yet been paid...',
207        #                   self.browser.contents)
208        # Ok, then we approve the first instalment ...
209        self.browser.open(self.payments_path)
210        ctrl = self.browser.getControl(name='val_id')
211        p_id = ctrl.options[0]
212        self.browser.open(self.payments_path + '/' + p_id + '/approve')
213        # ... add the second instalment ...
214        self.browser.open(self.payments_path + '/addop')
215        self.browser.getControl(name="form.p_category").value = ['schoolfee_2']
216        self.browser.getControl("Create ticket").click()
217        self.assertTrue('ticket created' in self.browser.contents)
218        # ... approve the second instalment ...
219        ctrl = self.browser.getControl(name='val_id')
220        p_id = ctrl.options[1]
221        self.browser.open(self.payments_path + '/' + p_id + '/approve')
222        self.assertEqual(self.student['payments'].values()[0].p_category, 'schoolfee_1')
223        self.assertEqual(self.student['payments'].values()[1].p_category, 'schoolfee_2')
224        # (6666-250)/2 + 1250 + 750 - 500 + 250
225        self.assertEqual(self.student['payments'].values()[0].amount_auth, 4958.0)
226        # (6666-250)/2 + 250
227        self.assertEqual(self.student['payments'].values()[1].amount_auth, 3458.0)
228        return
229
230    def test_manage_payments_bypass_ac_creation(self):
231        self.student['studycourse'].certificate.school_fee_1 = 6666.0
232        self.student.nationality = u'NG'
233        self.browser.addHeader('Authorization', 'Basic mgr:mgrpw')
234        self.browser.open(self.payments_path)
235        IWorkflowState(self.student).setState('cleared')
236        self.browser.getLink("Add current session payment ticket").click()
237        self.browser.getControl(name="form.p_category").value = ['schoolfee_incl']
238        self.browser.getControl("Create ticket").click()
239        ctrl = self.browser.getControl(name='val_id')
240        value = ctrl.options[0]
241        self.browser.getLink(value).click()
242        payment_url = self.browser.url
243        logfile = os.path.join(
244            self.app['datacenter'].storage, 'logs', 'students.log')
245        # The ticket can be found in the payments_catalog
246        cat = queryUtility(ICatalog, name='payments_catalog')
247        results = list(cat.searchResults(p_state=('unpaid', 'unpaid')))
248        self.assertTrue(len(results), 1)
249        self.assertTrue(results[0] is self.student['payments'][value])
250        # Managers can approve the payment
251        self.browser.open(payment_url)
252        self.browser.getLink("Approve payment").click()
253        self.assertMatches('...Payment approved...',
254                          self.browser.contents)
255        # Approval is logged in students.log ...
256        logcontent = open(logfile).read()
257        self.assertTrue(
258            'zope.mgr - students.browser.OnlinePaymentApproveView '
259            '- E1000000 - schoolfee_incl payment approved'
260            in logcontent)
261        # ... and in payments.log
262        logfile = os.path.join(
263            self.app['datacenter'].storage, 'logs', 'payments.log')
264        logcontent = open(logfile).read()
265        self.assertTrue(
266            '"zope.mgr",E1000000,%s,schoolfee_incl,6666.0,AP,,,,,,\n' % value
267            in logcontent)
268        # Student is in state school fee paid, no activation
269        # code was necessary.
270        self.assertEqual(self.student.state, 'school fee paid')
271        self.assertEqual(len(self.app['accesscodes']['SFE-0']),0)
272        return
273
274class StudentUITests(StudentsFullSetup):
275    """Tests for customized student class views and pages
276    """
277
278    layer = FunctionalLayer
279
280    def setUp(self):
281        super(StudentUITests, self).setUp()
282
283        bedticket = BedTicket()
284        bedticket.booking_session = 2004
285        bedticket.bed_type = u'any bed type'
286        bedticket.bed = self.app['hostels']['hall-1']['hall-1_A_101_A']
287        bedticket.bed_coordinates = u'My bed coordinates'
288        self.student['accommodation'].addBedTicket(bedticket)
289
290    def test_student_payments(self):
291        self.certificate.study_mode = 'ug_ft'
292        self.student['studycourse'].entry_session = 2013
293        self.student['studycourse'].certificate.school_fee_1 = 50250.0
294        self.app['configuration']['2004'].union_fee = 1250.0
295        self.app['configuration']['2004'].welfare_fee = 750.0
296        self.student.nationality = u'NG'
297        # Login
298        IWorkflowState(self.student).setState('cleared')
299        self.browser.open(self.login_path)
300        self.browser.getControl(name="form.login").value = self.student_id
301        self.browser.getControl(name="form.password").value = 'spwd'
302        self.browser.getControl("Login").click()
303        # Test school fee payments
304        self.browser.open(self.student_path + '/payments')
305        self.browser.getLink("Add current session payment ticket").click()
306        self.browser.getControl(name="form.p_category").value = ['schoolfee_incl']
307        self.browser.getControl("Create ticket").click()
308        self.assertTrue('ticket created' in self.browser.contents)
309        value = self.student['payments'].keys()[0]
310        self.browser.getLink(value).click()
311        self.assertTrue('Amount Authorized' in self.browser.contents)
312        self.assertEqual(self.student['payments'][value].amount_auth, 51750.0)
313        self.browser.open(self.browser.url + '/payment_slip.pdf')
314        self.assertEqual(self.browser.headers['Status'], '200 Ok')
315        self.assertEqual(self.browser.headers['Content-Type'], 'application/pdf')
316        path = os.path.join(samples_dir(), 'payment_slip.pdf')
317        open(path, 'wb').write(self.browser.contents)
318        print "Sample PDF payment_slip.pdf written to %s" % path
319        # Test hostel maintenance payments
320        self.browser.open(self.student_path + '/payments')
321        self.browser.getLink("Add current session payment ticket").click()
322        self.browser.getControl(name="form.p_category").value = ['hostel_maintenance']
323        self.browser.getControl("Create ticket").click()
324        self.assertTrue('ticket created' in self.browser.contents)
325        value = self.student['payments'].keys()[1]
326        self.browser.getLink(value).click()
327        self.assertTrue('<span>My bed coordinates</span>' in self.browser.contents)
328        self.assertEqual(self.student['payments'][value].amount_auth, 876.0)
329        return
330
331    def test_late_registration(self):
332        # Login
333        delta = timedelta(days=10)
334        self.app['configuration'][
335            '2004'].coursereg_deadline = datetime.now(pytz.utc) - delta
336        IWorkflowState(self.student).setState('school fee paid')
337        # Current session is 2004. Here we test course registration for
338        # returning students.
339        self.student['studycourse'].entry_session = 2003
340        self.browser.open(self.login_path)
341        self.browser.getControl(name="form.login").value = self.student_id
342        self.browser.getControl(name="form.password").value = 'spwd'
343        self.browser.getControl("Login").click()
344        self.browser.open(self.payments_path)
345        self.browser.open(self.payments_path + '/addop')
346        self.browser.getControl(name="form.p_category").value = ['late_registration']
347        self.browser.getControl("Create ticket").click()
348        self.assertMatches('...ticket created...',
349                           self.browser.contents)
350        self.browser.getLink("Study Course").click()
351        self.browser.getLink("Add course list").click()
352        self.assertMatches('...Add current level 100 (Year 1)...',
353                           self.browser.contents)
354        self.browser.getControl("Create course list now").click()
355        self.browser.getLink("100").click()
356        self.browser.getLink("Edit course list").click()
357        self.browser.getControl("Register course list").click()
358        self.assertTrue('Course registration has ended. Please pay' in self.browser.contents)
359        self.student['payments'].values()[0].approve()
360        self.browser.getControl("Register course list").click()
361        self.assertTrue('Course list has been registered' in self.browser.contents)
362        self.assertEqual(self.student.state, 'courses registered')
363        # Reset student and check if fresh students are always allowed to
364        # register courses.
365        self.student['studycourse'].entry_session = 2004
366        del self.student['payments'][self.student['payments'].keys()[0]]
367        IWorkflowState(self.student).setState('school fee paid')
368        self.browser.open(self.studycourse_path + '/100/edit')
369        self.browser.getControl("Register course list").click()
370        self.assertTrue('Course list has been registered' in self.browser.contents)
371        return
372
373
374    def deactivated_test_student_course_registration(self):
375        # Add more courses
376        self.course2 = createObject('waeup.Course')
377        self.course2.code = 'COURSE2'
378        self.course2.semester = 2
379        self.course2.credits = 10
380        self.course2.passmark = 40
381        self.app['faculties']['fac1']['dep1'].courses.addCourse(
382            self.course2)
383        self.app['faculties']['fac1']['dep1'].certificates['CERT1'].addCertCourse(
384            self.course2, level=100)
385        self.course3 = createObject('waeup.Course')
386        self.course3.code = 'COURSE3'
387        self.course3.semester = 3
388        self.course3.credits = 10
389        self.course3.passmark = 40
390        self.app['faculties']['fac1']['dep1'].courses.addCourse(
391            self.course3)
392        self.app['faculties']['fac1']['dep1'].certificates['CERT1'].addCertCourse(
393            self.course3, level=100)
394
395        # Login as student
396        self.browser.open(self.login_path)
397        IWorkflowState(self.student).setState('school fee paid')
398        self.browser.open(self.login_path)
399        self.browser.getControl(name="form.login").value = self.student_id
400        self.browser.getControl(name="form.password").value = 'spwd'
401        self.browser.getControl("Login").click()
402        # Students can add the current study level
403        self.browser.getLink("Study Course").click()
404        self.browser.getLink("Add course list").click()
405        self.assertMatches('...Add current level 100 (Year 1)...',
406                           self.browser.contents)
407        self.browser.getControl("Create course list now").click()
408        # Student has not paid second instalment, therefore a level
409        # with two course ticket was created (semester 1 and combined)
410        self.assertEqual(self.student['studycourse']['100'].number_of_tickets, 2)
411        self.browser.getLink("100").click()
412        self.browser.getLink("Edit course list").click()
413        self.browser.getControl("Add course ticket").click()
414        # Student can't add second semester course
415        self.assertTrue('<option value="COURSE1">' in self.browser.contents)
416        self.assertTrue('<option value="COURSE3">' in self.browser.contents)
417        self.assertFalse('<option value="COURSE2">' in self.browser.contents)
418
419        # Let's remove level and see what happens after 2nd instalment payment
420        del(self.student['studycourse']['100'])
421        payment2 = createObject('waeup.StudentOnlinePayment')
422        payment2.p_category = u'schoolfee_2'
423        payment2.p_session = self.student.current_session
424        self.student['payments']['anykey'] = payment2
425        self.browser.open(self.studycourse_path)
426        self.browser.getLink("Add course list").click()
427        self.browser.getControl("Create course list now").click()
428        # Still only 2 tickets have been created since payment ticket
429        # was not paid
430        self.assertEqual(self.student['studycourse']['100'].number_of_tickets, 2)
431        payment2.p_state = u'paid'
432        del(self.student['studycourse']['100'])
433        self.browser.open(self.studycourse_path)
434        self.browser.getLink("Add course list").click()
435        self.browser.getControl("Create course list now").click()
436        # Now 2nd semester course has been added
437        self.assertEqual(self.student['studycourse']['100'].number_of_tickets, 3)
438        # Student can add second semester course
439        self.browser.getLink("100").click()
440        self.browser.getLink("Edit course list").click()
441        self.browser.getControl("Add course ticket").click()
442        self.assertTrue('<option value="COURSE1">' in self.browser.contents)
443        self.assertTrue('<option value="COURSE2">' in self.browser.contents)
444        self.assertTrue('<option value="COURSE3">' in self.browser.contents)
445        return
446
447    def test_set_matric_number(self):
448        #payment = createObject('waeup.StudentOnlinePayment')
449        #payment.p_category = u'concessional'
450        #payment.p_id = u'anyid'
451        #payment.p_state = u'paid'
452        #self.student['payments']['anykey'] = payment
453        # Login as student
454        self.browser.open(self.login_path)
455        IWorkflowState(self.student).setState('school fee paid')
456        self.browser.open(self.login_path)
457        self.browser.getControl(name="form.login").value = self.student_id
458        self.browser.getControl(name="form.password").value = 'spwd'
459        self.browser.getControl("Login").click()
460        self.assertRaises(
461            LinkNotFoundError,
462            self.browser.getLink, 'Get Matriculation Number')
463        self.student.matric_number = None
464        site = grok.getSite()
465        site['configuration'].next_matric_integer = 1
466        self.student['studycourse'].certificate.study_mode = 'ug_pt'
467        self.browser.open(self.student_path)
468        self.assertRaises(
469            LinkNotFoundError,
470            self.browser.getLink, 'Download matriculation number slip')
471        self.browser.getLink("Get Matriculation Number").click()
472        self.assertTrue('Matriculation number PTP/fac1/dep1/04/00001 assigned.'
473            in self.browser.contents)
474        self.assertEqual(self.student.matric_number, 'PTP/fac1/dep1/04/00001')
475        self.assertRaises(
476            LinkNotFoundError,
477            self.browser.getLink, 'Get Matriculation Number')
478        # Setting matric number is logged.
479        logfile = os.path.join(
480            self.app['datacenter'].storage, 'logs', 'students.log')
481        logcontent = open(logfile).read()
482        self.assertTrue('E1000000 - waeup.aaue.students.browser.StudentGetMatricNumberPage - '
483                        'E1000000 - PTP/fac1/dep1/04/00001 assigned' in logcontent)
484        # Matric Number Slip can be downloaded
485        self.browser.getLink("Download matriculation number slip").click()
486        self.assertEqual(self.browser.headers['Status'], '200 Ok')
487        self.assertEqual(self.browser.headers['Content-Type'], 'application/pdf')
488        path = os.path.join(samples_dir(), 'matric_number_slip.pdf')
489        open(path, 'wb').write(self.browser.contents)
490        print "Sample PDF matric_number_slip.pdf written to %s" % path
491        return
492
493    def test_personal_data_slip(self):
494        # Login as student
495        self.browser.open(self.login_path)
496        IWorkflowState(self.student).setState('school fee paid')
497        self.browser.open(self.login_path)
498        self.browser.getControl(name="form.login").value = self.student_id
499        self.browser.getControl(name="form.password").value = 'spwd'
500        self.browser.getControl("Login").click()
501        self.browser.getLink("Personal Data").click()
502        self.assertRaises(
503            LinkNotFoundError,
504            self.browser.getLink, 'Download personal data slip')
505        self.student.father_name = u'Rudolf'
506        self.browser.open(self.personal_path)
507        self.browser.getLink("Download personal data slip").click()
508        self.assertEqual(self.browser.headers['Status'], '200 Ok')
509        self.assertEqual(self.browser.headers['Content-Type'], 'application/pdf')
510        path = os.path.join(samples_dir(), 'personal_data_slip.pdf')
511        open(path, 'wb').write(self.browser.contents)
512        print "Sample PDF personal_data_slip.pdf written to %s" % path
513        return
514
515    def test_student_course_registration(self):
516        IWorkflowState(self.student).setState('school fee paid')
517        self.browser.open(self.login_path)
518        self.browser.getControl(name="form.login").value = self.student_id
519        self.browser.getControl(name="form.password").value = 'spwd'
520        self.browser.getControl("Login").click()
521        # Now students can add the current study level
522        self.browser.getLink("Study Course").click()
523        self.browser.getLink("Add course list").click()
524        self.assertMatches('...Add current level 100 (Year 1)...',
525                           self.browser.contents)
526        self.browser.getControl("Create course list now").click()
527        # Students can't open the customized pdf course registration slip
528        self.browser.open(
529            self.student_path + '/studycourse/100/course_registration_slip.pdf')
530        self.assertTrue('Forbidden' in self.browser.contents)
531        # They can open slips from the previous session ...
532        self.student['studycourse'].current_level = 200
533        self.browser.open(self.student_path + '/studycourse/100')
534        self.browser.getLink("Download course registration slip").click()
535        self.assertEqual(self.browser.headers['Status'], '200 Ok')
536        self.assertEqual(self.browser.headers['Content-Type'], 'application/pdf')
537        # or if they have registered their course list
538        self.student['studycourse'].current_level = 200
539        IWorkflowState(self.student).setState('courses registered')
540        self.browser.open(self.student_path + '/studycourse/100')
541        self.browser.getLink("Download course registration slip").click()
542        self.assertEqual(self.browser.headers['Status'], '200 Ok')
543        self.assertEqual(self.browser.headers['Content-Type'], 'application/pdf')
544        path = os.path.join(samples_dir(), 'ft_course_registration_slip.pdf')
545        open(path, 'wb').write(self.browser.contents)
546        print "Sample PDF ft_course_registration_slip.pdf written to %s" % path
547
548        self.certificate.study_mode = 'ug_pt'
549        self.browser.open(self.student_path + '/studycourse/100')
550        self.browser.getLink("Download course registration slip").click()
551        self.assertEqual(self.browser.headers['Status'], '200 Ok')
552        self.assertEqual(self.browser.headers['Content-Type'], 'application/pdf')
553        path = os.path.join(samples_dir(), 'pt_course_registration_slip.pdf')
554        open(path, 'wb').write(self.browser.contents)
555        print "Sample PDF pt_course_registration_slip.pdf written to %s" % path
556
557        self.certificate.study_mode = 'special_pg_ft'
558        self.student.matric_number = u'AAU/SPS/FLW/LAW/15/PHD/09504'
559        self.browser.open(self.student_path + '/studycourse/100')
560        self.browser.getLink("Download course registration slip").click()
561        self.assertEqual(self.browser.headers['Status'], '200 Ok')
562        self.assertEqual(self.browser.headers['Content-Type'], 'application/pdf')
563        path = os.path.join(samples_dir(), 'pg_course_registration_slip.pdf')
564        open(path, 'wb').write(self.browser.contents)
565        print "Sample PDF pg_course_registration_slip.pdf written to %s" % path
566
567    def test_student_clearance(self):
568        # Student cant login if their password is not set
569        IWorkflowInfo(self.student).fireTransition('admit')
570        self.browser.open(self.login_path)
571        self.browser.getControl(name="form.login").value = self.student_id
572        self.browser.getControl(name="form.password").value = 'spwd'
573        self.browser.getControl("Login").click()
574        self.assertMatches(
575            '...You logged in...', self.browser.contents)
576        # Admitted student can upload a passport picture
577        self.browser.open(self.student_path + '/change_portrait')
578        ctrl = self.browser.getControl(name='passportuploadedit')
579        file_obj = open(SAMPLE_IMAGE, 'rb')
580        file_ctrl = ctrl.mech_control
581        file_ctrl.add_file(file_obj, filename='my_photo.jpg')
582        self.browser.getControl(
583            name='upload_passportuploadedit').click()
584        self.assertTrue(
585            'src="http://localhost/app/students/E1000000/passport.jpg"'
586            in self.browser.contents)
587        # Student is redirected to the personal data form because
588        # personal data form is not properly filled.
589        self.browser.open(self.student_path + '/start_clearance')
590        self.assertMatches('...Personal data form is not properly filled...',
591                           self.browser.contents)
592        self.assertEqual(self.browser.url, self.student_path + '/edit_personal')
593        self.student.father_name = u'Rudolf'
594        self.browser.open(self.student_path + '/start_clearance')
595        self.assertMatches(
596            '...<h1 class="kofa-content-label">Start clearance</h1>...',
597            self.browser.contents)
598
599    def test_student_accommodation(self):
600        del self.student['accommodation']['2004']
601        self.student['studycourse'].certificate.study_mode = 'dp_ft'
602        # All beds can be assigned
603        bed1 = self.app['hostels']['hall-1']['hall-1_A_101_A']
604        bed1.bed_type = u'regular_male_all'
605        bed2 = self.app['hostels']['hall-1']['hall-1_A_101_B']
606        bed2.bed_type = u'regular_female_all'
607        notify(grok.ObjectModifiedEvent(bed1))
608        notify(grok.ObjectModifiedEvent(bed2))
609        # Login
610        self.browser.open(self.login_path)
611        self.browser.getControl(name="form.login").value = self.student_id
612        self.browser.getControl(name="form.password").value = 'spwd'
613        self.browser.getControl("Login").click()
614        # Students can book accommodation without AC ...
615        self.browser.open(self.acco_path)
616        IWorkflowInfo(self.student).fireTransition('admit')
617        self.browser.getControl("Book accommodation").click()
618        self.assertTrue(
619            'You are not eligible to book accommodation.'
620            in self.browser.contents)
621        self.student['studycourse'].certificate.study_mode = 'ug_ft'
622        self.browser.getControl("Book accommodation").click()
623        self.assertFalse('Activation Code:' in self.browser.contents)
624        self.browser.getControl("Create bed ticket").click()
625        # Bed is randomly selected but, since there is only
626        # one bed for this student, we know that
627        self.assertEqual(self.student['accommodation']['2004'].bed_coordinates,
628            'Hall 1, Block A, Room 101, Bed A (regular_male_all)')
629        # Only the hall name is displayed
630        self.assertEqual(self.student[
631            'accommodation']['2004'].display_coordinates,
632            'Hall 1')
633        self.assertFalse('Hall 1, Block A, Room 101, Bed A'
634            in self.browser.contents)
635        self.assertTrue('<td>Hall 1</td>'
636            in self.browser.contents)
637        return
638
639    def test_handle_courses_by_lecturer(self):
640        self.app['users'].addUser('mrslecturer', 'mrslecturersecret')
641        self.app['users']['mrslecturer'].email = 'mrslecturer@foo.ng'
642        self.app['users']['mrslecturer'].title = u'Mercedes Benz'
643        # Add course ticket
644        studylevel = createObject(u'waeup.StudentStudyLevel')
645        studylevel.level = 100
646        studylevel.level_session = 2004
647        self.student['studycourse'].addStudentStudyLevel(
648            self.certificate, studylevel)
649        # Assign local Lecturer role for a certificate.
650        course = self.app['faculties']['fac1']['dep1'].courses['COURSE1']
651        prmlocal = IPrincipalRoleManager(course)
652        prmlocal.assignRoleToPrincipal('waeup.local.Lecturer', 'mrslecturer')
653        notify(LocalRoleSetEvent(
654            course, 'waeup.local.Lecturer', 'mrslecturer', granted=True))
655        # Login as lecturer.
656        self.browser.open(self.login_path)
657        self.browser.getControl(name="form.login").value = 'mrslecturer'
658        self.browser.getControl(name="form.password").value = 'mrslecturersecret'
659        self.browser.getControl("Login").click()
660        self.browser.getLink("My Roles").click()
661        self.browser.getLink(
662            "http://localhost/app/faculties/fac1/dep1/courses/COURSE1").click()
663        # Course results can be batch edited via the edit_courses view.
664        self.app['faculties']['fac1']['dep1'].score_editing_disabled = False
665        self.app['configuration'].current_academic_session = 2004
666        IWorkflowState(self.student).setState('courses validated')
667        self.browser.open(
668            "http://localhost/app/faculties/fac1/dep1/courses/COURSE1/edit_scores")
669        self.assertTrue(
670            'input type="text" name="scores"'
671            in self.browser.contents)
672        self.browser.getControl(name="scores", index=0).value = '55'
673        self.browser.getControl(name="cas", index=0).value = '66'
674        self.browser.getControl("Update scores").click()
675        # New score and ca has been set.
676        self.assertEqual(
677            self.student['studycourse']['100']['COURSE1'].score, 55)
678        self.assertEqual(
679            self.student['studycourse']['100']['COURSE1'].ca, 66)
680        # Score editing has been logged.
681        logfile = os.path.join(
682            self.app['datacenter'].storage, 'logs', 'students.log')
683        logcontent = open(logfile).read()
684        self.assertTrue('mrslecturer - waeup.aaue.students.browser.CustomEditScoresPage - '
685                        'E1000000 100/COURSE1 score updated (55)' in logcontent)
686        self.assertTrue('mrslecturer - waeup.aaue.students.browser.CustomEditScoresPage - '
687                        'E1000000 100/COURSE1 ca updated (66)' in logcontent)
688        # Non-integer scores won't be accepted.
689        self.browser.open(
690            "http://localhost/app/faculties/fac1/dep1/courses/COURSE1/edit_scores")
691        self.assertTrue('value="55" />' in self.browser.contents)
692        self.browser.getControl(name="scores", index=0).value = 'abc'
693        self.browser.getControl("Update scores").click()
694        self.assertTrue('Error: Score(s) and CA(s) of Anna Tester have not be updated.'
695            in self.browser.contents)
696        # Scores can be removed.
697        self.browser.open(
698            "http://localhost/app/faculties/fac1/dep1/courses/COURSE1/edit_scores")
699        self.browser.getControl(name="scores", index=0).value = ''
700        self.browser.getControl("Update scores").click()
701        self.assertEqual(
702            self.student['studycourse']['100']['COURSE1'].score, None)
703        logcontent = open(logfile).read()
704        self.assertTrue('mrslecturer - waeup.aaue.students.browser.CustomEditScoresPage - '
705                        'E1000000 100/COURSE1 score updated (None)' in logcontent)
Note: See TracBrowser for help on using the repository browser.