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

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

Adjust customizations to changes in base package.

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