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

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

Extend DISABLE_PAYMENT_GROUP_DICT.

  • Property svn:keywords set to Id
File size: 51.2 KB
Line 
1## $Id: test_browser.py 14246 2016-11-01 07:22:54Z 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, PAID
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
45UPLOAD_CSV_TEMPLATE = (
46    'matric_number,student_id,display_fullname,level,code,level_session,'
47    'score,ca\r\n'
48    '234,E1000000,Anna Tester,100,COURSE1,2004,%s,%s\r\n')
49
50class OfficerUITests(StudentsFullSetup):
51    # Tests for Student class views and pages
52
53    layer = FunctionalLayer
54
55    def login_as_lecturer(self):
56        self.app['users'].addUser('mrslecturer', 'mrslecturersecret')
57        self.app['users']['mrslecturer'].email = 'mrslecturer@foo.ng'
58        self.app['users']['mrslecturer'].title = u'Mercedes Benz'
59        # Add course ticket
60        studylevel = createObject(u'waeup.StudentStudyLevel')
61        studylevel.level = 100
62        studylevel.level_session = 2004
63        self.student['studycourse'].addStudentStudyLevel(
64            self.certificate, studylevel)
65        # Assign local Lecturer role for a certificate.
66        course = self.app['faculties']['fac1']['dep1'].courses['COURSE1']
67        prmlocal = IPrincipalRoleManager(course)
68        prmlocal.assignRoleToPrincipal('waeup.local.Lecturer', 'mrslecturer')
69        notify(LocalRoleSetEvent(
70            course, 'waeup.local.Lecturer', 'mrslecturer', granted=True))
71        # Login as lecturer.
72        self.browser.open(self.login_path)
73        self.browser.getControl(name="form.login").value = 'mrslecturer'
74        self.browser.getControl(
75            name="form.password").value = 'mrslecturersecret'
76        self.browser.getControl("Login").click()
77        # Store reused urls/paths
78        self.course_url = (
79            'http://localhost/app/faculties/fac1/dep1/courses/COURSE1')
80        self.edit_scores_url = '%s/edit_scores' % self.course_url
81        # Set standard parameters
82        self.app['configuration'].current_academic_session = 2004
83        self.app['faculties']['fac1']['dep1'].score_editing_disabled = False
84        IWorkflowState(self.student).setState(VALIDATED)
85
86
87    def test_gpa_calculation(self):
88        studylevel = createObject(u'waeup.StudentStudyLevel')
89        studylevel.level = 100
90        studylevel.level_session = 2005
91        self.student['studycourse'].entry_mode = 'ug_ft'
92        self.student['studycourse'].addStudentStudyLevel(
93            self.certificate, studylevel)
94        # First course has been added automatically.
95        # Set score.
96        studylevel['COURSE1'].score = 35
97        studylevel['COURSE1'].ca = 20
98        # GPA is 3.0.
99        self.assertEqual(studylevel.gpa_params[0], 3.0)
100        courseticket = createObject('waeup.CourseTicket')
101        courseticket.code = 'ANYCODE'
102        courseticket.title = u'Any TITLE'
103        courseticket.credits = 13
104        courseticket.score = 44
105        courseticket.ca = 22
106        courseticket.semester = 1
107        courseticket.dcode = u'ANYDCODE'
108        courseticket.fcode = u'ANYFCODE'
109        studylevel['COURSE2'] = courseticket
110        # total credits
111        self.assertEqual(self.student['studycourse']['100'].gpa_params[1], 23)
112        # weigheted credits = 3 * 10 + 4 * 13
113        self.assertEqual(self.student['studycourse']['100'].gpa_params[2], 82.0)
114        # sgpa = 82 / 23
115        self.assertEqual(
116            self.student['studycourse']['100'].gpa_params[0], 3.565)
117        # imported gpa values override calculated values
118        studylevel.imported_gpa = 4.3
119        studylevel.imported_cgpa = 5.4
120        self.assertEqual(self.student['studycourse']['100'].gpa_params[0], 4.3)
121        self.assertEqual(
122            self.student['studycourse']['100'].cumulative_params[0], 5.4)
123        self.assertEqual(self.student['studycourse']['100'].gpa, 4.3)
124        self.student['studycourse'].imported_cgpa = 6.6
125        self.assertEqual(
126            self.student['studycourse'].getTranscriptData()[1], 6.6)
127        return
128
129    def test_grade_weight(self):
130        studylevel = createObject(u'waeup.StudentStudyLevel')
131        studylevel.level = 100
132        studylevel.level_session = 2005
133        self.student['studycourse'].entry_mode = 'ug_ft'
134        self.student['studycourse'].addStudentStudyLevel(
135            self.certificate, studylevel)
136        studylevel['COURSE1'].score = 42
137        studylevel['COURSE1'].ca = 0
138        courseticket = createObject('waeup.CourseTicket')
139        self.assertEqual(studylevel['COURSE1'].weight, 1)
140        self.assertEqual(studylevel['COURSE1'].grade, 'E')
141        self.student['studycourse'].entry_session = 2015
142        self.assertEqual(studylevel['COURSE1'].weight, 0)
143        self.assertEqual(studylevel['COURSE1'].grade, 'F')
144        studylevel['COURSE1'].score = 45
145        self.assertEqual(studylevel['COURSE1'].weight, 2)
146        self.assertEqual(studylevel['COURSE1'].grade, 'D')
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.app['configuration']['2004'].clearance_fee = 666.0
168        self.browser.getControl(name="form.p_category").value = ['clearance_incl']
169        self.browser.getControl("Create ticket").click()
170        ctrl = self.browser.getControl(name='val_id')
171        cpt_value = ctrl.options[0]
172        # School fee payment ticket can be added ...
173        self.student['studycourse'].certificate.school_fee_1 = 6666.0
174        self.student.nationality = u'NG'
175        self.browser.open(self.payments_path + '/addop')
176        self.browser.getControl(name="form.p_category").value = ['schoolfee_incl']
177        self.browser.getControl("Create ticket").click()
178        self.assertMatches('...ticket created...',
179                           self.browser.contents)
180        # ... but not paid through the query_history page.
181        ctrl = self.browser.getControl(name='val_id')
182        sfpt_value = ctrl.options[1]
183        self.student['studycourse'].entry_session = 2013
184        self.browser.open(self.payments_path + '/' + sfpt_value)
185        self.browser.getLink("Query eTranzact History").click()
186        self.assertMatches('...alert-danger">Please pay acceptance fee first...',
187                           self.browser.contents)
188        # If clearance/acceptance fee is paid ...
189        self.student['payments'][cpt_value].approveStudentPayment()
190        self.browser.getLink("Query eTranzact History").click()
191        # ... query_history page is accessible.
192        self.assertMatches(
193            '...<h1 class="kofa-content-label">Requery eTranzact History</h1>...',
194            self.browser.contents)
195        # Managers can open school fee payment slip
196        self.browser.open(self.payments_path + '/' + sfpt_value)
197        self.browser.getLink("Download payment slip").click()
198        self.assertEqual(self.browser.headers['Status'], '200 Ok')
199        self.assertEqual(self.browser.headers['Content-Type'], 'application/pdf')
200        # If school fee ticket is paid, the student is automatically set to
201        # school fee paid...
202        ticket = self.student['payments'][sfpt_value].approveStudentPayment()
203        self.assertEqual(self.student.state, 'school fee paid')
204        # ... no further school fee ticket can be added.
205        self.browser.open(self.payments_path + '/addop')
206        self.browser.getControl(name="form.p_category").value = ['schoolfee_incl']
207        self.browser.getControl("Create ticket").click()
208        self.assertMatches('...Wrong state...',
209                           self.browser.contents)
210        self.browser.open(self.payments_path + '/addop')
211        self.browser.getControl(name="form.p_category").value = ['late_registration']
212        self.browser.getControl("Create ticket").click()
213        self.assertMatches('...ticket created...',
214                           self.browser.contents)
215        return
216
217    def test_for_instalment_payments(self):
218
219        configuration_1 = createObject('waeup.SessionConfiguration')
220        configuration_1.academic_session = 2015
221        self.app['configuration'].addSessionConfiguration(configuration_1)
222        self.student['studycourse'].certificate.study_mode = 'ug_pt'
223        self.student['studycourse'].certificate.school_fee_1 = 6666.0
224        self.app['configuration']['2015'].union_fee = 1250.0
225        self.app['configuration']['2015'].welfare_fee = 750.0
226        self.student.nationality = u'NG'
227        self.browser.addHeader('Authorization', 'Basic mgr:mgrpw')
228        self.browser.open(self.payments_path + '/addop')
229        self.browser.getControl(name="form.p_category").value = ['schoolfee_1']
230        self.browser.getControl("Create ticket").click()
231        self.assertTrue(
232            'Part-time students are not allowed' in self.browser.contents)
233        self.student['studycourse'].certificate.study_mode = 'ug_ft'
234        self.browser.open(self.payments_path + '/addop')
235        self.browser.getControl(name="form.p_category").value = ['schoolfee_1']
236        self.browser.getControl("Create ticket").click()
237        self.assertTrue('You are not allowed to pay by instalments.'
238            in self.browser.contents)
239        IWorkflowState(self.student).setState('cleared')
240        self.student['studycourse'].entry_session = 2015
241        self.student['studycourse'].current_session = 2015
242        self.browser.open(self.payments_path + '/addop')
243        self.browser.getControl(name="form.p_category").value = ['schoolfee_1']
244        self.browser.getControl("Create ticket").click()
245        self.assertTrue('ticket created' in self.browser.contents)
246        # We can't add the 2nd instalment ticket because the
247        # first one has not yet been approved.
248        #self.browser.open(self.payments_path + '/addop')
249        #self.browser.getControl(name="form.p_category").value = ['schoolfee_2']
250        #self.browser.getControl("Create ticket").click()
251        #self.assertMatches('...1st school fee instalment has not yet been paid...',
252        #                   self.browser.contents)
253        # Ok, then we approve the first instalment ...
254        self.browser.open(self.payments_path)
255        ctrl = self.browser.getControl(name='val_id')
256        p_id = ctrl.options[0]
257        self.browser.open(self.payments_path + '/' + p_id + '/approve')
258        # ... add the second instalment ...
259        self.browser.open(self.payments_path + '/addop')
260        self.browser.getControl(name="form.p_category").value = ['schoolfee_2']
261        self.browser.getControl("Create ticket").click()
262        self.assertTrue('ticket created' in self.browser.contents)
263        # ... approve the second instalment ...
264        ctrl = self.browser.getControl(name='val_id')
265        p_id = ctrl.options[1]
266        self.browser.open(self.payments_path + '/' + p_id + '/approve')
267        self.assertEqual(self.student['payments'].values()[0].p_category, 'schoolfee_1')
268        self.assertEqual(self.student['payments'].values()[1].p_category, 'schoolfee_2')
269        # (6666-250)/2 + 1250 + 750 - 500 + 250
270        self.assertEqual(self.student['payments'].values()[0].amount_auth, 4958.0)
271        # (6666-250)/2 + 250
272        self.assertEqual(self.student['payments'].values()[1].amount_auth, 3458.0)
273        # The  two payments belong to the same session and level.
274        self.assertEqual(self.student['payments'].values()[0].p_session, 2015)
275        self.assertEqual(self.student['payments'].values()[0].p_level, 100)
276        self.assertEqual(self.student['payments'].values()[1].p_session, 2015)
277        self.assertEqual(self.student['payments'].values()[1].p_level, 100)
278
279        # Returning student
280        configuration_2 = createObject('waeup.SessionConfiguration')
281        configuration_2.academic_session = 2016
282        self.app['configuration'].addSessionConfiguration(configuration_2)
283        self.student['studycourse'].certificate.school_fee_2 = 5666.0
284        self.app['configuration']['2016'].union_fee = 1250.0
285        self.app['configuration']['2016'].welfare_fee = 750.0
286        self.student.father_name = u'Albert'
287        IWorkflowState(self.student).setState('returning')
288        self.browser.open(self.payments_path + '/addop')
289        self.browser.getControl(name="form.p_category").value = ['schoolfee_1']
290        self.browser.getControl("Create ticket").click()
291        self.browser.open(self.payments_path + '/addop')
292        self.browser.getControl(name="form.p_category").value = ['schoolfee_2']
293        self.browser.getControl("Create ticket").click()
294        # Student is still in the first  session.
295        self.assertTrue('This type of payment' in self.browser.contents)
296        self.browser.open(self.payments_path)
297        ctrl = self.browser.getControl(name='val_id')
298        p_id = ctrl.options[2]
299        self.browser.open(self.payments_path + '/' + p_id + '/approve')
300        self.browser.open(self.payments_path + '/addop')
301        self.browser.getControl(name="form.p_category").value = ['schoolfee_2']
302        self.browser.getControl("Create ticket").click()
303        self.assertTrue('ticket created' in self.browser.contents)
304        # (5666-250)/2 + 1250 + 750 - 500 + 250
305        self.assertEqual(self.student['payments'].values()[2].amount_auth, 4458.0)
306        # (5666-250)/2 + 250
307        self.assertEqual(self.student['payments'].values()[3].amount_auth, 2958.0)
308        # The last two payments belong to the same session and level.
309        self.assertEqual(self.student['payments'].values()[2].p_session, 2016)
310        self.assertEqual(self.student['payments'].values()[2].p_level, 200)
311        self.assertEqual(self.student['payments'].values()[3].p_session, 2016)
312        self.assertEqual(self.student['payments'].values()[3].p_level, 200)
313        return
314
315    def test_manage_payments_bypass_ac_creation(self):
316        self.student['studycourse'].certificate.school_fee_1 = 6666.0
317        self.student.nationality = u'NG'
318        self.browser.addHeader('Authorization', 'Basic mgr:mgrpw')
319        self.browser.open(self.payments_path)
320        IWorkflowState(self.student).setState('cleared')
321        self.browser.getLink("Add current session payment ticket").click()
322        self.browser.getControl(name="form.p_category").value = ['schoolfee_incl']
323        self.browser.getControl("Create ticket").click()
324        ctrl = self.browser.getControl(name='val_id')
325        value = ctrl.options[0]
326        self.browser.getLink(value).click()
327        payment_url = self.browser.url
328        logfile = os.path.join(
329            self.app['datacenter'].storage, 'logs', 'students.log')
330        # The ticket can be found in the payments_catalog
331        cat = queryUtility(ICatalog, name='payments_catalog')
332        results = list(cat.searchResults(p_state=('unpaid', 'unpaid')))
333        self.assertTrue(len(results), 1)
334        self.assertTrue(results[0] is self.student['payments'][value])
335        # Managers can approve the payment
336        self.browser.open(payment_url)
337        self.browser.getLink("Approve payment").click()
338        self.assertMatches('...Payment approved...',
339                          self.browser.contents)
340        # Approval is logged in students.log ...
341        logcontent = open(logfile).read()
342        self.assertTrue(
343            'zope.mgr - students.browser.OnlinePaymentApproveView '
344            '- E1000000 - schoolfee_incl payment approved'
345            in logcontent)
346        # ... and in payments.log
347        logfile = os.path.join(
348            self.app['datacenter'].storage, 'logs', 'payments.log')
349        logcontent = open(logfile).read()
350        self.assertTrue(
351            '"zope.mgr",E1000000,%s,schoolfee_incl,6666.0,AP,,,,,,\n' % value
352            in logcontent)
353        # Student is in state school fee paid, no activation
354        # code was necessary.
355        self.assertEqual(self.student.state, 'school fee paid')
356        self.assertEqual(len(self.app['accesscodes']['SFE-0']),0)
357        return
358
359    def test_scores_csv_upload_available(self):
360        # lecturers can upload a CSV file to set values.
361        self.login_as_lecturer()
362        # set value to change from
363        self.student['studycourse']['100']['COURSE1'].score = 55
364        self.browser.open(self.edit_scores_url)
365        upload_ctrl = self.browser.getControl(name='uploadfile:file')
366        upload_file = StringIO(UPLOAD_CSV_TEMPLATE % ('65','22'))
367        upload_ctrl.add_file(upload_file, 'text/csv', 'myscores.csv')
368        self.browser.getControl("Update editable scores from").click()
369        # value changed
370        self.assertEqual(
371            self.student['studycourse']['100']['COURSE1'].score, 65)
372        self.assertEqual(
373            self.student['studycourse']['100']['COURSE1'].ca, 22)
374
375    def test_lecturers_can_download_course_tickets(self):
376        # A course ticket slip can be downloaded
377        self.login_as_lecturer()
378        pdf_url = '%s/coursetickets.pdf' % self.course_url
379        self.browser.open(pdf_url)
380        self.assertEqual(self.browser.headers['Status'], '200 Ok')
381        self.assertEqual(
382            self.browser.headers['Content-Type'], 'application/pdf')
383        path = os.path.join(samples_dir(), 'coursetickets.pdf')
384        open(path, 'wb').write(self.browser.contents)
385        print "Sample PDF coursetickets.pdf written to %s" % path
386
387    def test_transcripts(self):
388        studylevel = createObject(u'waeup.StudentStudyLevel')
389        studylevel.level = 100
390        studylevel.level_session = 2005
391        self.student['studycourse'].entry_mode = 'ug_ft'
392        self.student['studycourse'].addStudentStudyLevel(
393            self.certificate, studylevel)
394        studylevel2 = createObject(u'waeup.StudentStudyLevel')
395        studylevel2.level = 200
396        studylevel2.level_session = 2006
397        self.student['studycourse']['100']['COURSE1'].score = 33 # no carry-over!
398        self.student['studycourse']['100']['COURSE1'].ca = 22
399        self.student['studycourse'].addStudentStudyLevel(
400            self.certificate, studylevel2)
401        # Add second course (COURSE has been added automatically)
402        courseticket = createObject('waeup.CourseTicket')
403        courseticket.code = 'ANYCODE'
404        courseticket.title = u'Any TITLE'
405        courseticket.credits = 13
406        courseticket.score = 55
407        courseticket.ca = 11
408        courseticket.semester = 1
409        courseticket.dcode = u'ANYDCODE'
410        courseticket.fcode = u'ANYFCODE'
411        self.student['studycourse']['200']['COURSE2'] = courseticket
412        self.assertEqual(self.student['studycourse']['100'].gpa_params_rectified[0], 3.0)
413        self.assertEqual(self.student['studycourse']['200'].gpa_params_rectified[0], 4.0)
414        # Get transcript data
415        td = self.student['studycourse'].getTranscriptData()
416        self.assertEqual(td[0][0]['level_key'], '100')
417        self.assertEqual(td[0][0]['sgpa'], 3.0)
418        self.assertEqual(td[0][0]['level'].level, 100)
419        self.assertEqual(td[0][0]['level'].level_session, 2005)
420        self.assertEqual(td[0][0]['tickets_1'][0].code, 'COURSE1')
421        self.assertEqual(td[0][1]['level_key'], '200')
422        self.assertEqual(td[0][1]['sgpa'], 4.0)
423        self.assertEqual(td[0][1]['level'].level, 200)
424        self.assertEqual(td[0][1]['level'].level_session, 2006)
425        self.assertEqual(td[0][1]['tickets_1'][0].code, 'ANYCODE')
426        self.assertEqual(td[1], 3.57)
427        self.browser.addHeader('Authorization', 'Basic mgr:mgrpw')
428        self.browser.open(self.student_path + '/studycourse/transcript')
429        self.assertEqual(self.browser.headers['Status'], '200 Ok')
430        self.assertTrue('Transcript' in self.browser.contents)
431        # Officers can open the pdf transcript
432        self.browser.open(self.student_path + '/studycourse/transcript.pdf')
433        self.assertEqual(self.browser.headers['Status'], '200 Ok')
434        self.assertEqual(self.browser.headers['Content-Type'], 'application/pdf')
435        path = os.path.join(samples_dir(), 'transcript.pdf')
436        open(path, 'wb').write(self.browser.contents)
437        print "Sample PDF transcript.pdf written to %s" % path
438
439    def test_payment_disabled(self):
440        self.browser.addHeader('Authorization', 'Basic mgr:mgrpw')
441        self.browser.open(self.payments_path)
442        IWorkflowState(self.student).setState('cleared')
443        self.browser.getLink("Add current session payment ticket").click()
444        self.browser.getControl(name="form.p_category").value = ['schoolfee_incl']
445        self.browser.getControl("Create ticket").click()
446        self.assertMatches('...ticket created...', self.browser.contents)
447        self.app['configuration']['2004'].payment_disabled = ['sf_all']
448        self.browser.getLink("Add current session payment ticket").click()
449        self.browser.getControl(name="form.p_category").value = ['schoolfee_incl']
450        self.browser.getControl("Create ticket").click()
451        self.assertMatches('...This category of payments has been disabled...',
452                           self.browser.contents)
453
454        self.app['configuration']['2004'].payment_disabled = ['sf_pt']
455        self.browser.getControl(name="form.p_category").value = ['schoolfee_incl']
456        self.browser.getControl("Create ticket").click()
457        self.assertMatches('...ticket created...', self.browser.contents)
458        self.certificate.study_mode = 'ug_pt'
459        self.browser.getLink("Add current session payment ticket").click()
460        self.browser.getControl(name="form.p_category").value = ['schoolfee_incl']
461        self.browser.getControl("Create ticket").click()
462        self.assertMatches('...This category of payments has been disabled...',
463                           self.browser.contents)
464
465        self.app['configuration']['2004'].payment_disabled = ['sf_pg']
466        self.browser.getControl(name="form.p_category").value = ['schoolfee_incl']
467        self.browser.getControl("Create ticket").click()
468        self.assertMatches('...ticket created...', self.browser.contents)
469        self.certificate.study_mode = 'special_pg_ft'
470        self.browser.getLink("Add current session payment ticket").click()
471        self.browser.getControl(name="form.p_category").value = ['schoolfee']
472        self.browser.getControl("Create ticket").click()
473        self.assertMatches('...This category of payments has been disabled...',
474                           self.browser.contents)
475        return
476
477class StudentUITests(StudentsFullSetup):
478    """Tests for customized student class views and pages
479    """
480
481    layer = FunctionalLayer
482
483    def setUp(self):
484        super(StudentUITests, self).setUp()
485
486        bedticket = BedTicket()
487        bedticket.booking_session = 2004
488        bedticket.bed_type = u'any bed type'
489        bedticket.bed = self.app['hostels']['hall-1']['hall-1_A_101_A']
490        bedticket.bed_coordinates = u'My bed coordinates'
491        self.student['accommodation'].addBedTicket(bedticket)
492
493    def test_maintenance_fee_payment(self):
494        self.certificate.study_mode = 'ug_ft'
495        self.student['studycourse'].entry_session = 2013
496        self.student.nationality = u'NG'
497        IWorkflowState(self.student).setState('cleared')
498        self.browser.open(self.login_path)
499        self.browser.getControl(name="form.login").value = self.student_id
500        self.browser.getControl(name="form.password").value = 'spwd'
501        self.browser.getControl("Login").click()
502        self.browser.open(self.student_path + '/payments')
503        self.browser.getLink("Add current session payment ticket").click()
504        self.browser.getControl(name="form.p_category").value = ['hostel_maintenance']
505        self.browser.getControl("Create ticket").click()
506        self.assertTrue('ticket created' in self.browser.contents)
507        value = self.student['payments'].keys()[0]
508        self.browser.getLink(value).click()
509        self.assertTrue('<span>My bed coordinates</span>' in self.browser.contents)
510        self.assertEqual(self.student['payments'][value].amount_auth, 876.0)
511        return
512
513    def test_student_schoolfee_payments(self):
514        configuration_1 = createObject('waeup.SessionConfiguration')
515        configuration_1.academic_session = 2016
516        self.app['configuration'].addSessionConfiguration(configuration_1)
517        self.certificate.study_mode = 'ug_ft'
518        self.student['studycourse'].entry_session = 2016
519        self.student['studycourse'].current_session = 2016
520        self.student['studycourse'].entry_mode = 'ug_ft'
521        self.student['studycourse'].certificate.school_fee_1 = 50250.0
522        self.app['configuration']['2016'].union_fee = 1250.0
523        self.app['configuration']['2016'].welfare_fee = 750.0
524        self.app['configuration']['2016'].id_card_fee = 350.0
525        self.student.nationality = u'NG'
526        # Login
527        IWorkflowState(self.student).setState('cleared')
528        self.browser.open(self.login_path)
529        self.browser.getControl(name="form.login").value = self.student_id
530        self.browser.getControl(name="form.password").value = 'spwd'
531        self.browser.getControl("Login").click()
532        # Test school fee payments
533        self.browser.open(self.student_path + '/payments')
534        self.browser.getLink("Add current session payment ticket").click()
535        self.browser.getControl(name="form.p_category").value = ['schoolfee_incl']
536        self.browser.getControl("Create ticket").click()
537        self.assertTrue('ticket created' in self.browser.contents)
538        value = self.student['payments'].keys()[0]
539        self.browser.getLink(value).click()
540        self.assertTrue('Amount Authorized' in self.browser.contents)
541        # 50250 + 1000 + 500 + 100 = 51850
542        self.assertEqual(self.student['payments'][value].amount_auth, 51850.0)
543        self.browser.open(self.browser.url + '/payment_slip.pdf')
544        self.assertEqual(self.browser.headers['Status'], '200 Ok')
545        self.assertEqual(self.browser.headers['Content-Type'], 'application/pdf')
546        path = os.path.join(samples_dir(), 'payment_slip.pdf')
547        open(path, 'wb').write(self.browser.contents)
548        print "Sample PDF payment_slip.pdf written to %s" % path
549        # Another school fee payment cannot be added
550        self.student['payments'][value].approve()
551        self.browser.open(self.student_path + '/payments')
552        self.browser.getLink("Add current session payment ticket").click()
553        self.browser.getControl(name="form.p_category").value = ['schoolfee']
554        self.browser.getControl("Create ticket").click()
555        self.assertTrue(
556            'You must choose a payment which includes additional fees'
557            in self.browser.contents)
558        return
559
560    def test_late_registration(self):
561        # Login
562        delta = timedelta(days=10)
563        self.app['configuration'][
564            '2004'].coursereg_deadline = datetime.now(pytz.utc) - delta
565        IWorkflowState(self.student).setState('school fee paid')
566        # Current session is 2004. Here we test course registration for
567        # returning students.
568        self.student['studycourse'].entry_session = 2003
569        self.browser.open(self.login_path)
570        self.browser.getControl(name="form.login").value = self.student_id
571        self.browser.getControl(name="form.password").value = 'spwd'
572        self.browser.getControl("Login").click()
573        self.browser.open(self.payments_path)
574        self.browser.open(self.payments_path + '/addop')
575        self.browser.getControl(name="form.p_category").value = ['late_registration']
576        self.browser.getControl("Create ticket").click()
577        self.assertMatches('...ticket created...',
578                           self.browser.contents)
579        self.browser.getLink("Study Course").click()
580        self.browser.getLink("Add course list").click()
581        self.assertMatches('...Add current level 100 (Year 1)...',
582                           self.browser.contents)
583        self.browser.getControl("Create course list now").click()
584        self.student['studycourse']['100']['COURSE1'].score = 67
585        self.browser.getLink("100").click()
586        # Course results can't be seen
587        self.assertFalse('<td>67</td>' in self.browser.contents)
588        self.browser.getLink("Edit course list").click()
589        self.assertFalse('<td>67</td>' in self.browser.contents)
590        self.browser.getControl("Register course list").click()
591        self.assertTrue('Course registration has ended. Please pay' in self.browser.contents)
592        self.student['payments'].values()[0].approve()
593        self.browser.getControl("Register course list").click()
594        self.assertTrue('Course list has been registered' in self.browser.contents)
595        self.assertEqual(self.student.state, 'courses registered')
596        # Reset student and check if fresh students are always allowed to
597        # register courses.
598        self.student['studycourse'].entry_session = 2004
599        del self.student['payments'][self.student['payments'].keys()[0]]
600        IWorkflowState(self.student).setState('school fee paid')
601        self.browser.open(self.studycourse_path + '/100/edit')
602        self.browser.getControl("Register course list").click()
603        self.assertTrue('Course list has been registered' in self.browser.contents)
604        return
605
606
607    def deactivated_test_student_course_registration(self):
608        # Add more courses
609        self.course2 = createObject('waeup.Course')
610        self.course2.code = 'COURSE2'
611        self.course2.semester = 2
612        self.course2.credits = 10
613        self.course2.passmark = 40
614        self.app['faculties']['fac1']['dep1'].courses.addCourse(
615            self.course2)
616        self.app['faculties']['fac1']['dep1'].certificates['CERT1'].addCertCourse(
617            self.course2, level=100)
618        self.course3 = createObject('waeup.Course')
619        self.course3.code = 'COURSE3'
620        self.course3.semester = 3
621        self.course3.credits = 10
622        self.course3.passmark = 40
623        self.app['faculties']['fac1']['dep1'].courses.addCourse(
624            self.course3)
625        self.app['faculties']['fac1']['dep1'].certificates['CERT1'].addCertCourse(
626            self.course3, level=100)
627
628        # Login as student
629        self.browser.open(self.login_path)
630        IWorkflowState(self.student).setState('school fee paid')
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 add the current study level
636        self.browser.getLink("Study Course").click()
637        self.browser.getLink("Add course list").click()
638        self.assertMatches('...Add current level 100 (Year 1)...',
639                           self.browser.contents)
640        self.browser.getControl("Create course list now").click()
641        # Student has not paid second instalment, therefore a level
642        # with two course ticket was created (semester 1 and combined)
643        self.assertEqual(self.student['studycourse']['100'].number_of_tickets, 2)
644        self.browser.getLink("100").click()
645        self.browser.getLink("Edit course list").click()
646        self.browser.getControl("Add course ticket").click()
647        # Student can't add second semester course
648        self.assertTrue('<option value="COURSE1">' in self.browser.contents)
649        self.assertTrue('<option value="COURSE3">' in self.browser.contents)
650        self.assertFalse('<option value="COURSE2">' in self.browser.contents)
651
652        # Let's remove level and see what happens after 2nd instalment payment
653        del(self.student['studycourse']['100'])
654        payment2 = createObject('waeup.StudentOnlinePayment')
655        payment2.p_category = u'schoolfee_2'
656        payment2.p_session = self.student.current_session
657        self.student['payments']['anykey'] = payment2
658        self.browser.open(self.studycourse_path)
659        self.browser.getLink("Add course list").click()
660        self.browser.getControl("Create course list now").click()
661        # Still only 2 tickets have been created since payment ticket
662        # was not paid
663        self.assertEqual(self.student['studycourse']['100'].number_of_tickets, 2)
664        payment2.p_state = u'paid'
665        del(self.student['studycourse']['100'])
666        self.browser.open(self.studycourse_path)
667        self.browser.getLink("Add course list").click()
668        self.browser.getControl("Create course list now").click()
669        # Now 2nd semester course has been added
670        self.assertEqual(self.student['studycourse']['100'].number_of_tickets, 3)
671        # Student can add second semester course
672        self.browser.getLink("100").click()
673        self.browser.getLink("Edit course list").click()
674        self.browser.getControl("Add course ticket").click()
675        self.assertTrue('<option value="COURSE1">' in self.browser.contents)
676        self.assertTrue('<option value="COURSE2">' in self.browser.contents)
677        self.assertTrue('<option value="COURSE3">' in self.browser.contents)
678        return
679
680    def test_set_matric_number(self):
681        #payment = createObject('waeup.StudentOnlinePayment')
682        #payment.p_category = u'concessional'
683        #payment.p_id = u'anyid'
684        #payment.p_state = u'paid'
685        #self.student['payments']['anykey'] = payment
686        # Login as student
687        self.browser.open(self.login_path)
688        IWorkflowState(self.student).setState('school fee paid')
689        self.browser.open(self.login_path)
690        self.browser.getControl(name="form.login").value = self.student_id
691        self.browser.getControl(name="form.password").value = 'spwd'
692        self.browser.getControl("Login").click()
693        self.assertRaises(
694            LinkNotFoundError,
695            self.browser.getLink, 'Get Matriculation Number')
696        self.student.matric_number = None
697        site = grok.getSite()
698        site['configuration'].next_matric_integer = 1
699        self.student['studycourse'].certificate.study_mode = 'ug_pt'
700        self.browser.open(self.student_path)
701        self.assertRaises(
702            LinkNotFoundError,
703            self.browser.getLink, 'Download matriculation number slip')
704        self.browser.getLink("Get Matriculation Number").click()
705        self.assertTrue('Matriculation number PTP/fac1/dep1/04/00001 assigned.'
706            in self.browser.contents)
707        self.assertEqual(self.student.matric_number, 'PTP/fac1/dep1/04/00001')
708        self.assertRaises(
709            LinkNotFoundError,
710            self.browser.getLink, 'Get Matriculation Number')
711        # Setting matric number is logged.
712        logfile = os.path.join(
713            self.app['datacenter'].storage, 'logs', 'students.log')
714        logcontent = open(logfile).read()
715        self.assertTrue('E1000000 - waeup.aaue.students.browser.StudentGetMatricNumberPage - '
716                        'E1000000 - PTP/fac1/dep1/04/00001 assigned' in logcontent)
717        # Matric Number Slip can be downloaded
718        self.browser.getLink("Download matriculation number slip").click()
719        self.assertEqual(self.browser.headers['Status'], '200 Ok')
720        self.assertEqual(self.browser.headers['Content-Type'], 'application/pdf')
721        path = os.path.join(samples_dir(), 'matric_number_slip.pdf')
722        open(path, 'wb').write(self.browser.contents)
723        print "Sample PDF matric_number_slip.pdf written to %s" % path
724        return
725
726    def test_personal_data_slip(self):
727        # Login as student
728        self.browser.open(self.login_path)
729        IWorkflowState(self.student).setState('school fee paid')
730        self.browser.open(self.login_path)
731        self.browser.getControl(name="form.login").value = self.student_id
732        self.browser.getControl(name="form.password").value = 'spwd'
733        self.browser.getControl("Login").click()
734        self.browser.getLink("Personal Data").click()
735        self.assertRaises(
736            LinkNotFoundError,
737            self.browser.getLink, 'Download personal data slip')
738        self.student.father_name = u'Rudolf'
739        self.browser.open(self.personal_path)
740        self.browser.getLink("Download personal data slip").click()
741        self.assertEqual(self.browser.headers['Status'], '200 Ok')
742        self.assertEqual(self.browser.headers['Content-Type'], 'application/pdf')
743        path = os.path.join(samples_dir(), 'personal_data_slip.pdf')
744        open(path, 'wb').write(self.browser.contents)
745        print "Sample PDF personal_data_slip.pdf written to %s" % path
746        return
747
748    def test_student_course_registration(self):
749        IWorkflowState(self.student).setState('school fee paid')
750        self.browser.open(self.login_path)
751        self.browser.getControl(name="form.login").value = self.student_id
752        self.browser.getControl(name="form.password").value = 'spwd'
753        self.browser.getControl("Login").click()
754        # Now students can add the current study level
755        self.browser.getLink("Study Course").click()
756        self.browser.getLink("Add course list").click()
757        self.assertMatches('...Add current level 100 (Year 1)...',
758                           self.browser.contents)
759        self.browser.getControl("Create course list now").click()
760        # Students can't open the customized pdf course registration slip
761        self.browser.open(
762            self.student_path + '/studycourse/100/course_registration_slip.pdf')
763        self.assertTrue('Forbidden' in self.browser.contents)
764        # They can open slips from the previous session ...
765        self.student['studycourse'].current_level = 200
766        self.browser.open(self.student_path + '/studycourse/100')
767        self.browser.getLink("Download course registration slip").click()
768        self.assertEqual(self.browser.headers['Status'], '200 Ok')
769        self.assertEqual(self.browser.headers['Content-Type'], 'application/pdf')
770        # or if they have registered their course list
771        self.student['studycourse'].current_level = 200
772        IWorkflowState(self.student).setState('courses registered')
773        self.browser.open(self.student_path + '/studycourse/100')
774        self.browser.getLink("Download course registration slip").click()
775        self.assertEqual(self.browser.headers['Status'], '200 Ok')
776        self.assertEqual(self.browser.headers['Content-Type'], 'application/pdf')
777        path = os.path.join(samples_dir(), 'ft_course_registration_slip.pdf')
778        open(path, 'wb').write(self.browser.contents)
779        print "Sample PDF ft_course_registration_slip.pdf written to %s" % path
780
781        self.certificate.study_mode = 'ug_pt'
782        self.browser.open(self.student_path + '/studycourse/100')
783        self.browser.getLink("Download course registration slip").click()
784        self.assertEqual(self.browser.headers['Status'], '200 Ok')
785        self.assertEqual(self.browser.headers['Content-Type'], 'application/pdf')
786        path = os.path.join(samples_dir(), 'pt_course_registration_slip.pdf')
787        open(path, 'wb').write(self.browser.contents)
788        print "Sample PDF pt_course_registration_slip.pdf written to %s" % path
789
790        self.certificate.study_mode = 'special_pg_ft'
791        self.student.matric_number = u'AAU/SPS/FLW/LAW/15/PHD/09504'
792        self.browser.open(self.student_path + '/studycourse/100')
793        self.browser.getLink("Download course registration slip").click()
794        self.assertEqual(self.browser.headers['Status'], '200 Ok')
795        self.assertEqual(self.browser.headers['Content-Type'], 'application/pdf')
796        path = os.path.join(samples_dir(), 'pg_course_registration_slip.pdf')
797        open(path, 'wb').write(self.browser.contents)
798        print "Sample PDF pg_course_registration_slip.pdf written to %s" % path
799
800    def test_student_2nd_semester_course_registration(self):
801        IWorkflowState(self.student).setState('school fee paid')
802        self.student['studycourse'].entry_session = 2015
803        self.course.semester = 2
804        self.browser.open(self.login_path)
805        self.browser.getControl(name="form.login").value = self.student_id
806        self.browser.getControl(name="form.password").value = 'spwd'
807        self.browser.getControl("Login").click()
808        self.browser.getLink("Study Course").click()
809        self.browser.getLink("Add course list").click()
810        self.browser.getControl("Create course list now").click()
811        self.assertFalse('COURSE1' in self.browser.contents)
812        # 2nd semester tickets can't be added manually
813        self.browser.getLink("Edit course list").click()
814        self.browser.getLink("here").click()
815        self.browser.getControl(name="form.course").value = ['COURSE1']
816        self.browser.getControl("Add course ticket").click()
817        self.assertTrue(
818            'Course COURSE1 cannot be registered. '
819            'You have to pay for the 2nd semester first.'
820            in self.browser.contents)
821        # 2nd instalment has to be paid first
822        self.certificate.school_fee_3 = 678.0
823        self.browser.open(self.payments_path + '/addop')
824        self.browser.getControl(name="form.p_category").value = ['schoolfee_2']
825        self.browser.getControl("Create ticket").click()
826        self.student['payments'].values()[0].approve()
827        self.browser.open(self.studycourse_path + '/100/ctadd')
828        self.browser.getControl(name="form.course").value = ['COURSE1']
829        self.browser.getControl("Add course ticket").click()
830        self.assertTrue('Successfully added COURSE1' in self.browser.contents)
831        return
832
833    def test_student_clearance(self):
834        # Student cant login if their password is not set
835        IWorkflowInfo(self.student).fireTransition('admit')
836        self.browser.open(self.login_path)
837        self.browser.getControl(name="form.login").value = self.student_id
838        self.browser.getControl(name="form.password").value = 'spwd'
839        self.browser.getControl("Login").click()
840        self.assertMatches(
841            '...You logged in...', self.browser.contents)
842        # Admitted student can upload a passport picture
843        self.browser.open(self.student_path + '/change_portrait')
844        ctrl = self.browser.getControl(name='passportuploadedit')
845        file_obj = open(SAMPLE_IMAGE, 'rb')
846        file_ctrl = ctrl.mech_control
847        file_ctrl.add_file(file_obj, filename='my_photo.jpg')
848        self.browser.getControl(
849            name='upload_passportuploadedit').click()
850        self.assertTrue(
851            'src="http://localhost/app/students/E1000000/passport.jpg"'
852            in self.browser.contents)
853        # Student is redirected to the personal data form because
854        # personal data form is not properly filled.
855        self.browser.open(self.student_path + '/start_clearance')
856        self.assertMatches('...Personal data form is not properly filled...',
857                           self.browser.contents)
858        self.assertEqual(self.browser.url, self.student_path + '/edit_personal')
859        self.student.father_name = u'Rudolf'
860        self.browser.open(self.student_path + '/start_clearance')
861        self.assertMatches(
862            '...<h1 class="kofa-content-label">Start clearance</h1>...',
863            self.browser.contents)
864
865    def test_student_accommodation(self):
866        del self.student['accommodation']['2004']
867        self.student['studycourse'].certificate.study_mode = 'dp_ft'
868        # All beds can be assigned
869        bed1 = self.app['hostels']['hall-1']['hall-1_A_101_A']
870        bed1.bed_type = u'regular_male_all'
871        bed2 = self.app['hostels']['hall-1']['hall-1_A_101_B']
872        bed2.bed_type = u'regular_female_all'
873        notify(grok.ObjectModifiedEvent(bed1))
874        notify(grok.ObjectModifiedEvent(bed2))
875        # Login
876        self.browser.open(self.login_path)
877        self.browser.getControl(name="form.login").value = self.student_id
878        self.browser.getControl(name="form.password").value = 'spwd'
879        self.browser.getControl("Login").click()
880        # Students can book accommodation without AC ...
881        self.browser.open(self.acco_path)
882        IWorkflowInfo(self.student).fireTransition('admit')
883        self.browser.getControl("Book accommodation").click()
884        self.assertTrue(
885            'You are not eligible to book accommodation.'
886            in self.browser.contents)
887        self.student['studycourse'].certificate.study_mode = 'ug_ft'
888        self.app['hostels'].accommodation_states = [PAID]
889        self.browser.getControl("Book accommodation").click()
890        self.assertTrue(
891            'You are in the wrong registration state.'
892            in self.browser.contents)
893        IWorkflowState(self.student).setState(PAID)
894        self.browser.getControl("Book accommodation").click()
895        self.assertFalse('Activation Code:' in self.browser.contents)
896        self.browser.getControl("Create bed ticket").click()
897        # Bed is randomly selected but, since there is only
898        # one bed for this student, we know that
899        self.assertEqual(self.student['accommodation']['2004'].bed_coordinates,
900            'Hall 1, Block A, Room 101, Bed A (regular_male_all)')
901        # Only the hall name is displayed
902        self.assertEqual(self.student[
903            'accommodation']['2004'].display_coordinates,
904            'Hall 1')
905        self.assertFalse('Hall 1, Block A, Room 101, Bed A'
906            in self.browser.contents)
907        self.assertTrue('<td>Hall 1</td>'
908            in self.browser.contents)
909        return
910
911    def test_handle_courses_by_lecturer(self):
912        self.app['users'].addUser('mrslecturer', 'mrslecturersecret')
913        self.app['users']['mrslecturer'].email = 'mrslecturer@foo.ng'
914        self.app['users']['mrslecturer'].title = u'Mercedes Benz'
915        # Add course ticket
916        studylevel = createObject(u'waeup.StudentStudyLevel')
917        studylevel.level = 100
918        studylevel.level_session = 2004
919        self.student['studycourse'].addStudentStudyLevel(
920            self.certificate, studylevel)
921        # Assign local Lecturer role for a certificate.
922        course = self.app['faculties']['fac1']['dep1'].courses['COURSE1']
923        prmlocal = IPrincipalRoleManager(course)
924        prmlocal.assignRoleToPrincipal('waeup.local.Lecturer', 'mrslecturer')
925        notify(LocalRoleSetEvent(
926            course, 'waeup.local.Lecturer', 'mrslecturer', granted=True))
927        # Login as lecturer.
928        self.browser.open(self.login_path)
929        self.browser.getControl(name="form.login").value = 'mrslecturer'
930        self.browser.getControl(name="form.password").value = 'mrslecturersecret'
931        self.browser.getControl("Login").click()
932        self.browser.getLink("My Courses").click()
933        self.browser.getLink("COURSE1").click()
934        # Course results can be batch edited via the edit_courses view.
935        self.app['faculties']['fac1']['dep1'].score_editing_disabled = False
936        self.app['configuration'].current_academic_session = 2004
937        IWorkflowState(self.student).setState('courses validated')
938        self.browser.open(
939            "http://localhost/app/faculties/fac1/dep1/courses/COURSE1/edit_scores")
940        self.assertTrue(
941            'input type="text" name="scores:list"'
942            in self.browser.contents)
943        self.browser.getControl(name="scores:list", index=0).value = '55'
944        self.browser.getControl(name="cas:list", index=0).value = '22'
945        self.browser.getControl("Update scores from").click()
946        # New score and ca has been set.
947        self.assertEqual(
948            self.student['studycourse']['100']['COURSE1'].score, 55)
949        self.assertEqual(
950            self.student['studycourse']['100']['COURSE1'].ca, 22)
951        # Score editing has been logged.
952        logfile = os.path.join(
953            self.app['datacenter'].storage, 'logs', 'students.log')
954        logcontent = open(logfile).read()
955        self.assertTrue('mrslecturer - waeup.aaue.students.browser.CustomEditScoresPage - '
956                        'E1000000 100/COURSE1 score updated (55)' in logcontent)
957        self.assertTrue('mrslecturer - waeup.aaue.students.browser.CustomEditScoresPage - '
958                        'E1000000 100/COURSE1 ca updated (22)' in logcontent)
959        # Non-integer scores won't be accepted.
960        self.browser.open(
961            "http://localhost/app/faculties/fac1/dep1/courses/COURSE1/edit_scores")
962        self.assertTrue('value="55" />' in self.browser.contents)
963        self.browser.getControl(name="scores:list", index=0).value = 'abc'
964        self.browser.getControl("Update scores").click()
965        self.assertTrue('Error: Score(s) and CA(s) of TESTER, Anna have not be updated.'
966            in self.browser.contents)
967        # Scores can be removed.
968        self.browser.open(
969            "http://localhost/app/faculties/fac1/dep1/courses/COURSE1/edit_scores")
970        self.browser.getControl(name="scores:list", index=0).value = ''
971        self.browser.getControl("Update scores").click()
972        self.assertEqual(
973            self.student['studycourse']['100']['COURSE1'].score, None)
974        logcontent = open(logfile).read()
975        self.assertTrue('mrslecturer - waeup.aaue.students.browser.CustomEditScoresPage - '
976                        'E1000000 100/COURSE1 score updated (None)' in logcontent)
977
978
979    def test_student_view_transcript(self):
980        # Student cant login if their password is not set
981        IWorkflowInfo(self.student).fireTransition('admit')
982        self.browser.open(self.login_path)
983        self.browser.getControl(name="form.login").value = self.student_id
984        self.browser.getControl(name="form.password").value = 'spwd'
985        self.browser.getControl("Login").click()
986        self.assertMatches(
987            '...You logged in...', self.browser.contents)
988        # Students can view the transcript
989        self.browser.open(self.studycourse_path)
990        self.browser.getLink("Transcript").click()
991        self.browser.getLink("Academic Transcript").click()
992        self.assertEqual(self.browser.headers['Status'], '200 Ok')
993        self.assertEqual(self.browser.headers['Content-Type'], 'application/pdf')
Note: See TracBrowser for help on using the repository browser.