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

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

Fix test.

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