source: main/waeup.uniben/trunk/src/waeup/uniben/applicants/tests.py @ 8833

Last change on this file since 8833 was 8804, checked in by Henrik Bettermann, 13 years ago

Adjust test.

  • Property svn:keywords set to Id
File size: 19.3 KB
Line 
1## $Id: tests.py 8804 2012-06-26 07:31:00Z henrik $
2##
3## Copyright (C) 2011 Uli Fouquet & Henrik Bettermann
4## This program is free software; you can redistribute it and/or modify
5## it under the terms of the GNU General Public License as published by
6## the Free Software Foundation; either version 2 of the License, or
7## (at your option) any later version.
8##
9## This program is distributed in the hope that it will be useful,
10## but WITHOUT ANY WARRANTY; without even the implied warranty of
11## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12## GNU General Public License for more details.
13##
14## You should have received a copy of the GNU General Public License
15## along with this program; if not, write to the Free Software
16## Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17##
18import os
19import shutil
20import tempfile
21import datetime
22import grok
23import pytz
24from zope.event import notify
25from zope.intid.interfaces import IIntIds
26from zope.interface.verify import verifyClass, verifyObject
27from zope.schema.interfaces import ConstraintNotSatisfied
28from zope.component.hooks import setSite, clearSite
29from zope.component import createObject, getUtility
30from zope.catalog.interfaces import ICatalog
31from zope.testbrowser.testing import Browser
32from hurry.workflow.interfaces import IWorkflowState
33from waeup.kofa.app import University
34from waeup.kofa.university.faculty import Faculty
35from waeup.kofa.university.department import Department
36from waeup.kofa.testing import FunctionalTestCase
37from waeup.kofa.configuration import SessionConfiguration
38from waeup.kofa.applicants.container import ApplicantsContainer
39from waeup.kofa.applicants.tests.test_batching import ApplicantImportExportSetup
40from waeup.kofa.interfaces import IBatchProcessor
41from waeup.uniben.testing import FunctionalLayer
42from waeup.uniben.applicants.export import CustomApplicantsExporter
43from waeup.uniben.applicants.batching import CustomApplicantProcessor
44
45
46class ApplicantUITest(FunctionalTestCase):
47    """Perform some browser tests.
48    """
49    layer = FunctionalLayer
50
51    def setUp(self):
52        super(ApplicantUITest, self).setUp()
53        # Setup a sample site for each test
54        app = University()
55        self.dc_root = tempfile.mkdtemp()
56        app['datacenter'].setStoragePath(self.dc_root)
57
58        # Prepopulate the ZODB...
59        self.getRootFolder()['app'] = app
60        # we add the site immediately after creation to the
61        # ZODB. Catalogs and other local utilities are not setup
62        # before that step.
63        self.app = self.getRootFolder()['app']
64        # Set site here. Some of the following setup code might need
65        # to access grok.getSite() and should get our new app then
66        setSite(app)
67
68        # Add an two different applicants containers
69        self.pgcontainer = ApplicantsContainer()
70        self.pgcontainer.code = u'pgft2011'
71        self.pgcontainer.prefix = u'pgft'
72        self.pgcontainer.application_category = u'pg_ft'
73        self.pgcontainer.year = 2011
74        self.pgcontainer.application_fee = 300.0
75        self.pgcontainer.title = u'This is the pgft2011 container'
76        self.app['applicants']['pgft2011'] = self.pgcontainer
77        self.ugcontainer = ApplicantsContainer()
78        self.ugcontainer.code = u'putme2011'
79        self.ugcontainer.prefix = u'putme'
80        self.ugcontainer.application_category = u'basic'
81        self.ugcontainer.year = 2011
82        self.ugcontainer.application_fee = 200.0
83        self.ugcontainer.title = u'This is the app2011 container'
84        self.app['applicants']['app2011'] = self.ugcontainer
85
86        self.ugcontainer.mode = 'update'
87        delta = datetime.timedelta(days=10)
88        self.ugcontainer.startdate = datetime.datetime.now(pytz.utc) - delta
89        self.ugcontainer.enddate = datetime.datetime.now(pytz.utc) + delta
90
91        # Populate university
92        self.certificate = createObject('waeup.Certificate')
93        self.certificate.code = 'CERT1'
94        self.certificate.application_category = 'basic'
95        self.certificate.start_level = 100
96        self.certificate.end_level = 500
97        self.certificate.study_mode = u'ug_ft'
98        self.app['faculties']['fac1'] = Faculty()
99        self.app['faculties']['fac1']['dep1'] = Department()
100        self.app['faculties']['fac1']['dep1'].certificates.addCertificate(
101            self.certificate)
102        self.certificate2 = createObject('waeup.Certificate')
103        self.certificate2.code = 'CERT2'
104        self.certificate2.application_category = 'pg_ft'
105        self.certificate2.start_level = 100
106        self.certificate2.end_level = 500
107        self.certificate.study_mode = u'pg_ft'
108        self.app['faculties']['fac1']['dep1'].certificates.addCertificate(
109            self.certificate2)
110
111        # Add (customized) applicants
112        pgapplicant = createObject(u'waeup.Applicant')
113        pgapplicant.firstname = u'Anna'
114        pgapplicant.lastname = u'Post'
115        self.app['applicants']['pgft2011'].addApplicant(pgapplicant)
116        self.pgapplication_number = pgapplicant.application_number
117        self.pgapplicant = self.app['applicants']['pgft2011'][
118            self.pgapplication_number]
119
120        ugapplicant = createObject(u'waeup.Applicant')
121        ugapplicant.firstname = u'Klaus'
122        ugapplicant.lastname = u'Under'
123        self.app['applicants']['app2011'].addApplicant(ugapplicant)
124        self.ugapplication_number = ugapplicant.application_number
125        self.ugapplicant = self.app['applicants']['app2011'][
126            self.ugapplication_number]
127        self.pgapplicant_path = ('http://localhost/app/applicants/pgft2011/%s'
128            % self.pgapplication_number)
129        self.ugapplicant_path = ('http://localhost/app/applicants/app2011/%s'
130            % self.ugapplication_number)
131
132        self.browser = Browser()
133        self.browser.handleErrors = False
134
135    def tearDown(self):
136        super(ApplicantUITest, self).tearDown()
137        shutil.rmtree(self.dc_root)
138        clearSite()
139        return
140
141    def fill_correct_values(self):
142        self.browser.getControl(name="form.reg_number").value = '1234'
143        self.browser.getControl(name="form.firstname").value = 'John'
144        self.browser.getControl(name="form.lastname").value = 'Tester'
145        self.browser.getControl(name="form.date_of_birth").value = '09/09/1988'
146        self.browser.getControl(name="form.lga").value = ['foreigner']
147        self.browser.getControl(name="form.nationality").value = ['NG']
148        self.browser.getControl(name="form.sex").value = ['m']
149        self.browser.getControl(name="form.email").value = 'xx@yy.zz'
150
151    def test_manage_and_view_applicant(self):
152        # Managers can manage pg applicants.
153        self.browser.addHeader('Authorization', 'Basic mgr:mgrpw')
154        # The IPGApplicant interface is really used in all pages.
155        self.browser.open(self.pgapplicant_path)
156        self.assertEqual(self.browser.headers['Status'], '200 Ok')
157        self.assertTrue('Employer' in self.browser.contents)
158        self.browser.open(self.pgapplicant_path + '/manage')
159        self.assertEqual(self.browser.headers['Status'], '200 Ok')
160        self.assertTrue('Employer' in self.browser.contents)
161        self.browser.open(self.pgapplicant_path + '/edit')
162        self.assertEqual(self.browser.headers['Status'], '200 Ok')
163        self.assertTrue('Employer' in self.browser.contents)
164        self.browser.open(self.pgapplicant_path + '/application_slip.pdf')
165        self.assertEqual(self.browser.headers['Status'], '200 Ok')
166        # If we view the applicant in the ug container,
167        # the employer field doesn't appear.
168        self.browser.open(self.ugapplicant_path)
169        self.assertEqual(self.browser.headers['Status'], '200 Ok')
170        self.assertFalse('Employer' in self.browser.contents)
171        self.browser.open(self.ugapplicant_path + '/manage')
172        self.assertEqual(self.browser.headers['Status'], '200 Ok')
173        # We can save the applicant.
174        self.fill_correct_values()
175        self.browser.getControl(name="form.course1").value = ['CERT1']
176        self.browser.getControl("Save").click()
177        self.assertMatches('...Form has been saved...', self.browser.contents)
178        self.assertFalse('Employer' in self.browser.contents)
179        self.browser.open(self.ugapplicant_path + '/edit')
180        self.assertEqual(self.browser.headers['Status'], '200 Ok')
181        self.assertFalse('Employer' in self.browser.contents)
182        self.browser.open(self.ugapplicant_path + '/application_slip.pdf')
183        self.assertEqual(self.browser.headers['Status'], '200 Ok')
184        return
185
186    def test_set_wrong_course1(self):
187        self.ugapplicant.course1 = self.certificate
188        self.assertRaises(
189            ConstraintNotSatisfied,
190            setattr, self.ugapplicant, 'course1', self.certificate2)
191        self.pgapplicant.course1 = self.certificate2
192        self.assertRaises(
193            ConstraintNotSatisfied,
194            setattr, self.pgapplicant, 'course1', self.certificate)
195        return
196
197    def test_application_payment(self):
198        self.browser.addHeader('Authorization', 'Basic mgr:mgrpw')
199
200        # UG (UTME) applicant
201        self.browser.open(self.ugapplicant_path)
202        self.browser.open(self.ugapplicant_path + '/manage')
203        self.assertEqual(self.browser.headers['Status'], '200 Ok')
204        self.fill_correct_values()
205        self.browser.getControl(name="form.course1").value = ['CERT1']
206        self.browser.getControl("Save").click()
207        self.assertMatches('...Form has been saved...', self.browser.contents)
208        self.browser.getControl("Save").click()
209        self.browser.getControl("Add online payment ticket").click()
210        self.assertMatches('...Payment ticket created...',
211                           self.browser.contents)
212        self.assertMatches('...Amount Authorized...',
213                           self.browser.contents)
214        payment_id = self.ugapplicant.keys()[0]
215        payment = self.ugapplicant[payment_id]
216        self.assertEqual(payment.p_item,'This is the app2011 container')
217        self.assertEqual(payment.p_session,2011)
218        self.assertEqual(payment.p_category,'application')
219        self.assertEqual(payment.amount_auth, 200.0)
220
221        # PG applicants pay more
222        self.browser.open(self.pgapplicant_path)
223        self.browser.open(self.pgapplicant_path + '/manage')
224        self.assertEqual(self.browser.headers['Status'], '200 Ok')
225        self.fill_correct_values()
226        self.browser.getControl(name="form.course1").value = ['CERT2']
227        self.browser.getControl(name="form.reg_number").value = '2345'
228        self.browser.getControl(name="form.firstname").value = 'Anna'
229        self.browser.getControl("Save").click()
230        self.assertMatches('...Form has been saved...', self.browser.contents)
231        self.browser.getControl("Add online payment ticket").click()
232        self.assertMatches('...Payment ticket created...',
233                           self.browser.contents)
234        self.assertMatches('...Amount Authorized...',
235                           self.browser.contents)
236        payment_id = self.pgapplicant.keys()[0]
237        payment = self.pgapplicant[payment_id]
238        self.assertEqual(payment.p_item,'This is the pgft2011 container')
239        self.assertEqual(payment.p_session,2011)
240        self.assertEqual(payment.p_category,'application')
241        self.assertEqual(payment.amount_auth, 300.0)
242        return
243
244    def test_register_applicant_update(self):
245        # An applicant can register himself.
246        self.ugapplicant.reg_number = u'1234'
247        notify(grok.ObjectModifiedEvent(self.ugapplicant))
248        self.browser.open('http://localhost/app/applicants/app2011/')
249        self.browser.getLink("Register for application").click()
250        # Fill the edit form with suitable values
251        self.browser.getControl(name="form.firstname").value = 'Klaus'
252        self.browser.getControl(name="form.email").value = 'xx@yy.zz'
253        self.browser.getControl(name="form.reg_number").value = '1234'
254        self.browser.getControl("Get login credentials").click()
255        self.assertMatches('...Your registration was successful...',
256            self.browser.contents)
257        self.assertFalse('...<td>Password:</td>...' in self.browser.contents)
258        # The new applicant can be found in the catalog via the email address
259        cat = getUtility(ICatalog, name='applicants_catalog')
260        results = list(
261            cat.searchResults(email=('xx@yy.zz', 'xx@yy.zz')))
262        applicant = results[0]
263        self.assertEqual(applicant.lastname,'Under')
264        # The applicant can be found in the catalog via the reg_number
265        results = list(
266            cat.searchResults(
267            reg_number=(applicant.reg_number, applicant.reg_number)))
268        self.assertEqual(applicant,results[0])
269        return
270
271    def test_create_ugstudent(self):
272        self.browser.addHeader('Authorization', 'Basic mgr:mgrpw')
273        manage_path = 'http://localhost/app/applicants/%s/%s/%s' % (
274            'app2011', self.ugapplicant.application_number, 'manage')
275        self.browser.open(manage_path)
276        self.fill_correct_values()
277        self.browser.getControl("Save").click()
278        IWorkflowState(self.ugapplicant).setState('admitted')
279        self.browser.getControl(name="form.course1").value = ['CERT1']
280        self.browser.getControl(name="form.course_admitted").value = ['CERT1']
281        self.browser.getControl("Save").click()
282        self.browser.getLink("Create student").click()
283        student_id =  self.app['students'].keys()[0]
284        self.assertTrue(('Student %s created' % student_id)
285            in self.browser.contents)
286        student = self.app['students'][student_id]
287        self.assertEqual(student.email, 'xx@yy.zz')
288        self.assertEqual(student.firstname, 'John')
289        self.assertEqual(student.lastname, 'Tester')
290        # Also additional attributes have been copied.
291        self.assertEqual(student.lga, 'foreigner')
292        self.assertEqual(student.nationality, 'NG')
293        return
294
295class ApplicantsExporterTest(ApplicantImportExportSetup):
296
297    layer = FunctionalLayer
298
299    def setUp(self):
300        super(ApplicantsExporterTest, self).setUp()
301        self.outfile = os.path.join(self.workdir, 'myoutput.csv')
302        self.cat = getUtility(ICatalog, name='applicants_catalog')
303        self.intids = getUtility(IIntIds)
304        return
305
306    def setup_applicant(self, applicant):
307        # set predictable values for `applicant`
308        applicant.reg_number = u'123456'
309        applicant.applicant_id = u'dp2011_654321'
310        applicant.firstname = u'Anna'
311        applicant.lastname = u'Tester'
312        applicant.middlename = u'M.'
313        applicant.date_of_birth = datetime.date(1981, 2, 4)
314        applicant.sex = 'f'
315        applicant.email = 'anna@sample.com'
316        applicant.phone = u'+234-123-12345'
317        applicant.course1 = self.certificate
318        applicant.course2 = self.certificate
319        applicant.course_admitted = self.certificate
320        applicant.notice = u'Some notice\nin lines.'
321        applicant.screening_score = 98
322        applicant.screening_venue = u'Exam Room'
323        applicant.screening_date = u'Saturday, 16th June 2012 2:00:00 PM'
324        applicant.password = 'any password'
325        return applicant
326
327    def test_export_reimport_all(self):
328        # we can export all applicants in a portal
329        # set values we can expect in export file
330        self.applicant = self.setup_applicant(self.applicant)
331        exporter = CustomApplicantsExporter()
332        exporter.export_all(self.app, self.outfile)
333        result = open(self.outfile, 'rb').read()
334        # The exported records do contain a real date in their
335        # history dict. We skip the date and split the comparison
336        # into two parts.
337        self.assertTrue(
338            'aggregate,applicant_id,application_date,application_number,course1,course2,'
339            'course_admitted,date_of_birth,display_fullname,email,emp2_end,'
340            'emp2_position,emp2_reason,emp2_start,emp_end,emp_position,'
341            'emp_reason,emp_start,employer,employer2,firstname,history,'
342            'hq_degree,hq_disc,hq_matric_no,hq_school,hq_session,hq_type,'
343            'jamb_score,jamb_subjects,lastname,lga,locked,middlename,'
344            'nationality,notice,nysc_lga,'
345            'nysc_year,password,perm_address,phone,pp_school,presently_inst,'
346            'reg_number,result_uploaded,screening_date,screening_score,screening_venue,sex,'
347            'state,student_id,'
348            'container_code'
349            in result)
350        self.assertTrue(
351            'Application initialized by system\'],,,,,,,,,Tester,,0,M.,,'
352            '"Some notice\nin lines.",,,any password,,+234-123-12345,,,'
353            '123456,,"Saturday, 16th June 2012 2:00:00 PM",98,Exam Room,f,'
354            'initialized,,dp2011'
355            in result)
356        # We can import the same file if we ignore some columns.
357        # Since the applicants_catalog hasn't been notified, the same
358        # record with same reg_number can be imported twice.
359        processor = CustomApplicantProcessor()
360        result = processor.doImport(
361            self.outfile,
362            ['aggreagate','ignore_applicant_id','application_date',
363            'ignore_application_number','course1','course2',
364            'course_admitted','date_of_birth','ignore3','email','emp2_end',
365            'emp2_position','emp2_reason','emp2_start','emp_end','emp_position',
366            'emp_reason','emp_start','employer','employer2','firstname','ignore4',
367            'hq_degree','hq_disc','hq_matric_no','hq_school','hq_session','hq_type',
368            'jamb_score','jamb_subjects','lastname','lga','locked','middlename',
369            'nationality','notice','nysc_lga',
370            'nysc_year','password','perm_address','phone','pp_school','presently_inst',
371            'reg_number','result_uploaded',
372            'screening_date','screening_score','screening_venue','sex',
373            'state','student_id','container_code'],
374            mode='create')
375        num_succ, num_fail, finished_path, failed_path = result
376        self.assertEqual(num_succ,1)
377        self.assertEqual(num_fail,0)
378        # Now we ignore also the container_code and import the same file
379        # in update mode which means that ICustomApplicantUpdateByRegNo
380        # is used for field conversion. applicant_id must be ignored
381        # too since the previous import has notified the applicants_catalog
382        # so that the portal 'knows' that reg_number is in use.
383        processor = CustomApplicantProcessor()
384        result = processor.doImport(
385            self.outfile,
386            ['aggregate','ignore_applicant_id','application_date',
387            'ignore_application_number','course1','course2',
388            'course_admitted','date_of_birth','ignore3','email','emp2_end',
389            'emp2_position','emp2_reason','emp2_start','emp_end','emp_position',
390            'emp_reason','emp_start','employer','employer2','firstname','ignore4',
391            'hq_degree','hq_disc','hq_matric_no','hq_school','hq_session','hq_type',
392            'jamb_score','jamb_subjects','lastname','lga','locked','middlename',
393            'nationality','notice','nysc_lga',
394            'nysc_year','password','perm_address','phone','pp_school','presently_inst',
395            'reg_number','result_uploaded','screening_date','screening_score',
396            'screening_venue','sex',
397            'state','student_id','ignore_container_code'],
398            mode='update')
399        num_succ, num_fail, finished_path, failed_path = result
400        self.assertEqual(num_succ,1)
401        self.assertEqual(num_fail,0)
402        return
Note: See TracBrowser for help on using the repository browser.