## $Id: test_browser.py 17885 2024-08-11 19:29:13Z henrik $
##
## Copyright (C) 2011 Uli Fouquet & Henrik Bettermann
## This program is free software; you can redistribute it and/or modify
## it under the terms of the GNU General Public License as published by
## the Free Software Foundation; either version 2 of the License, or
## (at your option) any later version.
##
## This program is distributed in the hope that it will be useful,
## but WITHOUT ANY WARRANTY; without even the implied warranty of
## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
## GNU General Public License for more details.
##
## You should have received a copy of the GNU General Public License
## along with this program; if not, write to the Free Software
## Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
##
import os
import shutil
import tempfile
import pytz
from time import time
from datetime import datetime, timedelta, date
from StringIO import StringIO
from hurry.workflow.interfaces import IWorkflowState, IWorkflowInfo
from zope.securitypolicy.interfaces import IPrincipalRoleManager
from zope.security.interfaces import Unauthorized
from zope.component.hooks import setSite, clearSite
from zope.component import getUtility, createObject
from zope.interface import verify
from zope.event import notify
from waeup.kofa.authentication import LocalRoleSetEvent
from waeup.kofa.app import University
from waeup.kofa.university.faculty import Faculty
from waeup.kofa.university.department import Department
from waeup.kofa.students.tests.test_browser import StudentsFullSetup
from waeup.kofa.students.accommodation import BedTicket
from waeup.kofa.hostels.hostel import Hostel, Bed, NOT_OCCUPIED
from waeup.kofa.testing import FunctionalTestCase
from waeup.kofa.browser.tests.test_pdf import samples_dir
from waeup.kofa.interfaces import (
IExtFileStore, IFileStoreNameChooser)
from waeup.kofa.students.interfaces import IStudentsUtils
from waeup.kofa.tests.test_authentication import SECRET
from waeup.uniben.testing import FunctionalLayer
SAMPLE_FPM = os.path.join(os.path.dirname(__file__), 'sample.fpm')
SAMPLE_PASSPORT = os.path.join(os.path.dirname(__file__), 'test_image.jpg')
class OfficerUITests(StudentsFullSetup):
# Tests for Student class views and pages
layer = FunctionalLayer
def test_jhl_idcard_officer(self):
# Create library officer
self.app['users'].addUser('mrlibrary', SECRET)
self.app['users']['mrlibrary'].email = 'library@foo.ng'
self.app['users']['mrlibrary'].title = 'Carlo Pitter'
prmglobal = IPrincipalRoleManager(self.app)
prmglobal.assignRoleToPrincipal(
'waeup.LibraryClearanceOfficer', 'mrlibrary')
prmglobal.assignRoleToPrincipal(
'waeup.StudentsOfficer', 'mrlibrary')
self.browser.open(self.login_path)
self.browser.getControl(name="form.login").value = 'mrlibrary'
self.browser.getControl(name="form.password").value = SECRET
self.browser.getControl("Login").click()
self.assertMatches('...You logged in...', self.browser.contents)
self.browser.open(self.student_path)
self.assertFalse('JHL' in self.browser.contents)
self.browser.getLink("Switch library access").click()
self.assertTrue('Library access enabled' in self.browser.contents)
self.assertTrue('JHL' in self.browser.contents)
self.browser.getLink("Download JHL Id Card").click()
self.assertEqual(self.browser.headers['Status'], '200 Ok')
self.assertEqual(self.browser.headers['Content-Type'], 'application/pdf')
path = os.path.join(samples_dir(), 'jhl_idcard_officer.pdf')
open(path, 'wb').write(self.browser.contents)
print "Sample PDF jhl_idcard_officer.pdf written to %s" % path
class StudentUITests(StudentsFullSetup):
"""Tests for customized student class views and pages
"""
layer = FunctionalLayer
def setUp(self):
super(StudentUITests, self).setUp()
def test_next_session_allowed(self):
# Let's see if next_session_allowed works as expected
# A, ug_ft, 100
IWorkflowState(self.student).setState('returning')
self.assertTrue(self.student['studycourse'].next_session_allowed)
# Uniben special PG programmes have the same workflow
# as UG students
self.certificate.study_mode = 'special_pg_pt'
self.assertTrue(self.student['studycourse'].next_session_allowed)
IWorkflowState(self.student).setState('school fee paid')
self.assertFalse(self.student['studycourse'].next_session_allowed)
# Now we convert the certificate into a 'regular
# postgraduate certificate ...
self.certificate.study_mode = 'pg_ft'
# ... and voila next session registration is allowed
self.assertTrue(self.student['studycourse'].next_session_allowed)
def test_manage_access(self):
self.browser.addHeader('Authorization', 'Basic mgr:mgrpw')
# The student created in the base package is a ug student
self.browser.open(self.manage_clearance_path)
self.assertMatches('...First Sitting Record...',
self.browser.contents)
# There is no pg field in the clearance form
self.assertFalse('Second Higher Education Record'
in self.browser.contents)
# Now we change the study mode ...
self.certificate.study_mode = 'pg_ft'
self.browser.open(self.clearance_path)
# ... and additional pg clearance fields appears
self.assertMatches('...Second Higher Education Record...',
self.browser.contents)
# But also fields from the ug form are displayed
self.assertMatches('...First Sitting Record...',
self.browser.contents)
# The same holds for Uniben's special pg students
self.certificate.study_mode = 'special_pg_pt'
self.browser.open(self.clearance_path)
self.assertMatches('...Second Higher Education Record...',
self.browser.contents)
self.assertMatches('...First Sitting Record...',
self.browser.contents)
# We want to see the signature fields.
IWorkflowState(self.student).setState('returning')
self.browser.open(self.student_path + '/clearance_slip.pdf')
self.assertEqual(self.browser.headers['Status'], '200 Ok')
self.assertEqual(self.browser.headers['Content-Type'],
'application/pdf')
path = os.path.join(samples_dir(), 'clearance_slip.pdf')
open(path, 'wb').write(self.browser.contents)
print "Sample PDF clearance_slip.pdf written to %s" % path
def test_student_access(self):
# Students can edit clearance data
IWorkflowState(self.student).setState('clearance started')
self.student.nationality = u'NG'
self.student['studycourse'].entry_mode = 'ug_ft'
file_store = getUtility(IExtFileStore)
self.browser.open(self.login_path)
self.browser.getControl(name="form.login").value = self.student_id
self.browser.getControl(name="form.password").value = 'spwd'
self.browser.getControl("Login").click()
self.browser.open(self.edit_clearance_path)
# UG students can't edit date_of_birth, nationality and lga
self.assertFalse('form.date_of_birth' in self.browser.contents)
self.assertFalse('form.nationality' in self.browser.contents)
self.assertFalse('form.lga' in self.browser.contents)
# Clearance can only be requested if all required documents
# have been uploaded.
self.browser.getControl("Save and request clearance").click()
self.assertTrue('No red background passport picture uploaded'
in self.browser.contents)
passport = 'My passport picture'
file_id = IFileStoreNameChooser(self.student).chooseName(
attr="passport.jpg")
image = open(SAMPLE_PASSPORT, 'rb')
file_store.createFile(file_id, image)
self.browser.open(self.edit_clearance_path)
self.browser.getControl("Save and request clearance").click()
self.assertTrue('No birth certificate uploaded'
in self.browser.contents)
birth_certificate = 'My birth certificate'
file_id = IFileStoreNameChooser(self.student).chooseName(
attr="birth_certificate.jpg")
file_store.createFile(file_id, StringIO(birth_certificate))
self.browser.open(self.edit_clearance_path)
self.browser.getControl("Save and request clearance").click()
self.assertTrue('No guarantor/referee letter uploaded'
in self.browser.contents)
ref_let = 'My ref let'
file_id = IFileStoreNameChooser(self.student).chooseName(
attr="ref_let.jpg")
file_store.createFile(file_id, StringIO(ref_let))
self.browser.open(self.edit_clearance_path)
self.browser.getControl("Save and request clearance").click()
self.assertTrue('No acceptance letter uploaded'
in self.browser.contents)
acc_let = 'My acc let'
file_id = IFileStoreNameChooser(self.student).chooseName(
attr="acc_let.jpg")
file_store.createFile(file_id, StringIO(acc_let))
self.browser.open(self.edit_clearance_path)
self.browser.getControl("Save and request clearance").click()
self.assertTrue('No first sitting result uploaded'
in self.browser.contents)
fst_sit_scan = 'My first sitting result'
file_id = IFileStoreNameChooser(self.student).chooseName(
attr="fst_sit_scan.jpg")
file_store.createFile(file_id, StringIO(fst_sit_scan))
self.browser.open(self.edit_clearance_path)
self.browser.getControl("Save and request clearance").click()
self.assertTrue('No affidavit of non-membership of secret cults uploaded'
in self.browser.contents)
secr_cults = 'My non-membership scan'
file_id = IFileStoreNameChooser(self.student).chooseName(
attr="secr_cults.jpg")
file_store.createFile(file_id, StringIO(secr_cults))
self.browser.open(self.edit_clearance_path)
self.browser.getControl("Save and request clearance").click()
self.assertTrue('No O level results scratch card uploaded'
in self.browser.contents)
olevel_sc = 'My O level results scratch card'
file_id = IFileStoreNameChooser(self.student).chooseName(
attr="olevel_sc.jpg")
file_store.createFile(file_id, StringIO(olevel_sc))
# Clearance invitation letter is not yet available
self.browser.open(self.clearance_path)
self.assertFalse('invitation slip' in self.browser.contents)
self.browser.open(self.student_path + '/clearance_invitation_slip.pdf')
self.assertTrue('Forbidden' in self.browser.contents)
self.browser.open(self.edit_clearance_path)
self.browser.getControl("Save and request clearance").click()
self.assertTrue('Clearance has been requested'
in self.browser.contents)
# Now student can export physical_clearance_slip
self.app['configuration'].name = u'University of Benin'
self.student.physical_clearance_date = u'January 5th, 2015'
self.browser.getLink("Clearance Data").click()
self.browser.getLink("Download clearance invitation slip").click()
self.assertEqual(self.browser.headers['Status'], '200 Ok')
self.assertEqual(self.browser.headers['Content-Type'], 'application/pdf')
path = os.path.join(samples_dir(), 'clearance_invitation_slip.pdf')
open(path, 'wb').write(self.browser.contents)
print "Sample PDF clearance_invitation_slip.pdf written to %s" % path
def test_medical_examination_slip(self):
# Student can export medical_examination_slip
self.app['configuration']['2004'].medical_clearance_fee = 1000.0
self.app['configuration'].name = u'University of Benin'
IWorkflowState(self.student).setState('cleared')
self.student.perm_address = u'My Address in Nigeria'
self.student.physical_clearance_date = u'January 5th, 2015'
self.browser.open(self.login_path)
self.browser.getControl(name="form.login").value = self.student_id
self.browser.getControl(name="form.password").value = 'spwd'
self.browser.getControl("Login").click()
self.browser.open(self.clearance_path)
self.browser.getLink("Download medical examination slip").click()
self.assertTrue('Please pay medical clearance fee first' in
self.browser.contents)
self.browser.open(self.payments_path)
self.browser.getLink("Add current session payment ticket").click()
self.browser.getControl(name="form.p_category").value = ['medical_clearance']
self.browser.getControl("Create ticket").click()
p_ticket = self.student['payments'].values()[0]
p_ticket.approveStudentPayment()
self.browser.open(self.clearance_path)
self.browser.getLink("Download medical examination slip").click()
self.assertEqual(self.browser.headers['Status'], '200 Ok')
self.assertEqual(self.browser.headers['Content-Type'], 'application/pdf')
path = os.path.join(samples_dir(), 'medical_examination_slip.pdf')
open(path, 'wb').write(self.browser.contents)
print "Sample PDF medical_examination_slip.pdf written to %s" % path
# Students can open the personal edit page and see the parent_email field.
self.browser.open(self.student_path + '/edit_personal')
self.assertTrue('parent_email' in self.browser.contents)
def test_examination_schedule_slip(self):
self.student.flash_notice = u'My Examination Date'
self.browser.open(self.login_path)
self.browser.getControl(name="form.login").value = self.student_id
self.browser.getControl(name="form.password").value = 'spwd'
self.browser.getControl("Login").click()
self.browser.open(self.student_path)
self.browser.getLink("Download examination schedule slip").click()
self.assertEqual(self.browser.headers['Status'], '200 Ok')
self.assertEqual(self.browser.headers['Content-Type'], 'application/pdf')
path = os.path.join(samples_dir(), 'examination_schedule_slip.pdf')
open(path, 'wb').write(self.browser.contents)
print "Sample PDF examination_schedule_slip.pdf written to %s" % path
# If flash_notive does not contain exam' the button does not show up.
self.student.flash_notice = u'anything'
self.browser.open(self.student_path)
self.assertFalse('examination schedule slip' in self.browser.contents)
def test_jhl_idcard(self):
IWorkflowState(self.student).setState('returning')
self.browser.open(self.login_path)
self.browser.getControl(name="form.login").value = self.student_id
self.browser.getControl(name="form.password").value = 'spwd'
self.browser.getControl("Login").click()
self.assertFalse('JHL' in self.browser.contents)
self.student.library = True
self.browser.open(self.student_path)
self.assertTrue('JHL' in self.browser.contents)
self.browser.getLink("Download JHL Id Card").click()
self.assertEqual(self.browser.headers['Status'], '200 Ok')
self.assertEqual(self.browser.headers['Content-Type'], 'application/pdf')
path = os.path.join(samples_dir(), 'jhl_idcard_student.pdf')
open(path, 'wb').write(self.browser.contents)
print "Sample PDF jhl_idcard_student.pdf written to %s" % path
self.assertTrue(self.student.library)
IWorkflowInfo(self.student).fireTransition('pay_school_fee')
self.assertFalse(self.student.library)
def test_jupeb_result_slip(self):
self.student.flash_notice = u'My JUPEB results'
self.browser.open(self.login_path)
self.browser.getControl(name="form.login").value = self.student_id
self.browser.getControl(name="form.password").value = 'spwd'
self.browser.getControl("Login").click()
self.assertFalse('JUPEB result slip' in self.browser.contents)
# Create JUPEB faculty
cert = createObject('waeup.Certificate')
cert.code = u'xyz'
cert.study_mode = 'found'
self.app['faculties']['JUPEB123'] = Faculty(code=u'JUPEB123')
self.app['faculties']['JUPEB123']['dep1'] = Department(code=u'dep1')
self.app['faculties']['JUPEB123']['dep1'].certificates.addCertificate(cert)
self.student['studycourse'].certificate = cert
self.browser.open(self.student_path)
self.browser.getLink("Download JUPEB result slip").click()
self.assertEqual(self.browser.headers['Status'], '200 Ok')
self.assertEqual(self.browser.headers['Content-Type'], 'application/pdf')
path = os.path.join(samples_dir(), 'jupeb_result_slip.pdf')
open(path, 'wb').write(self.browser.contents)
print "Sample PDF jupeb_result_slip.pdf written to %s" % path
self.student.flash_notice = u''
self.browser.open(self.student_path)
self.assertFalse('JUPEB result slip' in self.browser.contents)
def test_manage_payments(self):
# Add missing configuration data
self.app['configuration']['2004'].gown_fee = 150.0
self.app['configuration']['2004'].transfer_fee = 90.0
#self.app['configuration']['2004'].clearance_fee = 120.0
self.app['configuration']['2004'].booking_fee = 150.0
self.app['configuration']['2004'].maint_fee = 180.0
# Managers can add online payment tickets
self.browser.addHeader('Authorization', 'Basic mgr:mgrpw')
self.browser.open(self.payments_path)
self.browser.getLink("Add current session payment ticket").click()
self.browser.getControl(name="form.p_category").value = ['schoolfee']
self.browser.getControl("Create ticket").click()
self.assertMatches('...Amount could not be determined...',
self.browser.contents)
IWorkflowState(self.student).setState('cleared')
self.student.nationality = u'NG'
self.browser.open(self.payments_path + '/addop')
self.browser.getControl(name="form.p_category").value = ['schoolfee']
self.browser.getControl("Create ticket").click()
self.assertMatches('...ticket created...',
self.browser.contents)
self.assertMatches('...Amount Authorized...',
self.browser.contents)
# Managers can open payment slip because we did not proceed to
# any payment gateway
self.assertFalse('Download payment slip' in self.browser.contents)
# Set ticket paid
ticket = self.student['payments'].items()[0][1]
ticket.p_state = 'paid'
self.browser.open(self.payments_path + '/addop')
self.browser.getControl(name="form.p_category").value = ['schoolfee']
self.browser.getControl("Create ticket").click()
self.assertMatches('...This type of payment has already been made...',
self.browser.contents)
# Remove all payments so that we can add a school fee payment again
keys = [i for i in self.student['payments'].keys()]
for payment in keys:
del self.student['payments'][payment]
self.browser.open(self.payments_path + '/addop')
self.browser.getControl(name="form.p_category").value = ['schoolfee']
self.browser.getControl("Create ticket").click()
self.assertMatches('...ticket created...',
self.browser.contents)
schoolfee_ticket = self.student['payments'].values()[0]
self.browser.open(self.payments_path + '/addop')
self.browser.getControl(name="form.p_category").value = ['gown']
self.browser.getControl("Create ticket").click()
self.assertMatches('...ticket created...',
self.browser.contents)
self.browser.open(self.payments_path + '/addop')
self.browser.getControl(name="form.p_category").value = ['clearance']
self.browser.getControl("Create ticket").click()
self.assertMatches('...ticket created...',
self.browser.contents)
self.assertTrue('60000.0' in self.browser.contents)
self.browser.open(self.payments_path + '/addop')
self.browser.getControl(name="form.p_category").value = ['schoolfee']
self.browser.getControl("Create ticket").click()
self.assertMatches('...ticket created...',
self.browser.contents)
# In state returning we can add a new school fee ticket since
# p_session and p_level is different
IWorkflowState(self.student).setState('returning')
self.browser.open(self.payments_path + '/addop')
self.browser.getControl(name="form.p_category").value = ['schoolfee']
self.browser.getControl("Create ticket").click()
# Uups, we forgot to add a session configuration for next session
self.assertMatches('...Session configuration object is not...',
self.browser.contents)
configuration = createObject('waeup.SessionConfiguration')
configuration.academic_session = 2005
self.app['configuration'].addSessionConfiguration(configuration)
self.browser.open(self.payments_path + '/addop')
self.browser.getControl(name="form.p_category").value = ['schoolfee']
self.browser.getControl("Create ticket").click()
#self.assertMatches('...You have not yet paid your current/active session...',
# self.browser.contents)
## Ok, let's pay the first schoolfee ticket.
#schoolfee_ticket.approve()
#self.browser.open(self.payments_path + '/addop')
#self.browser.getControl(name="form.p_category").value = ['schoolfee']
#self.browser.getControl("Create ticket").click()
self.assertMatches('...ticket created...',
self.browser.contents)
# In state admitted school fee can't be determined
IWorkflowState(self.student).setState('admitted')
self.browser.open(self.payments_path + '/addop')
self.browser.getControl(name="form.p_category").value = ['schoolfee']
self.browser.getControl("Create ticket").click()
self.assertMatches('...Amount could not be determined...',
self.browser.contents)
# If the session configuration doesn't exist an error message will
# be shown. No other requirement is being checked.
del self.app['configuration']['2004']
self.browser.open(self.payments_path)
self.browser.getLink("Add current session payment ticket").click()
self.browser.getControl("Create ticket").click()
self.assertMatches('...Session configuration object is not...',
self.browser.contents)
def test_student_course_registration(self):
# Uniben students see grade instead of score on all level pages
# and on course ticket page.
IWorkflowState(self.student).setState('school fee paid')
self.browser.open(self.login_path)
self.browser.getControl(name="form.login").value = self.student_id
self.browser.getControl(name="form.password").value = 'spwd'
self.browser.getControl("Login").click()
# Now students can add the current study level
self.browser.getLink("Study Course").click()
self.browser.getLink("Add course list").click()
self.assertMatches('...Add current level 100 (Year 1)...',
self.browser.contents)
self.browser.getControl("Create course list now").click()
# A level with one course ticket was created
self.assertEqual(self.student['studycourse']['100'].number_of_tickets, 1)
self.student['studycourse']['100']['COURSE1'].score = 55
self.browser.getLink("100").click()
# GPA has been properly calculated
self.assertEqual(self.student['studycourse']['100'].gpa_params[0], 3.0)
# Score is not shown but grade
self.assertTrue('
Grade | ' in self.browser.contents)
self.assertFalse('Score | ' in self.browser.contents)
self.browser.getLink("Edit course list").click()
self.assertTrue('Grade | ' in self.browser.contents)
self.assertFalse('Score | ' in self.browser.contents)
self.browser.getLink("COURSE1").click()
self.assertFalse('Score' in self.browser.contents)
# Students can open the special Uniben pdf course result slip
self.browser.open(self.student_path + '/studycourse/100')
self.browser.getLink("Download course result slip").click()
self.assertEqual(self.browser.headers['Status'], '200 Ok')
self.assertEqual(self.browser.headers['Content-Type'], 'application/pdf')
# Even if course is mandatory, students can remove the course
self.student['studycourse']['100']['COURSE1'].mandatory = True
self.browser.open(self.student_path + '/studycourse/100')
self.browser.getLink("Edit course list").click()
ctrl = self.browser.getControl(name='val_id')
ctrl.getControl(value='COURSE1').selected = True
self.browser.getControl("Remove selected", index=0).click()
self.assertTrue('Successfully removed' in self.browser.contents)
# Students can open the customized pdf course registration slip
# if they have registered their course list
self.browser.open(
self.student_path + '/studycourse/100/course_registration_slip.pdf')
self.assertTrue('Forbidden' in self.browser.contents)
IWorkflowState(self.student).setState('courses registered')
self.browser.open(self.student_path + '/studycourse/100')
self.browser.getLink("Download course registration slip").click()
self.assertEqual(self.browser.headers['Status'], '200 Ok')
self.assertEqual(self.browser.headers['Content-Type'], 'application/pdf')
path = os.path.join(samples_dir(), 'course_registration_slip.pdf')
open(path, 'wb').write(self.browser.contents)
print "Sample PDF course_registration_slip.pdf written to %s" % path
# Students can always download pdf course result slip
self.browser.open(
self.student_path + '/studycourse/100/course_result_slip.pdf')
self.assertEqual(self.browser.headers['Status'], '200 Ok')
self.assertEqual(self.browser.headers['Content-Type'], 'application/pdf')
path = os.path.join(samples_dir(), 'course_result_slip.pdf')
open(path, 'wb').write(self.browser.contents)
print "Sample PDF course_result_slip.pdf written to %s" % path
def test_get_returning_data(self):
# Student is in level 100, session 2004 with verdict A
utils = getUtility(IStudentsUtils)
self.assertEqual(utils.getReturningData(self.student),(2005, 200))
self.student['studycourse'].current_verdict = 'C'
self.assertEqual(utils.getReturningData(self.student),(2005, 110))
self.student['studycourse'].current_verdict = 'D'
self.assertEqual(utils.getReturningData(self.student),(2005, 100))
return
def test_set_returning_data(self):
# Student is in level 100, session 2004 with verdict A
utils = getUtility(IStudentsUtils)
utils.setReturningData(self.student)
self.assertEqual(self.student['studycourse'].current_session, 2005)
self.assertEqual(self.student['studycourse'].current_level, 200)
self.student['studycourse'].current_session = 2004
self.student['studycourse'].current_level = 100
self.student['studycourse'].current_verdict = 'C'
utils.setReturningData(self.student)
self.assertEqual(self.student['studycourse'].current_session, 2005)
self.assertEqual(self.student['studycourse'].current_level, 110)
self.student['studycourse'].current_session = 2004
self.student['studycourse'].current_level = 100
self.student['studycourse'].current_verdict = 'D'
utils.setReturningData(self.student)
self.assertEqual(self.student['studycourse'].current_session, 2005)
self.assertEqual(self.student['studycourse'].current_level, 100)
return
def test_set_payment_details(self):
self.app['configuration']['2004'].gown_fee = 150.0
self.app['configuration']['2004'].transfer_fee = 90.0
self.app['configuration']['2004'].booking_fee = 150.0
self.app['configuration']['2004'].maint_fee = 180.0
configuration = createObject('waeup.SessionConfiguration')
configuration.academic_session = 2000
self.app['configuration'].addSessionConfiguration(configuration)
configuration2 = createObject('waeup.SessionConfiguration')
configuration2.academic_session = 2002
self.app['configuration'].addSessionConfiguration(configuration2)
configuration3 = createObject('waeup.SessionConfiguration')
configuration3.academic_session = 2003
self.app['configuration'].addSessionConfiguration(configuration3)
configuration4 = createObject('waeup.SessionConfiguration')
configuration4.academic_session = 2005
self.app['configuration'].addSessionConfiguration(configuration4)
utils = getUtility(IStudentsUtils)
self.student['studycourse'].entry_session = 2002
self.student.nationality = u'NG'
error, payment = utils.setPaymentDetails('schoolfee',
self.student, None, None, None)
self.assertEqual(payment, None)
# Student is in state 'created' and can thus not pay.
self.assertTrue(u'Amount could not be determined.' in error)
# Previous session must be valid.
error, payment = utils.setPaymentDetails('schoolfee',
self.student, 2000, 300, None)
self.assertEqual(payment, None)
self.assertTrue(u'The previous session must not fall below' in error)
error, payment = utils.setPaymentDetails('schoolfee',
self.student, 2005, 300, None)
self.assertEqual(payment, None)
self.assertTrue(u'This is not a previous session' in error)
# Previous session schoolfee payment; fresh and returning
# are distinguished by their entry_level
error, payment = utils.setPaymentDetails('schoolfee',
self.student, 2002, 300, None)
self.assertEqual(payment.amount_auth, 63000.0)
self.assertEqual(payment.p_session, 2002)
self.assertEqual(payment.p_level, 300)
self.assertFalse(payment.p_current)
error, payment = utils.setPaymentDetails('schoolfee',
self.student, 2003, 300, None)
self.assertEqual(payment.amount_auth, 26800.0)
self.assertEqual(payment.p_session, 2003)
self.assertEqual(payment.p_level, 300)
self.assertFalse(payment.p_current)
# Current schoolfee payment; fresh and returning
# are distinguished by their state
IWorkflowState(self.student).setState('cleared')
error, payment = utils.setPaymentDetails('schoolfee',
self.student, None, None, None)
self.assertEqual(payment.p_level, 100)
self.assertEqual(payment.p_session, 2004)
self.assertEqual(payment.amount_auth, 63000.0)
self.assertEqual(payment.p_item, u'CERT1')
self.assertEqual(error, None)
self.assertTrue(payment.p_current)
# Add penalty fee ...
# ... for cleared
self.app['configuration']['2004'].penalty_ug_ft = 99.0
# ... for returning
self.app['configuration']['2005'].penalty_ug_ft = 88.0
error, payment = utils.setPaymentDetails('schoolfee',
self.student, None, None, None)
self.assertEqual(payment.amount_auth, 63099.0)
IWorkflowState(self.student).setState('returning')
#error, payment = utils.setPaymentDetails('schoolfee',
# self.student, None, None, None)
#self.assertTrue(
# u'You have not yet paid your current/active session.' in error)
## Ok, that means we have to add paid payment ticket first.
#payment = createObject('waeup.StudentOnlinePayment')
#payment.p_category = u'schoolfee'
#payment.p_session = self.student.current_session
#payment.p_item = u'My Certificate'
#payment.p_id = u'anyid'
#payment.p_state = u'paid'
#self.student['payments']['anykey'] = payment
error, payment = utils.setPaymentDetails('schoolfee',
self.student, None, None, None)
self.assertEqual(payment.p_level, 200)
self.assertEqual(payment.p_session, 2005)
self.assertEqual(payment.amount_auth, 26888.0)
self.assertEqual(payment.p_item, u'CERT1')
self.assertEqual(error, None)
# Old returning students may pay less.
#self.certificate.school_fee_2 = 50000.0
#self.certificate.custom_float_2 = 30000.0
error, payment = utils.setPaymentDetails(
'schoolfee', self.student, None, None, None)
self.assertEqual(payment.amount_auth, 26888.0)
# Staff members pay less.
self.student.is_staff = True
error, payment = utils.setPaymentDetails('schoolfee',
self.student, None, None, None)
self.assertEqual(payment.p_level, 200)
self.assertEqual(payment.p_session, 2005)
self.assertEqual(payment.amount_auth, 13488.0)
self.assertEqual(payment.p_item, u'CERT1')
self.assertEqual(error, None)
# Foreigners pay more.
IWorkflowState(self.student).setState('cleared')
self.student.is_staff = False
self.student.nationality = u'DE'
error, payment = utils.setPaymentDetails(
'schoolfee', self.student, None, None, None)
self.assertEqual(payment.p_level, 100)
self.assertEqual(payment.p_session, 2004)
self.assertEqual(payment.amount_auth, 300099.0)
self.assertEqual(payment.p_item, u'CERT1')
self.assertEqual(error, None)
IWorkflowState(self.student).setState('returning')
self.student.is_staff = False
error, payment = utils.setPaymentDetails(
'schoolfee', self.student, None, None, None)
self.assertEqual(payment.p_level, 200)
self.assertEqual(payment.p_session, 2005)
self.assertEqual(payment.amount_auth, 277088.0)
self.assertEqual(payment.p_item, u'CERT1')
self.assertEqual(error, None)
# In Uniben students can pay school fee in all states no matter
# if they are ug or pg students.
# diabled on 02/10/2017, see ticket 1108
#IWorkflowState(self.student).setState('school fee paid')
#self.student.is_staff = False
#self.student.nationality = u'NG'
#self.certificate.school_fee_2 = 10000.0
#error, payment = utils.setPaymentDetails(
# 'schoolfee', self.student, None, None, None)
#self.assertEqual(payment.p_level, None)
#self.assertEqual(payment.p_session, 2005)
#self.assertEqual(payment.amount_auth, 10088.0)
#self.assertEqual(payment.p_item, u'CERT1')
#self.assertEqual(error, None)
#IWorkflowState(self.student).setState('courses registered')
#self.certificate.study_mode = 'special_pg_pt'
#error, payment = utils.setPaymentDetails(
# 'schoolfee', self.student, None, None, None)
#self.assertEqual(payment.p_level, None)
#self.assertEqual(payment.p_session, 2005)
#self.assertEqual(payment.amount_auth, 10000.0)
#self.assertEqual(payment.p_item, u'CERT1')
#self.assertEqual(error, None)
#IWorkflowState(self.student).setState('courses validated')
#error, payment = utils.setPaymentDetails(
# 'schoolfee', self.student, None, None, None)
#self.assertEqual(payment.p_level, None)
#self.assertEqual(payment.p_session, 2005)
#self.assertEqual(payment.amount_auth, 10000.0)
#self.assertEqual(payment.p_item, u'CERT1')
#self.assertEqual(error, None)
error, payment = utils.setPaymentDetails('clearance',
self.student, None, None, None)
self.assertEqual(payment.p_level, 100)
self.assertEqual(payment.p_session, 2004)
self.assertEqual(payment.amount_auth, 60000.0)
self.assertEqual(payment.p_item, u'CERT1')
self.assertEqual(error, None)
error, payment = utils.setPaymentDetails('gown',
self.student, None, None, None)
self.assertEqual(payment.p_level, 100)
self.assertEqual(payment.p_session, 2004)
self.assertEqual(payment.amount_auth, 150.0)
self.assertEqual(payment.p_item, u'')
self.assertEqual(error, None)
bedticket = BedTicket()
bedticket.booking_session = 2004
bedticket.bed_type = u'any bed type'
bedticket.bed = self.app['hostels']['hall-1']['hall-1_A_101_A']
bedticket.bed_coordinates = u'My bed coordinates'
self.student['accommodation'].addBedTicket(bedticket)
error, payment = utils.setPaymentDetails('hostel_maintenance',
self.student, None, None, None)
self.assertEqual(payment.p_level, 100)
self.assertEqual(payment.p_session, 2004)
self.assertEqual(payment.amount_auth, 876.0)
self.assertEqual(payment.p_item, u'My bed coordinates')
self.assertEqual(error, None)
#self.certificate.study_mode = 'ug_ft'
#error, payment = utils.setPaymentDetails('bed_allocation',
# self.student, None, None, None)
#self.assertTrue(u'Amount could not be determined.' in error)
#self.student['studycourse'].current_session = 2004
#self.student['studycourse'].entry_session = 2004
#self.student['studycourse'].current_level = 100
#error, payment = utils.setPaymentDetails('bed_allocation',
# self.student, None, None, None)
#self.assertEqual(payment.p_level, 100)
#self.assertEqual(payment.p_session, 2004)
#self.assertEqual(payment.amount_auth, 650.0) # plus 500 student union
#self.assertEqual(payment.p_item, u'regular_male_fr')
#self.assertEqual(error, None)
self.certificate.study_mode = 'pg_ft'
error, payment = utils.setPaymentDetails('bed_allocation',
self.student, None, None, None)
self.assertEqual(error, u'Select your favoured hostel first.')
self.student['accommodation'].desired_hostel = u'no'
error, payment = utils.setPaymentDetails('bed_allocation',
self.student, None, None, None)
self.assertEqual(payment.p_level, 100)
self.assertEqual(payment.p_session, 2004)
self.assertEqual(payment.amount_auth, 650.0)
self.assertEqual(payment.p_item, u'pg_male_all')
self.assertEqual(error, None)
#error, payment = utils.setPaymentDetails('hostel_application',
# self.student, None, None, None)
#self.assertEqual(payment.p_level, 100)
#self.assertEqual(payment.p_session, 2004)
#self.assertEqual(payment.amount_auth, 1000.0)
#self.assertEqual(payment.p_item, u'')
#self.assertEqual(error, None)
#payment.approve()
#self.student['payments'][payment.p_id] = payment
#error, payment = utils.setPaymentDetails('tempmaint_1',
# self.student, None, None, None)
#self.assertEqual(payment.p_level, 100)
#self.assertEqual(payment.p_session, 2004)
#self.assertEqual(payment.amount_auth, 8150.0)
#self.assertEqual(payment.p_item, u'Hall 1-4 M/F Ekehuan')
#self.assertEqual(error, None)
#error, payment = utils.setPaymentDetails('tempmaint_2',
# self.student, None, None, None)
#self.assertEqual(payment.p_level, 100)
#self.assertEqual(payment.p_session, 2004)
#self.assertEqual(payment.amount_auth, 12650.0)
#self.assertEqual(payment.p_item, u'Hall 5 M/F')
#self.assertEqual(error, None)
#error, payment = utils.setPaymentDetails('tempmaint_3',
# self.student, None, None, None)
#self.assertEqual(payment.p_level, 100)
#self.assertEqual(payment.p_session, 2004)
#self.assertEqual(payment.amount_auth, 9650.0)
#self.assertEqual(payment.p_item, u'Clinical Hostel')
#self.assertEqual(error, None)
error, payment = utils.setPaymentDetails('transfer',
self.student, None, None, None)
self.assertEqual(payment.p_level, 100)
self.assertEqual(payment.p_session, 2004)
self.assertEqual(payment.amount_auth, 90.0)
self.assertEqual(payment.p_item, u'')
self.assertEqual(error, None)
return
def test_edit_level_by_co(self):
# Create clearance officer
self.app['users'].addUser('mrclear', 'mrClearsecret1')
self.app['users']['mrclear'].email = 'mrclear@foo.ng'
self.app['users']['mrclear'].title = 'Carlo Pitter'
# Assign local ClearanceOfficer role
department = self.app['faculties']['fac1']['dep1']
prmlocal = IPrincipalRoleManager(department)
prmlocal.assignRoleToPrincipal('waeup.local.ClearanceOfficer', 'mrclear')
notify(LocalRoleSetEvent(
department, 'waeup.local.ClearanceOfficer', 'mrclear', granted=True))
IWorkflowState(self.student).setState('clearance started')
# Login as clearance officer
self.browser.open(self.login_path)
self.browser.getControl(name="form.login").value = 'mrclear'
self.browser.getControl(name="form.password").value = 'mrClearsecret1'
self.browser.getControl("Login").click()
self.assertMatches('...You logged in...', self.browser.contents)
# Only in state clearance requested the CO does see the
# 'Edit level' button ...
self.browser.open(self.studycourse_path)
self.assertFalse('Edit level' in self.browser.contents)
# ... and can open the edit_level view
self.browser.open(self.studycourse_path + '/edit_level')
self.assertMatches('...is locked...', self.browser.contents)
self.assertEqual(self.browser.url, self.studycourse_path)
IWorkflowInfo(self.student).fireTransition('request_clearance')
self.browser.open(self.studycourse_path)
self.assertTrue('Edit level' in self.browser.contents)
self.browser.getLink("Edit level").click()
self.browser.getControl(name="form.current_level").value = ['200']
self.browser.getControl("Save").click()
self.assertMatches('...has been saved...', self.browser.contents)
self.assertEqual(self.student.current_level, 200)
def test_postgraduate_student_access(self):
self.certificate.study_mode = 'special_pg_pt'
self.certificate.start_level = 700
self.certificate.end_level = 800
self.student['studycourse'].current_level = 700
IWorkflowState(self.student).setState('school fee paid')
self.browser.open(self.login_path)
self.browser.getControl(name="form.login").value = self.student_id
self.browser.getControl(name="form.password").value = 'spwd'
self.browser.getControl("Login").click()
self.assertTrue(
'Did you know that with' in self.browser.contents)
# Now students can add the current study level
self.browser.getLink("Study Course").click()
self.browser.getLink("Add course list").click()
self.assertMatches('...Add current level 700...',
self.browser.contents)
self.browser.getControl("Create course list now").click()
# A level with no course ticket was created
self.assertEqual(self.student['studycourse']['700'].number_of_tickets, 0)
self.browser.getLink("700").click()
self.browser.getLink("Edit course list").click()
self.browser.getLink("here").click()
self.browser.getControl(name="form.course").value = ['COURSE1']
# Non-final year students can't add ticket with 51 credits
self.app['faculties']['fac1']['dep1'].courses['COURSE1'].credits = 51
self.browser.getControl("Add course ticket").click()
self.assertMatches('...Maximum credits exceeded...',
self.browser.contents)
# Final year students can't add ticket with 52 credits ...
self.app['faculties']['fac1']['dep1'].courses['COURSE1'].credits = 52
self.student['studycourse'].certificate.end_level = 700
self.browser.getControl("Add course ticket").click()
self.assertMatches('...Maximum credits exceeded...',
self.browser.contents)
# ... but with 51 credits
self.app['faculties']['fac1']['dep1'].courses['COURSE1'].credits = 51
self.browser.getControl("Add course ticket").click()
self.assertMatches('...Successfully added COURSE1...',
self.browser.contents)
# Non-final year special postgraduate students can't register
# course lists if their total credits are 51 and thus exceed 50 ...
self.student['studycourse'].certificate.end_level = 800
self.browser.getControl("Register course list").click()
self.assertMatches('...Maximum credits exceeded...',
self.browser.contents)
# ... but final year students can
self.student['studycourse'].certificate.end_level = 700
self.browser.getControl("Register course list").click()
self.assertMatches('...Course list has been registered...',
self.browser.contents)
self.assertEqual(self.student.state, 'courses registered')
return
def test_login(self):
# If suspended_comment is set this message will be flashed instead
self.student.suspended_comment = u'Aetsch baetsch!'
self.student.suspended = True
self.browser.open(self.login_path)
self.browser.getControl(name="form.login").value = self.student_id
self.browser.getControl(name="form.password").value = 'spwd'
self.browser.getControl("Login").click()
# Uniben does not display suspended_comment
self.assertMatches(
'...Your account has been deactivated.
...',
self.browser.contents)
self.student.suspended = False
def test_activate_deactivate_buttons(self):
self.browser.addHeader('Authorization', 'Basic mgr:mgrpw')
self.browser.open(self.student_path)
self.browser.getLink("Deactivate").click()
self.assertTrue(
'Student account has been deactivated.' in self.browser.contents)
self.assertTrue(
'Base Data (account deactivated)' in self.browser.contents)
self.assertTrue(self.student.suspended)
self.browser.getLink("Activate").click()
self.assertTrue(
'Student account has been activated.' in self.browser.contents)
self.assertFalse(
'Base Data (account deactivated)' in self.browser.contents)
self.assertFalse(self.student.suspended)
# History messages have been added ...
self.browser.getLink("History").click()
# User is undisclosed
self.assertTrue(
'Student account deactivated
' in self.browser.contents)
self.assertTrue(
'Student account activated
' in self.browser.contents)
# ... and actions have been logged.
logfile = os.path.join(
self.app['datacenter'].storage, 'logs', 'students.log')
logcontent = open(logfile).read()
self.assertTrue('zope.mgr - waeup.uniben.students.browser.CustomStudentDeactivateView - '
'B1000000 - account deactivated' in logcontent)
self.assertTrue('zope.mgr - waeup.uniben.students.browser.CustomStudentActivateView - '
'B1000000 - account activated' in logcontent)
def test_manage_upload_fpm_file(self):
self.browser.addHeader('Authorization', 'Basic mgr:mgrpw')
self.browser.open(self.manage_clearance_path)
image = open(SAMPLE_FPM, 'rb')
ctrl = self.browser.getControl(name='leftthumbprintupload')
file_ctrl = ctrl.mech_control
file_ctrl.add_file(image, filename='thumbprint.fpm')
self.browser.getControl(
name='upload_leftthumbprintupload').click()
self.assertTrue(
'File finger1.fpm uploaded.' in self.browser.contents)
self.assertTrue(
'http://localhost/app/students/B1000000/finger1.fpm'
in self.browser.contents)
self.browser.getControl(
name='delete_leftthumbprintupload').click()
self.assertTrue(
'finger1.fpm deleted'
in self.browser.contents)
def test_handle_clearance_by_co(self):
# Create clearance officer
self.app['users'].addUser('mrclear', 'mrClearsecret1')
self.app['users']['mrclear'].email = 'mrclear@foo.ng'
self.app['users']['mrclear'].title = 'Carlo Pitter'
department = self.app['faculties']['fac1']['dep1']
prmlocal = IPrincipalRoleManager(department)
prmlocal.assignRoleToPrincipal('waeup.local.ClearanceOfficer', 'mrclear')
notify(LocalRoleSetEvent(
department, 'waeup.local.ClearanceOfficer', 'mrclear', granted=True))
IWorkflowState(self.student).setState('clearance requested')
# Login as clearance officer
self.browser.open(self.login_path)
self.browser.getControl(name="form.login").value = 'mrclear'
self.browser.getControl(name="form.password").value = 'mrClearsecret1'
self.browser.getControl("Login").click()
self.assertMatches('...You logged in...', self.browser.contents)
# CO can view the student ...
self.browser.open(self.clearance_path)
self.assertEqual(self.browser.headers['Status'], '200 Ok')
self.assertEqual(self.browser.url, self.clearance_path)
# Clearance is disabled for this session for ug students ...
self.browser.open(self.clearance_path)
self.assertFalse('Clear student' in self.browser.contents)
self.browser.open(self.student_path + '/clear')
self.assertTrue('Clearance is disabled for this session'
in self.browser.contents)
# ... but not for
self.certificate.study_mode = 'pg_ft'
self.browser.open(self.clearance_path)
self.assertTrue('Clear student' in self.browser.contents)
self.browser.open(self.student_path + '/clear')
self.assertTrue('Student has been cleared' in self.browser.contents)
def test_transcripts(self):
studylevel = createObject(u'waeup.StudentStudyLevel')
IWorkflowState(self.student).setState('transcript validated')
studylevel.level = 100
studylevel.level_session = 2005
self.student['studycourse'].entry_mode = 'ug_ft'
self.student['studycourse'].addStudentStudyLevel(
self.certificate, studylevel)
studylevel2 = createObject(u'waeup.StudentStudyLevel')
studylevel2.level = 110
studylevel2.level_session = 2006
self.student['studycourse'].addStudentStudyLevel(
self.certificate, studylevel2)
# Add second course (COURSE has been added automatically)
courseticket = createObject('waeup.CourseTicket')
courseticket.code = 'ANYCODE'
courseticket.title = u'Any TITLE'
courseticket.credits = 13
courseticket.score = 66
courseticket.semester = 1
courseticket.dcode = u'ANYDCODE'
courseticket.fcode = u'ANYFCODE'
self.student['studycourse']['110']['COURSE2'] = courseticket
self.student['studycourse']['100']['COURSE1'].score = 55
self.assertEqual(self.student['studycourse']['100'].gpa_params_rectified[0], 3.0)
self.assertEqual(self.student['studycourse']['110'].gpa_params_rectified[0], 4.0)
# Get transcript data
td = self.student['studycourse'].getTranscriptData()
self.assertEqual(td[0][0]['level_key'], '100')
self.assertEqual(td[0][0]['sgpa'], 3.0)
self.assertEqual(td[0][0]['level'].level, 100)
self.assertEqual(td[0][0]['level'].level_session, 2005)
self.assertEqual(td[0][0]['tickets_1'][0].code, 'COURSE1')
self.assertEqual(td[0][1]['level_key'], '110')
self.assertEqual(td[0][1]['sgpa'], 4.0)
self.assertEqual(td[0][1]['level'].level, 110)
self.assertEqual(td[0][1]['level'].level_session, 2006)
self.assertEqual(td[0][1]['tickets_1'][0].code, 'ANYCODE')
self.assertEqual(td[1], 3.5652173913043477)
self.browser.open(self.login_path)
self.browser.getControl(name="form.login").value = self.student_id
self.browser.getControl(name="form.password").value = 'spwd'
self.browser.getControl("Login").click()
# Students can't open the pdf transcript ...
transcript_path = self.student_path + '/studycourse/transcript'
self.assertRaises(
Unauthorized, self.browser.open, transcript_path)
# ... but managers can
self.browser.open(self.student_path)
self.browser.getLink("Logout").click()
self.browser.addHeader('Authorization', 'Basic mgr:mgrpw')
self.browser.open(transcript_path)
self.assertEqual(self.browser.headers['Status'], '200 Ok')
self.assertTrue('Transcript' in self.browser.contents)
self.browser.open(self.student_path + '/studycourse/transcript.pdf')
self.assertEqual(self.browser.headers['Status'], '200 Ok')
self.assertEqual(self.browser.headers['Content-Type'], 'application/pdf')
path = os.path.join(samples_dir(), 'transcript.pdf')
open(path, 'wb').write(self.browser.contents)
print "Sample PDF transcript.pdf written to %s" % path
def test_student_accommodation(self):
self.app['hostels'].allocation_expiration = 7
self.student['accommodation'].desired_hostel = u'hall-1'
bed = Bed()
bed.bed_id = u'hall-1_A_101_C'
bed.bed_number = 3
bed.owner = NOT_OCCUPIED
bed.bed_type = u'regular_male_fi'
self.app['hostels']['hall-1'].addBed(bed)
self.browser.open(self.login_path)
self.browser.getControl(name="form.login").value = self.student_id
self.browser.getControl(name="form.password").value = 'spwd'
self.browser.getControl("Login").click()
# Students can add online booking fee payment tickets and open the
# callback view (see test_manage_payments).
self.browser.getLink("Payments").click()
self.browser.getLink("Add current session payment ticket").click()
self.browser.getControl(name="form.p_category").value = ['bed_allocation']
self.browser.getControl("Create ticket").click()
p_ticket = self.student['payments'].values()[0]
self.assertEqual(p_ticket.p_item, 'regular_male_fr (hall-1)')
p_ticket.approveStudentPayment()
# The new HOS-0 pin has been created.
self.assertEqual(len(self.app['accesscodes']['HOS-0']),1)
pin = self.app['accesscodes']['HOS-0'].keys()[0]
ac = self.app['accesscodes']['HOS-0'][pin]
parts = pin.split('-')[1:]
sfeseries, sfenumber = parts
# Students can use HOS code and book a bed space with it ...
self.browser.open(self.acco_path)
# ... but not if booking period has expired ...
self.app['hostels'].enddate = datetime.now(pytz.utc)
self.browser.getControl("Book accommodation").click()
self.assertMatches('...Outside booking period: ...',
self.browser.contents)
self.app['hostels'].enddate = datetime.now(pytz.utc) + timedelta(days=10)
# ... or student data are incomplete ...
self.student['studycourse'].current_level = None
self.browser.getControl("Book accommodation").click()
self.assertMatches('...Your data are incomplete...',
self.browser.contents)
self.student['studycourse'].current_level = 200
# ... or student is not the an allowed state ...
self.browser.getControl("Book accommodation").click()
self.assertMatches('...You are in the wrong...',
self.browser.contents)
self.app['hostels'].accommodation_states = ['admitted', 'school fee paid']
IWorkflowState(self.student).setState('school fee paid')
# ... or student has not appropriate verdict (Uniben only!)
self.student['studycourse'].entry_session = 2000 # non-fresh
self.student['studycourse'].current_level = 500 # final-year
self.student['studycourse'].current_verdict = 'C'
self.browser.getControl("Book accommodation").click()
self.assertMatches('...Your are not eligible...',
self.browser.contents)
self.student['studycourse'].previous_verdict = 'A'
self.browser.getControl("Book accommodation").click()
self.assertMatches('...Activation Code:...',
self.browser.contents)
# Student can't use faked ACs ...
self.browser.getControl(name="ac_series").value = u'nonsense'
self.browser.getControl(name="ac_number").value = sfenumber
self.browser.getControl("Create bed ticket").click()
self.assertMatches('...Activation code is invalid...',
self.browser.contents)
# ... or ACs owned by somebody else.
ac.owner = u'Anybody'
self.browser.getControl(name="ac_series").value = sfeseries
self.browser.getControl(name="ac_number").value = sfenumber
self.browser.getControl("Create bed ticket").click()
self.assertMatches('...You are not the owner of this access code...',
self.browser.contents)
# The bed remains empty.
bed = self.app['hostels']['hall-1']['hall-1_A_101_C']
self.assertTrue(bed.owner == NOT_OCCUPIED)
ac.owner = self.student_id
self.browser.getControl(name="ac_series").value = sfeseries
self.browser.getControl(name="ac_number").value = sfenumber
self.browser.getControl("Create bed ticket").click()
self.assertMatches('...Hall 1, Block/Unit A, Room 101, Bed C...',
self.browser.contents)
# Bed has been allocated.
self.assertTrue(bed.owner == self.student_id)
# BedTicketAddPage is now blocked.
self.browser.getControl("Book accommodation").click()
self.assertMatches('...You already booked a bed space...',
self.browser.contents)
# The bed ticket displays the data correctly.
self.browser.open(self.acco_path + '/2004')
self.assertMatches('...Hall 1, Block/Unit A, Room 101, Bed C...',
self.browser.contents)
self.assertMatches('...2004/2005...', self.browser.contents)
self.assertMatches('...regular_male_fi...', self.browser.contents)
self.assertMatches('...%s...' % pin, self.browser.contents)
# Students can open the pdf slip.
self.browser.open(self.browser.url + '/bed_allocation_slip.pdf')
self.assertEqual(self.browser.headers['Status'], '200 Ok')
self.assertEqual(self.browser.headers['Content-Type'], 'application/pdf')
path = os.path.join(samples_dir(), 'bed_allocation_slip.pdf')
open(path, 'wb').write(self.browser.contents)
print "Sample PDF bed_allocation_slip.pdf written to %s" % path
# Students can't relocate themselves.
self.assertFalse('Relocate' in self.browser.contents)
relocate_path = self.acco_path + '/2004/relocate'
self.assertRaises(
Unauthorized, self.browser.open, relocate_path)
# Students can't see the Remove button and check boxes.
self.browser.open(self.acco_path)
self.assertFalse('Remove' in self.browser.contents)
self.assertFalse('val_id' in self.browser.contents)
# Students can pay maintenance fee now.
self.browser.open(self.payments_path)
self.browser.open(self.payments_path + '/addop')
self.browser.getControl(name="form.p_category").value = ['hostel_maintenance']
self.browser.getControl("Create ticket").click()
self.assertMatches('...Payment ticket created...',
self.browser.contents)
# Maintennace fee is taken from the hostel object.
self.assertEqual(self.student['payments'].values()[1].amount_auth, 876.0)
# If the hostel's maintenance fee isn't set, the fee is
# taken from the session configuration object.
self.app['hostels']['hall-1'].maint_fee = 0.0
self.browser.open(self.payments_path + '/addop')
self.browser.getControl(name="form.p_category").value = ['hostel_maintenance']
self.browser.getControl("Create ticket").click()
self.assertEqual(self.student['payments'].values()[2].amount_auth, 987.0)
return
def test_student_clearance(self):
# create some passport file for `student`
storage = getUtility(IExtFileStore)
image_path = os.path.join(os.path.dirname(__file__), 'test_image.jpg')
self.image_contents = open(image_path, 'rb').read()
file_id = IFileStoreNameChooser(self.student).chooseName(
attr='passport.jpg')
storage.createFile(file_id, StringIO(self.image_contents))
IWorkflowInfo(self.student).fireTransition('admit')
self.browser.open(self.login_path)
self.browser.getControl(name="form.login").value = self.student_id
self.browser.getControl(name="form.password").value = 'spwd'
self.browser.getControl("Login").click()
self.assertMatches(
'...Did you know that with...', self.browser.contents)
self.browser.getLink("Base Data").click()
self.browser.getLink("Download admission letter").click()
self.assertEqual(self.browser.headers['Status'], '200 Ok')
self.assertEqual(self.browser.headers['Content-Type'], 'application/pdf')
path = os.path.join(samples_dir(), 'admission_slip.pdf')
open(path, 'wb').write(self.browser.contents)
print "Sample PDF admission_slip.pdf written to %s" % path
self.browser.open(self.student_path + '/start_clearance')
# Regular students have to enter an access code
self.browser.getControl("Start clearance now").click()
self.assertTrue('Activation code is invalid' in self.browser.contents)
# DCOEM students can start clearance without access code
self.app['faculties']['fac1'].code = 'DCOEM'
self.browser.open(self.student_path + '/start_clearance')
self.browser.getControl("Start clearance now").click()
self.assertMatches('...Clearance process has been started...',
self.browser.contents)
def test_student_medical_questionnaire(self):
self.app['configuration']['2004'].medical_quest_fee = 1000.0
IWorkflowInfo(self.student).fireTransition('admit')
self.browser.open(self.login_path)
self.browser.getControl(name="form.login").value = self.student_id
self.browser.getControl(name="form.password").value = 'spwd'
self.browser.getControl("Login").click()
self.assertMatches(
'...Did you know that with...', self.browser.contents)
self.browser.getLink("Base Data").click()
self.browser.getLink("Medical Questionnaire").click()
self.assertTrue('Please pay medical questionnaire payment first' in
self.browser.contents)
self.assertEqual(self.browser.url, self.student_path)
self.browser.open(self.payments_path)
self.browser.getLink("Add current session payment ticket").click()
self.browser.getControl(name="form.p_category").value = ['medical_quest']
self.browser.getControl("Create ticket").click()
p_ticket = self.student['payments'].values()[0]
p_ticket.approveStudentPayment()
self.browser.getLink("Base Data").click()
self.browser.getLink("Medical Questionnaire").click()
self.browser.getLink("Download medical questionnaire slip").click()
self.assertEqual(self.browser.headers['Status'], '200 Ok')
self.assertEqual(self.browser.headers['Content-Type'], 'application/pdf')
path = os.path.join(samples_dir(), 'medical_questionnaire_slip.pdf')
open(path, 'wb').write(self.browser.contents)
print "Sample PDF medical_questionnaire_slip.pdf written to %s" % path
self.browser.open(self.student_path)
self.browser.getLink("Medical Questionnaire").click()
self.browser.getControl(name="form.bloodgroup").value = 'A'
self.browser.getControl(name="form.genotype").value = 'XYZ'
self.browser.getControl("Save").click()
self.browser.getLink("Base Data").click()
self.browser.getLink("Download TISHIP registration slip").click()
self.assertEqual(self.browser.headers['Status'], '200 Ok')
self.assertEqual(self.browser.headers['Content-Type'], 'application/pdf')
path = os.path.join(samples_dir(), 'tiship_slip.pdf')
open(path, 'wb').write(self.browser.contents)
print "Sample PDF tiship_slip.pdf written to %s" % path
def test_fiancial_clearance_pdf_slip(self):
payment1 = createObject(u'waeup.StudentOnlinePayment')
timestamp = ("%d" % int(time()*10000))[1:]
payment1.p_id = "LSCNEW-2-4153206270" # the longest possible p_id
payment1.p_category = 'schoolfee'
payment1.p_item = u'My School Fee'
payment1.p_session = 2015
payment1.p_level = 100
payment1.p_current = True
payment1.amount_auth = 23456.9
payment1.approve()
payment2 = createObject(u'waeup.StudentOnlinePayment')
timestamp = ("%d" % int(time()*10000))[1:]
payment2.p_id = "p%s" % timestamp
payment2.p_category = 'clearance'
payment2.p_item = u'My Clearance Fee'
payment2.p_session = 2015
payment2.p_level = 100
payment2.p_current = True
payment2.amount_auth = 5678.6
payment2.approve()
self.student['payments'][payment1.p_id] = payment1
self.student['payments'][payment2.p_id] = payment2
self.student.nysc = True
self.student.nysc_updated = datetime.now(pytz.utc)
self.student.nysc_senate_info = u'Senate Info test'
self.browser.addHeader('Authorization', 'Basic mgr:mgrpw')
self.browser.open(self.student_path + '/clear_financially')
self.browser.getLink("Download fee payment history").click()
self.assertEqual(self.browser.headers['Status'], '200 Ok')
self.assertEqual(self.browser.headers['Content-Type'],
'application/pdf')
path = os.path.join(samples_dir(), 'fee_payment_history.pdf')
open(path, 'wb').write(self.browser.contents)
print "Sample PDF fee_payment_history.pdf written to %s" % path
return
def test_affidavit_slip(self):
self.browser.open(self.login_path)
self.browser.getControl(name="form.login").value = self.student_id
self.browser.getControl(name="form.password").value = 'spwd'
self.browser.getControl("Login").click()
self.browser.getLink("Base Data").click()
self.browser.getLink("Upload affidavit of good conduct").click()
self.browser.getLink("Download affidavit of good conduct form").click()
self.assertEqual(self.browser.headers['Status'], '200 Ok')
self.assertEqual(self.browser.headers['Content-Type'], 'application/pdf')
path = os.path.join(samples_dir(), 'affidavit_good_conduct.pdf')
open(path, 'wb').write(self.browser.contents)
print "Sample PDF affidavit_good_conduct.pdf written to %s" % path