source: main/waeup.kwarapoly/trunk/src/waeup/kwarapoly/students/tests/test_browser.py @ 10756

Last change on this file since 10756 was 10756, checked in by Henrik Bettermann, 11 years ago

Allow students in state cleared to upload a passport picture.

  • Property svn:keywords set to Id
File size: 21.7 KB
Line 
1## $Id: test_browser.py 10756 2013-11-18 12:24:51Z 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
21from mechanize import LinkNotFoundError
22from StringIO import StringIO
23from hurry.workflow.interfaces import IWorkflowState, IWorkflowInfo
24from zope.component.hooks import setSite, clearSite
25from zope.component import getUtility, createObject
26from zope.interface import verify
27from waeup.kofa.app import University
28from waeup.kofa.students.tests.test_browser import (
29    StudentsFullSetup, SAMPLE_IMAGE)
30from waeup.kofa.students.accommodation import BedTicket
31from waeup.kofa.testing import FunctionalTestCase
32from waeup.kofa.interfaces import (
33    IExtFileStore, IFileStoreNameChooser)
34from waeup.kofa.browser.tests.test_pdf import samples_dir
35from waeup.kofa.students.interfaces import IStudentsUtils
36from waeup.kwarapoly.testing import FunctionalLayer
37from waeup.kwarapoly.students.utils import (
38    local_nonlocal, arts_science, pt_ft)
39
40
41class StudentProcessorTest(FunctionalTestCase):
42    """Perform some batching tests.
43    """
44
45    layer = FunctionalLayer
46
47    def setUp(self):
48        super(StudentProcessorTest, self).setUp()
49        # Setup a sample site for each test
50        app = University()
51        self.dc_root = tempfile.mkdtemp()
52        app['datacenter'].setStoragePath(self.dc_root)
53
54        # Prepopulate the ZODB...
55        self.getRootFolder()['app'] = app
56        # we add the site immediately after creation to the
57        # ZODB. Catalogs and other local utilities are not setup
58        # before that step.
59        self.app = self.getRootFolder()['app']
60        # Set site here. Some of the following setup code might need
61        # to access grok.getSite() and should get our new app then
62        setSite(app)
63
64
65    def tearDown(self):
66        super(StudentProcessorTest, self).tearDown()
67        shutil.rmtree(self.workdir)
68        shutil.rmtree(self.dc_root)
69        clearSite()
70        return
71
72class StudentUITests(StudentsFullSetup):
73    """Tests for customized student class views and pages
74    """
75
76    layer = FunctionalLayer
77
78    def setUp(self):
79        super(StudentUITests, self).setUp()
80        self.certificate.study_mode = 'hnd_ft'
81        bedticket = BedTicket()
82        bedticket.booking_session = 2004
83        bedticket.bed_type = u'any bed type'
84        bedticket.bed = self.app['hostels']['hall-1']['hall-1_A_101_A']
85        bedticket.bed_coordinates = u'My bed coordinates'
86        self.student['accommodation'].addBedTicket(bedticket)
87
88        self.app['configuration']['2004'].gown_fee = 150.0
89        self.app['configuration']['2004'].transfer_fee = 90.0
90        self.app['configuration']['2004'].clearance_fee = 120.0
91        self.app['configuration']['2004'].booking_fee = 150.0
92        self.app['configuration']['2004'].maint_fee = 180.0
93        self.app['configuration']['2004'].certificate_fee = 444.0
94
95    def test_manage_payments(self):
96        # Managers can add online payment tickets
97        self.browser.addHeader('Authorization', 'Basic mgr:mgrpw')
98        self.browser.open(self.payments_path)
99        self.browser.getLink("Add current session payment ticket").click()
100        self.browser.getControl(name="form.p_category").value = ['schoolfee']
101        self.browser.getControl("Create ticket").click()
102        self.assertMatches('...Amount could not be determined...',
103                           self.browser.contents)
104        IWorkflowState(self.student).setState('cleared')
105        self.browser.open(self.payments_path + '/addop')
106        self.browser.getControl(name="form.p_category").value = ['schoolfee']
107        self.browser.getControl("Create ticket").click()
108        self.assertMatches('...Book and pay for accommodation first...',
109                           self.browser.contents)
110
111        # In KwaraPoly only returning students can create school fee payment
112        # without haveing paid accommodation fee
113        IWorkflowState(self.student).setState('returning')
114        configuration = createObject('waeup.SessionConfiguration')
115        configuration.academic_session = 2005
116        self.app['configuration'].addSessionConfiguration(configuration)
117        self.browser.getControl(name="form.p_category").value = ['schoolfee']
118        self.browser.getControl("Create ticket").click()
119        self.assertMatches('...ticket created...',
120                           self.browser.contents)
121        ctrl = self.browser.getControl(name='val_id')
122        value = ctrl.options[0]
123        self.browser.getLink(value).click()
124        self.assertMatches('...Amount Authorized...',
125                           self.browser.contents)
126        # Managers can open payment slip
127        self.browser.getLink("Download payment slip").click()
128        self.assertEqual(self.browser.headers['Status'], '200 Ok')
129        self.assertEqual(self.browser.headers['Content-Type'], 'application/pdf')
130        # Set ticket paid
131        ticket = self.student['payments'].items()[0][1]
132        ticket.p_state = 'paid'
133        self.browser.open(self.payments_path + '/addop')
134        self.browser.getControl(name="form.p_category").value = ['schoolfee']
135        self.browser.getControl("Create ticket").click()
136        self.assertMatches('...This type of payment has already been made...',
137                           self.browser.contents)
138        # Remove all payments so that we can add a school fee payment again
139        keys = [i for i in self.student['payments'].keys()]
140        for payment in keys:
141            del self.student['payments'][payment]
142        self.browser.open(self.payments_path + '/addop')
143        self.browser.getControl(name="form.p_category").value = ['schoolfee']
144        self.browser.getControl("Create ticket").click()
145        self.assertMatches('...ticket created...',
146                           self.browser.contents)
147        self.browser.open(self.payments_path + '/addop')
148        self.browser.getControl(name="form.p_category").value = ['carryover1']
149        self.browser.getControl("Create ticket").click()
150        self.assertMatches('...ticket created...',
151                           self.browser.contents)
152        self.browser.open(self.payments_path + '/addop')
153        self.browser.getControl(name="form.p_category").value = ['carryover2']
154        self.browser.getControl("Create ticket").click()
155        self.assertMatches('...ticket created...',
156                           self.browser.contents)
157        self.browser.open(self.payments_path + '/addop')
158        self.browser.getControl(name="form.p_category").value = ['carryover3']
159        self.browser.getControl("Create ticket").click()
160        self.assertMatches('...ticket created...',
161                           self.browser.contents)
162        self.browser.open(self.payments_path + '/addop')
163        self.browser.getControl(
164            name="form.p_category").value = ['hostel_maintenance']
165        self.browser.getControl("Create ticket").click()
166        self.assertMatches('...ticket created...',
167                           self.browser.contents)
168        self.browser.open(self.payments_path + '/addop')
169        self.browser.getControl(name="form.p_category").value = ['schoolfee']
170        self.browser.getControl("Create ticket").click()
171        self.assertMatches('...ticket created...',
172                           self.browser.contents)
173        # In state admitted school fee can't be determined
174        IWorkflowState(self.student).setState('admitted')
175        self.browser.open(self.payments_path + '/addop')
176        self.browser.getControl(name="form.p_category").value = ['schoolfee']
177        self.browser.getControl("Create ticket").click()
178        self.assertMatches('...Amount could not be determined...',
179                           self.browser.contents)
180        self.browser.open(self.payments_path + '/addop')
181        self.browser.getControl(name="form.p_category").value = ['certificate']
182        self.browser.getControl("Create ticket").click()
183        self.assertMatches('...ticket created...',
184                           self.browser.contents)
185
186    def test_student_payments(self):
187        # Login
188        IWorkflowState(self.student).setState('returning')
189        self.browser.open(self.login_path)
190        self.browser.getControl(name="form.login").value = self.student_id
191        self.browser.getControl(name="form.password").value = 'spwd'
192        self.browser.getControl("Login").click()
193        self.browser.open(self.student_path + '/payments')
194        self.assertTrue(
195          'Add current session payment ticket' in self.browser.contents)
196        self.assertFalse(
197          'Add previous session payment ticket' in self.browser.contents)
198        return
199
200    def test_get_returning_data(self):
201        # Student is in level 100, session 2004 with verdict A
202        utils = getUtility(IStudentsUtils)
203        self.assertEqual(utils.getReturningData(self.student),(2005, 200))
204        self.student['studycourse'].current_verdict = 'C'
205        self.assertEqual(utils.getReturningData(self.student),(2005, 110))
206        self.student['studycourse'].current_verdict = 'D'
207        self.assertEqual(utils.getReturningData(self.student),(2005, 100))
208        return
209
210    def test_set_payment_details(self):
211        utils = getUtility(IStudentsUtils)
212
213        error, payment = utils.setPaymentDetails('schoolfee',self.student)
214        self.assertEqual(payment, None)
215        self.assertEqual(error, u'Amount could not be determined.')
216
217        IWorkflowState(self.student).setState('cleared')
218        self.assertEqual(local_nonlocal(self.student), 'non-local')
219        self.assertEqual(arts_science(self.student), 'science')
220        self.assertEqual(pt_ft(self.student), 'ft')
221
222        error, payment = utils.setPaymentDetails('schoolfee',self.student)
223        self.assertEqual(error,
224            'Book and pay for accommodation first before making'
225            ' school fee payments.')
226        # We add a fake maint. payment ticket to meet the condition
227        maint_payment = createObject('waeup.StudentOnlinePayment')
228        self.student['payments']['any_key'] = maint_payment
229        maint_payment.p_category = 'hostel_maintenance'
230        maint_payment.p_state = 'paid'
231        maint_payment.p_session = 2004
232        error, payment = utils.setPaymentDetails('schoolfee',self.student)
233        self.assertEqual(payment.p_level, 100)
234        self.assertEqual(payment.p_session, 2004)
235        self.assertEqual(payment.amount_auth, 53900.0)
236        self.assertEqual(payment.p_item, u'CERT1')
237        self.assertEqual(error, None)
238
239        IWorkflowState(self.student).setState('returning')
240        error, payment = utils.setPaymentDetails('schoolfee',self.student)
241        self.assertEqual('Session configuration object is not available.', error)
242        configuration = createObject('waeup.SessionConfiguration')
243        configuration.academic_session = 2005
244        self.app['configuration'].addSessionConfiguration(configuration)
245        error, payment = utils.setPaymentDetails('schoolfee',self.student)
246        self.assertEqual(payment.p_level, 200)
247        self.assertEqual(payment.p_session, 2005)
248        self.assertEqual(payment.amount_auth, 32090.0)
249        self.assertEqual(payment.p_item, u'CERT1')
250        self.assertEqual(error, None)
251
252        error, payment = utils.setPaymentDetails('clearance',self.student)
253        self.assertEqual(payment.p_level, 100)
254        self.assertEqual(payment.p_session, 2004)
255        self.assertEqual(payment.amount_auth, 120.0)
256        self.assertEqual(payment.p_item, u'CERT1')
257        self.assertEqual(error, None)
258
259        error, payment = utils.setPaymentDetails('carryover1',self.student)
260        self.assertEqual(payment.p_level, 100)
261        self.assertEqual(payment.p_session, 2004)
262        self.assertEqual(payment.amount_auth, 6000.0)
263        self.assertEqual(payment.p_item, u'1 CarryOver')
264        self.assertEqual(payment.p_category, 'schoolfee')
265        self.assertEqual(error, None)
266
267        error, payment = utils.setPaymentDetails('carryover2',self.student)
268        self.assertEqual(payment.p_level, 100)
269        self.assertEqual(payment.p_session, 2004)
270        self.assertEqual(payment.amount_auth, 7000.0)
271        self.assertEqual(payment.p_item, u'2 CarryOvers')
272        self.assertEqual(payment.p_category, 'schoolfee')
273        self.assertEqual(error, None)
274
275        error, payment = utils.setPaymentDetails('carryover3',self.student)
276        self.assertEqual(payment.p_level, 100)
277        self.assertEqual(payment.p_session, 2004)
278        self.assertEqual(payment.amount_auth, 8000.0)
279        self.assertEqual(payment.p_item, u'3 CarryOvers')
280        self.assertEqual(payment.p_category, 'schoolfee')
281        self.assertEqual(error, None)
282
283        error, payment = utils.setPaymentDetails('hostel_maintenance',self.student)
284        self.assertEqual(payment.p_level, 100)
285        self.assertEqual(payment.p_session, 2004)
286        self.assertEqual(payment.amount_auth, 876.0)
287        self.assertEqual(payment.p_item, u'My bed coordinates')
288        self.assertEqual(error, None)
289
290        self.app['hostels']['hall-1'].maint_fee = 0.0
291        error, payment = utils.setPaymentDetails('hostel_maintenance',self.student)
292        self.assertEqual(payment.p_level, 100)
293        self.assertEqual(payment.p_session, 2004)
294        self.assertEqual(payment.amount_auth, 180.0)
295        self.assertEqual(payment.p_item, u'My bed coordinates')
296        self.assertEqual(error, None)
297
298        error, payment = utils.setPaymentDetails('bed_allocation',self.student)
299        self.assertEqual(payment.p_level, 100)
300        self.assertEqual(payment.p_session, 2004)
301        self.assertEqual(payment.amount_auth, 150.0)
302        self.assertEqual(payment.p_item, u'')
303        self.assertEqual(error, None)
304
305        error, payment = utils.setPaymentDetails('certificate',self.student)
306        self.assertEqual(payment.p_level, 100)
307        self.assertEqual(payment.p_session, 2004)
308        self.assertEqual(payment.amount_auth, 444.0)
309        self.assertEqual(payment.p_item, u'')
310        self.assertEqual(payment.p_category, 'certificate')
311        self.assertEqual(error, None)
312
313        error, payment = utils.setPaymentDetails('schoolfee',self.student, 2004, 100)
314        self.assertEqual(error, u'Previous session payment not yet implemented.')
315        return
316
317    def test_student_start_clearance(self):
318        self.browser.open(self.login_path)
319        self.browser.getControl(name="form.login").value = self.student_id
320        self.browser.getControl(name="form.password").value = 'spwd'
321        self.browser.getControl("Login").click()
322
323        IWorkflowInfo(self.student).fireTransition('admit')
324        self.browser.open(self.student_path + '/change_portrait')
325        image = open(SAMPLE_IMAGE, 'rb')
326        ctrl = self.browser.getControl(name='passportuploadedit')
327        file_ctrl = ctrl.mech_control
328        file_ctrl.add_file(image, filename='my_photo.jpg')
329        self.browser.getControl(
330            name='upload_passportuploadedit').click()
331        self.browser.open(self.student_path + '/start_clearance')
332        # In KwaraPoly the students can just start clearance without entering
333        # an activation code.
334        self.browser.getControl("Start clearance now").click()
335        self.assertMatches('...Clearance process has been started...',
336                           self.browser.contents)
337
338    def test_change_passport(self):
339        self.browser.open(self.login_path)
340        self.browser.getControl(name="form.login").value = self.student_id
341        self.browser.getControl(name="form.password").value = 'spwd'
342        self.browser.getControl("Login").click()
343
344        IWorkflowState(self.student).setState('cleared')
345        self.browser.open(self.student_path + '/change_portrait')
346        image = open(SAMPLE_IMAGE, 'rb')
347        ctrl = self.browser.getControl(name='passportuploadedit')
348        file_ctrl = ctrl.mech_control
349        file_ctrl.add_file(image, filename='my_photo.jpg')
350        self.browser.getControl(
351            name='upload_passportuploadedit').click()
352
353
354    def test_student_accommodation(self):
355        del self.student['accommodation']['2004']
356        # Login
357        self.browser.open(self.login_path)
358        self.browser.getControl(name="form.login").value = self.student_id
359        self.browser.getControl(name="form.password").value = 'spwd'
360        self.browser.getControl("Login").click()
361
362        # Students can book accommodation without AC ...
363        self.browser.open(self.acco_path)
364        IWorkflowInfo(self.student).fireTransition('admit')
365        self.browser.getLink("Book accommodation").click()
366        self.assertFalse('Activation Code:' in self.browser.contents)
367        self.browser.getControl("Create bed ticket").click()
368        # Bed is randomly selected but, since there is only
369        # one bed for this student, we know that
370        self.assertMatches('...Hall 1, Block A, Room 101, Bed A...',
371                           self.browser.contents)
372        return
373
374    def test_no_beds_for_itch(self):
375        self.app['faculties']['fac1'].code = 'ITCH'
376        del self.student['accommodation']['2004']
377        # Login
378        self.browser.open(self.login_path)
379        self.browser.getControl(name="form.login").value = self.student_id
380        self.browser.getControl(name="form.password").value = 'spwd'
381        self.browser.getControl("Login").click()
382
383        self.browser.open(self.acco_path)
384        IWorkflowInfo(self.student).fireTransition('admit')
385        self.browser.getLink("Book accommodation").click()
386        self.browser.getControl("Create bed ticket").click()
387        self.assertTrue('There is no free bed in your category itch_male_fr.' in
388                           self.browser.contents)
389        return
390
391    def test_admission_pdf_slips(self):
392        # Login
393        self.browser.open(self.login_path)
394        self.browser.getControl(name="form.login").value = self.student_id
395        self.browser.getControl(name="form.password").value = 'spwd'
396        self.browser.getControl("Login").click()
397        # admission slip
398        IWorkflowState(self.student).setState('school fee paid')
399        self.browser.open(self.student_path)
400        self.browser.getLink("Download admission letter").click()
401        self.assertEqual(self.browser.headers['Status'], '200 Ok')
402        self.assertEqual(self.browser.headers['Content-Type'],
403                         'application/pdf')
404        path = os.path.join(samples_dir(), 'admission_slip.pdf')
405        open(path, 'wb').write(self.browser.contents)
406        print "Sample PDF admission_slip_slip.pdf written to %s" % path
407        self.browser.open(self.student_path)
408        self.assertRaises(
409            LinkNotFoundError, self.browser.getLink, 'Download admission notification')
410        self.browser.open(self.student_path + '/admission_notification.pdf')
411        self.assertTrue('Not allowed' in self.browser.contents)
412        # admission notification
413        IWorkflowState(self.student).setState('cleared')
414        self.browser.open(self.student_path)
415        self.browser.getLink("Download admission notification").click()
416        self.assertEqual(self.browser.headers['Status'], '200 Ok')
417        self.assertEqual(self.browser.headers['Content-Type'],
418                         'application/pdf')
419        path = os.path.join(samples_dir(), 'admission_notification.pdf')
420        open(path, 'wb').write(self.browser.contents)
421        print "Sample PDF admission_notification.pdf written to %s" % path
422        self.browser.open(self.student_path)
423        self.assertRaises(
424            LinkNotFoundError, self.browser.getLink, 'Download admission letter')
425        self.browser.open(self.student_path + '/admission_slip.pdf')
426        self.assertTrue('Not allowed' in self.browser.contents)
427        return
428
429    def test_registration_pdf_slips(self):
430        # Student cant login if their password is not set
431        IWorkflowState(self.student).setState('school fee paid')
432        self.browser.open(self.login_path)
433        self.browser.getControl(name="form.login").value = self.student_id
434        self.browser.getControl(name="form.password").value = 'spwd'
435        self.browser.getControl("Login").click()
436        self.browser.getLink("Study Course").click()
437        self.browser.getLink("Add course list").click()
438        self.assertMatches('...Add current level 100 (Year 1)...',
439                           self.browser.contents)
440        self.browser.getControl("Create course list now").click()
441        # A level with one course ticket was created
442        self.browser.getLink("100").click()
443        self.browser.getLink("Download course registration slip").click()
444        self.assertEqual(self.browser.headers['Status'], '200 Ok')
445        self.assertEqual(self.browser.headers['Content-Type'],
446                         'application/pdf')
447        path = os.path.join(samples_dir(), 'course_registration_slip.pdf')
448        open(path, 'wb').write(self.browser.contents)
449        print "Sample PDF course_registration_slip.pdf written to %s" % path
450
451        self.browser.open(self.student_path)
452        self.browser.getLink("Download registration form").click()
453        self.assertEqual(self.browser.headers['Status'], '200 Ok')
454        self.assertEqual(self.browser.headers['Content-Type'],
455                         'application/pdf')
456        path = os.path.join(samples_dir(), 'registration_slip.pdf')
457        open(path, 'wb').write(self.browser.contents)
458        print "Sample PDF registration_form.pdf written to %s" % path
459
460        return
Note: See TracBrowser for help on using the repository browser.