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

Last change on this file since 13855 was 13855, checked in by Henrik Bettermann, 8 years ago

See ticket #213.

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