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

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

Add test to check if AppCatCertificateSource? is really used to validate course1 and course2 values.

  • Property svn:keywords set to Id
File size: 19.1 KB
Line 
1## $Id: tests.py 8727 2012-06-15 06:18:42Z 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.assertMatches('...<td>Password:</td>...',
258            self.browser.contents)
259        # The new applicant can be found in the catalog via the email address
260        cat = getUtility(ICatalog, name='applicants_catalog')
261        results = list(
262            cat.searchResults(email=('xx@yy.zz', 'xx@yy.zz')))
263        applicant = results[0]
264        self.assertEqual(applicant.lastname,'Under')
265        # The applicant can be found in the catalog via the reg_number
266        results = list(
267            cat.searchResults(
268            reg_number=(applicant.reg_number, applicant.reg_number)))
269        self.assertEqual(applicant,results[0])
270        return
271
272    def test_create_ugstudent(self):
273        self.browser.addHeader('Authorization', 'Basic mgr:mgrpw')
274        manage_path = 'http://localhost/app/applicants/%s/%s/%s' % (
275            'app2011', self.ugapplicant.application_number, 'manage')
276        self.browser.open(manage_path)
277        self.fill_correct_values()
278        self.browser.getControl("Save").click()
279        IWorkflowState(self.ugapplicant).setState('admitted')
280        self.browser.getControl(name="form.course1").value = ['CERT1']
281        self.browser.getControl(name="form.course_admitted").value = ['CERT1']
282        self.browser.getControl("Save").click()
283        self.browser.getLink("Create student").click()
284        student_id =  self.app['students'].keys()[0]
285        self.assertTrue(('Student %s created' % student_id)
286            in self.browser.contents)
287        student = self.app['students'][student_id]
288        self.assertEqual(student.email, 'xx@yy.zz')
289        self.assertEqual(student.firstname, 'John')
290        self.assertEqual(student.lastname, 'Tester')
291        # Also additional attributes have been copied.
292        self.assertEqual(student.lga, 'foreigner')
293        self.assertEqual(student.nationality, 'NG')
294        return
295
296class ApplicantsExporterTest(ApplicantImportExportSetup):
297
298    layer = FunctionalLayer
299
300    def setUp(self):
301        super(ApplicantsExporterTest, self).setUp()
302        self.outfile = os.path.join(self.workdir, 'myoutput.csv')
303        self.cat = getUtility(ICatalog, name='applicants_catalog')
304        self.intids = getUtility(IIntIds)
305        return
306
307    def setup_applicant(self, applicant):
308        # set predictable values for `applicant`
309        applicant.reg_number = u'123456'
310        applicant.applicant_id = u'dp2011_654321'
311        applicant.firstname = u'Anna'
312        applicant.lastname = u'Tester'
313        applicant.middlename = u'M.'
314        applicant.date_of_birth = datetime.date(1981, 2, 4)
315        applicant.sex = 'f'
316        applicant.email = 'anna@sample.com'
317        applicant.phone = u'+234-123-12345'
318        applicant.course1 = self.certificate
319        applicant.course2 = self.certificate
320        applicant.course_admitted = self.certificate
321        applicant.notice = u'Some notice\nin lines.'
322        applicant.screening_score = 98
323        applicant.screening_venue = u'Exam Room'
324        applicant.screening_date = u'Saturday, 16th June 2012 2:00:00 PM'
325        applicant.password = 'any password'
326        return applicant
327
328    def test_export_reimport_all(self):
329        # we can export all applicants in a portal
330        # set values we can expect in export file
331        self.applicant = self.setup_applicant(self.applicant)
332        exporter = CustomApplicantsExporter()
333        exporter.export_all(self.app, self.outfile)
334        result = open(self.outfile, 'rb').read()
335        # The exported records do contain a real date in their
336        # history dict. We skip the date and split the comparison
337        # into two parts.
338        self.assertTrue(
339            'applicant_id,application_date,application_number,course1,course2,'
340            'course_admitted,date_of_birth,display_fullname,email,emp2_end,'
341            'emp2_position,emp2_reason,emp2_start,emp_end,emp_position,'
342            'emp_reason,emp_start,employer,employer2,firstname,history,'
343            'hq_degree,hq_disc,hq_matric_no,hq_school,hq_session,hq_type,'
344            'jamb_score,jamb_subjects,lastname,lga,locked,middlename,'
345            'nationality,notice,nysc_lga,'
346            'nysc_year,password,perm_address,phone,pp_school,presently_inst,'
347            'reg_number,screening_date,screening_score,screening_venue,sex,'
348            'state,student_id,'
349            'container_code'
350            in result)
351        self.assertTrue(
352            'Application initialized by system\'],,,,,,,,,Tester,,0,M.,,'
353            '"Some notice\nin lines.",,,any password,,+234-123-12345,,,'
354            '123456,"Saturday, 16th June 2012 2:00:00 PM",98,Exam Room,f,'
355            'initialized,,dp2011' in result)
356        # We can import the same file with 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            ['ignore_applicant_id','application_date','ignore_application_number',
363            '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','screening_date','screening_score','screening_venue','sex',
372            'state','student_id','container_code'],
373            mode='create')
374        num_succ, num_fail, finished_path, failed_path = result
375        self.assertEqual(num_succ,1)
376        self.assertEqual(num_fail,0)
377        # Now we ignore also the container_code and import the same file
378        # in update mode which means that ICustomApplicantUpdateByRegNo
379        # is used for field conversion. applicant_id must be ignored
380        # too since the previous import has notified the applicants_catalog
381        # so that the portal 'knows' that reg_number is in use.
382        processor = CustomApplicantProcessor()
383        result = processor.doImport(
384            self.outfile,
385            ['ignore_applicant_id','application_date','ignore_application_number',
386            'course1','course2',
387            'course_admitted','date_of_birth','ignore3','email','emp2_end',
388            'emp2_position','emp2_reason','emp2_start','emp_end','emp_position',
389            'emp_reason','emp_start','employer','employer2','firstname','ignore4',
390            'hq_degree','hq_disc','hq_matric_no','hq_school','hq_session','hq_type',
391            'jamb_score','jamb_subjects','lastname','lga','locked','middlename',
392            'nationality','notice','nysc_lga',
393            'nysc_year','password','perm_address','phone','pp_school','presently_inst',
394            'reg_number','screening_date','screening_score','screening_venue','sex',
395            'state','student_id','ignore_container_code'],
396            mode='update')
397        num_succ, num_fail, finished_path, failed_path = result
398        self.assertEqual(num_succ,1)
399        self.assertEqual(num_fail,0)
400        return
Note: See TracBrowser for help on using the repository browser.