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

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

Add pdf registration form.

  • Property svn:keywords set to Id
File size: 19.9 KB
Line 
1## $Id: test_browser.py 10695 2013-11-04 16:22:35Z 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    def test_manage_payments(self):
89        # Add missing configuration data
90        self.app['configuration']['2004'].gown_fee = 150.0
91        self.app['configuration']['2004'].transfer_fee = 90.0
92        self.app['configuration']['2004'].clearance_fee = 120.0
93        self.app['configuration']['2004'].booking_fee = 150.0
94        self.app['configuration']['2004'].maint_fee = 180.0
95
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
181    def test_student_payments(self):
182        # Login
183        IWorkflowState(self.student).setState('returning')
184        self.browser.open(self.login_path)
185        self.browser.getControl(name="form.login").value = self.student_id
186        self.browser.getControl(name="form.password").value = 'spwd'
187        self.browser.getControl("Login").click()
188        self.browser.open(self.student_path + '/payments')
189        self.assertTrue(
190          'Add current session payment ticket' in self.browser.contents)
191        self.assertFalse(
192          'Add previous session payment ticket' in self.browser.contents)
193        return
194
195    def test_get_returning_data(self):
196        # Student is in level 100, session 2004 with verdict A
197        utils = getUtility(IStudentsUtils)
198        self.assertEqual(utils.getReturningData(self.student),(2005, 200))
199        self.student['studycourse'].current_verdict = 'C'
200        self.assertEqual(utils.getReturningData(self.student),(2005, 110))
201        self.student['studycourse'].current_verdict = 'D'
202        self.assertEqual(utils.getReturningData(self.student),(2005, 100))
203        return
204
205    def test_set_payment_details(self):
206        self.app['configuration']['2004'].gown_fee = 150.0
207        self.app['configuration']['2004'].transfer_fee = 90.0
208        self.app['configuration']['2004'].booking_fee = 150.0
209        self.app['configuration']['2004'].maint_fee = 180.0
210        self.app['configuration']['2004'].clearance_fee = 120.0
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('schoolfee',self.student, 2004, 100)
306        self.assertEqual(error, u'Previous session payment not yet implemented.')
307        return
308
309    def test_student_start_clearance(self):
310        self.browser.open(self.login_path)
311        self.browser.getControl(name="form.login").value = self.student_id
312        self.browser.getControl(name="form.password").value = 'spwd'
313        self.browser.getControl("Login").click()
314
315        IWorkflowInfo(self.student).fireTransition('admit')
316        self.browser.open(self.student_path + '/change_portrait')
317        image = open(SAMPLE_IMAGE, 'rb')
318        ctrl = self.browser.getControl(name='passportuploadedit')
319        file_ctrl = ctrl.mech_control
320        file_ctrl.add_file(image, filename='my_photo.jpg')
321        self.browser.getControl(
322            name='upload_passportuploadedit').click()
323        self.browser.open(self.student_path + '/start_clearance')
324        # In Okene the students can just start clearance without entering
325        # an activation code.
326        self.browser.getControl("Start clearance now").click()
327        self.assertMatches('...Clearance process has been started...',
328                           self.browser.contents)
329
330    def test_student_accommodation(self):
331        del self.student['accommodation']['2004']
332        # Login
333        self.browser.open(self.login_path)
334        self.browser.getControl(name="form.login").value = self.student_id
335        self.browser.getControl(name="form.password").value = 'spwd'
336        self.browser.getControl("Login").click()
337
338        # Students can book accommodation without AC ...
339        self.browser.open(self.acco_path)
340        IWorkflowInfo(self.student).fireTransition('admit')
341        self.browser.getLink("Book accommodation").click()
342        self.assertFalse('Activation Code:' in self.browser.contents)
343        self.browser.getControl("Create bed ticket").click()
344        # Bed is randomly selected but, since there is only
345        # one bed for this student, we know that
346        self.assertMatches('...Hall 1, Block A, Room 101, Bed A...',
347                           self.browser.contents)
348        return
349
350    def test_admission_pdf_slips(self):
351        # Login
352        self.browser.open(self.login_path)
353        self.browser.getControl(name="form.login").value = self.student_id
354        self.browser.getControl(name="form.password").value = 'spwd'
355        self.browser.getControl("Login").click()
356        # admission slip
357        IWorkflowState(self.student).setState('school fee paid')
358        self.browser.open(self.student_path)
359        self.browser.getLink("Download admission letter").click()
360        self.assertEqual(self.browser.headers['Status'], '200 Ok')
361        self.assertEqual(self.browser.headers['Content-Type'],
362                         'application/pdf')
363        path = os.path.join(samples_dir(), 'admission_slip.pdf')
364        open(path, 'wb').write(self.browser.contents)
365        print "Sample PDF admission_slip_slip.pdf written to %s" % path
366        self.browser.open(self.student_path)
367        self.assertRaises(
368            LinkNotFoundError, self.browser.getLink, 'Download admission notification')
369        self.browser.open(self.student_path + '/admission_notification.pdf')
370        self.assertTrue('Not allowed' in self.browser.contents)
371        # admission notification
372        IWorkflowState(self.student).setState('cleared')
373        self.browser.open(self.student_path)
374        self.browser.getLink("Download admission notification").click()
375        self.assertEqual(self.browser.headers['Status'], '200 Ok')
376        self.assertEqual(self.browser.headers['Content-Type'],
377                         'application/pdf')
378        path = os.path.join(samples_dir(), 'admission_notification.pdf')
379        open(path, 'wb').write(self.browser.contents)
380        print "Sample PDF admission_notification.pdf written to %s" % path
381        self.browser.open(self.student_path)
382        self.assertRaises(
383            LinkNotFoundError, self.browser.getLink, 'Download admission letter')
384        self.browser.open(self.student_path + '/admission_slip.pdf')
385        self.assertTrue('Not allowed' in self.browser.contents)
386        return
387
388    def test_registration_pdf_slips(self):
389        # Student cant login if their password is not set
390        IWorkflowState(self.student).setState('school fee paid')
391        self.browser.open(self.login_path)
392        self.browser.getControl(name="form.login").value = self.student_id
393        self.browser.getControl(name="form.password").value = 'spwd'
394        self.browser.getControl("Login").click()
395        self.browser.getLink("Study Course").click()
396        self.browser.getLink("Add course list").click()
397        self.assertMatches('...Add current level 100 (Year 1)...',
398                           self.browser.contents)
399        self.browser.getControl("Create course list now").click()
400        # A level with one course ticket was created
401        self.browser.getLink("100").click()
402        self.browser.getLink("Download course registration slip").click()
403        self.assertEqual(self.browser.headers['Status'], '200 Ok')
404        self.assertEqual(self.browser.headers['Content-Type'],
405                         'application/pdf')
406        path = os.path.join(samples_dir(), 'course_registration_slip.pdf')
407        open(path, 'wb').write(self.browser.contents)
408        print "Sample PDF course_registration_slip.pdf written to %s" % path
409
410        self.browser.open(self.student_path)
411        self.browser.getLink("Download registration form").click()
412        self.assertEqual(self.browser.headers['Status'], '200 Ok')
413        self.assertEqual(self.browser.headers['Content-Type'],
414                         'application/pdf')
415        path = os.path.join(samples_dir(), 'registration_form.pdf')
416        open(path, 'wb').write(self.browser.contents)
417        print "Sample PDF registration_form.pdf written to %s" % path
418
419        return
Note: See TracBrowser for help on using the repository browser.