source: main/kofacustom.nigeria/trunk/src/kofacustom/nigeria/applicants/tests/test_browser.py @ 10385

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

Add test for omitted screening venue and data.

  • Property svn:keywords set to Id
File size: 20.3 KB
Line 
1## $Id: test_browser.py 10379 2013-06-25 04:38:49Z 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 kofacustom.nigeria.testing import FunctionalLayer
42from kofacustom.nigeria.applicants.export import NigeriaApplicantsExporter
43from kofacustom.nigeria.applicants.batching import NigeriaApplicantProcessor
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("Add online payment ticket").click()
209        self.assertMatches('...Payment ticket created...',
210                           self.browser.contents)
211        self.assertMatches('...Amount Authorized...',
212                           self.browser.contents)
213        payment_id = self.ugapplicant.keys()[0]
214        payment = self.ugapplicant[payment_id]
215        self.assertEqual(payment.p_item,'This is the app2011 container')
216        self.assertEqual(payment.p_session,2011)
217        self.assertEqual(payment.p_category,'application')
218        self.assertEqual(payment.amount_auth, 200.0)
219
220        # PG applicants pay more
221        self.browser.open(self.pgapplicant_path)
222        self.browser.open(self.pgapplicant_path + '/manage')
223        self.assertEqual(self.browser.headers['Status'], '200 Ok')
224        self.fill_correct_values()
225        self.browser.getControl(name="form.course1").value = ['CERT2']
226        self.browser.getControl(name="form.reg_number").value = '2345'
227        self.browser.getControl(name="form.firstname").value = 'Anna'
228        self.browser.getControl("Save").click()
229        self.assertMatches('...Form has been saved...', self.browser.contents)
230        self.browser.getControl("Add online payment ticket").click()
231        self.assertMatches('...Payment ticket created...',
232                           self.browser.contents)
233        self.assertMatches('...Amount Authorized...',
234                           self.browser.contents)
235        payment_id = self.pgapplicant.keys()[0]
236        payment = self.pgapplicant[payment_id]
237        self.assertEqual(payment.p_item,'This is the pgft2011 container')
238        self.assertEqual(payment.p_session,2011)
239        self.assertEqual(payment.p_category,'application')
240        self.assertEqual(payment.amount_auth, 300.0)
241        return
242
243    def test_hide_screening_data(self):
244        self.browser.addHeader('Authorization', 'Basic mgr:mgrpw')
245        self.browser.open(self.ugapplicant_path + '/manage')
246        self.assertEqual(self.browser.headers['Status'], '200 Ok')
247        self.fill_correct_values()
248        self.browser.getControl(name="form.screening_venue").value = 'Mensa'
249        self.browser.getControl(name="form.screening_date").value = 'Easter'
250        self.browser.getControl(name="form.course1").value = ['CERT1']
251        self.browser.getControl("Save").click()
252        self.assertMatches('...Form has been saved...', self.browser.contents)
253        self.browser.getControl("Save").click()
254        # Venue and date are not shown
255        self.browser.open(self.ugapplicant_path)
256        self.assertFalse('Screening' in self.browser.contents)
257        IWorkflowState(self.ugapplicant).setState('paid')
258        # Venue and date are shown if applicant has paid
259        self.browser.open(self.ugapplicant_path)
260        self.assertTrue('Screening' in self.browser.contents)
261        return
262
263    def test_register_applicant_update(self):
264        # An applicant can register himself.
265        self.ugapplicant.reg_number = u'1234'
266        notify(grok.ObjectModifiedEvent(self.ugapplicant))
267        self.browser.open('http://localhost/app/applicants/app2011/')
268        self.browser.getLink("Register for application").click()
269        # Fill the edit form with suitable values
270        self.browser.getControl(name="form.firstname").value = 'Klaus'
271        self.browser.getControl(name="form.email").value = 'xx@yy.zz'
272        self.browser.getControl(name="form.reg_number").value = '1234'
273        self.browser.getControl("Send login credentials").click()
274        self.assertMatches('...Your registration was successful...',
275            self.browser.contents)
276        self.assertFalse('...<td>Password:</td>...' in self.browser.contents)
277        # The new applicant can be found in the catalog via the email address
278        cat = getUtility(ICatalog, name='applicants_catalog')
279        results = list(
280            cat.searchResults(email=('xx@yy.zz', 'xx@yy.zz')))
281        applicant = results[0]
282        self.assertEqual(applicant.lastname,'Under')
283        # The applicant can be found in the catalog via the reg_number
284        results = list(
285            cat.searchResults(
286            reg_number=(applicant.reg_number, applicant.reg_number)))
287        self.assertEqual(applicant,results[0])
288        return
289
290    def test_create_ugstudent(self):
291        self.browser.addHeader('Authorization', 'Basic mgr:mgrpw')
292        manage_path = 'http://localhost/app/applicants/%s/%s/%s' % (
293            'app2011', self.ugapplicant.application_number, 'manage')
294        self.browser.open(manage_path)
295        self.fill_correct_values()
296        self.browser.getControl("Save").click()
297        IWorkflowState(self.ugapplicant).setState('admitted')
298        self.browser.getControl(name="form.course1").value = ['CERT1']
299        self.browser.getControl(name="form.course_admitted").value = ['CERT1']
300        self.browser.getControl("Save").click()
301        self.browser.getLink("Create student").click()
302        student_id =  self.app['students'].keys()[0]
303        self.assertTrue(('Student %s created' % student_id)
304            in self.browser.contents)
305        student = self.app['students'][student_id]
306        self.assertEqual(student.email, 'xx@yy.zz')
307        self.assertEqual(student.firstname, 'John')
308        self.assertEqual(student.lastname, 'Tester')
309        # Also additional attributes have been copied.
310        self.assertEqual(student.lga, 'foreigner')
311        self.assertEqual(student.nationality, 'NG')
312        return
313
314class ApplicantsExporterTest(ApplicantImportExportSetup):
315
316    layer = FunctionalLayer
317
318    def setUp(self):
319        super(ApplicantsExporterTest, self).setUp()
320        self.outfile = os.path.join(self.workdir, 'myoutput.csv')
321        self.cat = getUtility(ICatalog, name='applicants_catalog')
322        self.intids = getUtility(IIntIds)
323        return
324
325    def setup_applicant(self, applicant):
326        # set predictable values for `applicant`
327        applicant.reg_number = u'123456'
328        applicant.applicant_id = u'dp2011_654321'
329        applicant.firstname = u'Anna'
330        applicant.lastname = u'Tester'
331        applicant.middlename = u'M.'
332        applicant.nationality = u'NG'
333        applicant.date_of_birth = datetime.date(1981, 2, 4)
334        applicant.sex = 'f'
335        applicant.email = 'anna@sample.com'
336        applicant.phone = u'+234-123-12345'
337        applicant.course1 = self.certificate
338        applicant.course2 = self.certificate
339        applicant.course_admitted = self.certificate
340        applicant.notice = u'Some notice\nin lines.'
341        applicant.screening_score = 98
342        applicant.screening_venue = u'Exam Room'
343        applicant.screening_date = u'Saturday, 16th June 2012 2:00:00 PM'
344        applicant.password = 'any password'
345        return applicant
346
347    def test_export_reimport_all(self):
348        # we can export all applicants in a portal
349        # set values we can expect in export file
350        self.applicant = self.setup_applicant(self.applicant)
351        exporter = NigeriaApplicantsExporter()
352        exporter.export_all(self.app, self.outfile)
353        result = open(self.outfile, 'rb').read()
354        self.assertMatches(result,
355            'aggregate,applicant_id,application_date,application_number,'
356            'course1,course2,course_admitted,date_of_birth,display_fullname,'
357            'email,emp2_end,emp2_position,emp2_reason,emp2_start,emp_end,'
358            'emp_position,emp_reason,emp_start,employer,employer2,'
359            'firstname,history,hq_degree,hq_disc,hq_matric_no,hq_school,'
360            'hq_session,hq_type,jamb_score,jamb_subjects,lastname,lga,'
361            'locked,middlename,nationality,notice,nysc_lga,nysc_year,'
362            'password,phone,pp_school,presently_inst,reg_number,'
363            'result_uploaded,screening_date,screening_score,'
364            'screening_venue,sex,state,student_id,suspended,container_code\r\n'
365            ',dp2011_654321,,654321,CERT1,CERT1,CERT1,1981-02-04#,'
366            'Anna M. Tester,anna@sample.com,,,,,,,,,,,Anna,'
367            '[u\'2012-10-28 21:27:52 WAT - Application initialized by system\']'
368            ',,,,,,,,,Tester,,0,M.,NG,"Some notice\nin lines.",,,'
369            'any password,+234-123-12345#,,,123456,,'
370            '"Saturday, 16th June 2012 2:00:00 PM",98,Exam Room,f,initialized,,'
371            '0,dp2011\r\n')
372        # We can import the same file if we ignore some columns.
373        # Since the applicants_catalog hasn't been notified, the same
374        # record with same reg_number can be imported twice.
375        processor = NigeriaApplicantProcessor()
376        result = processor.doImport(
377            self.outfile,
378            ['aggreagate','ignore_applicant_id','application_date',
379            'ignore_application_number','course1','course2',
380            'course_admitted','date_of_birth','ignore3','email','emp2_end',
381            'emp2_position','emp2_reason','emp2_start','emp_end','emp_position',
382            'emp_reason','emp_start','employer','employer2','firstname','ignore4',
383            'hq_degree','hq_disc','hq_matric_no','hq_school','hq_session','hq_type',
384            'jamb_score','jamb_subjects','lastname','lga','locked','middlename',
385            'nationality','notice','nysc_lga',
386            'nysc_year','password','phone','pp_school','presently_inst',
387            'reg_number','result_uploaded',
388            'screening_date','screening_score','screening_venue','sex',
389            'state','student_id','suspended','container_code'],
390            mode='create')
391        num_succ, num_fail, finished_path, failed_path = result
392        #content = open(failed_path).read()
393        self.assertEqual(num_succ,1)
394        self.assertEqual(num_fail,0)
395        # Now we ignore also the container_code and import the same file
396        # in update mode which means that INigeriaApplicantUpdateByRegNo
397        # is used for field conversion. applicant_id must be ignored
398        # too since the previous import has notified the applicants_catalog
399        # so that the portal 'knows' that reg_number is in use.
400        processor = NigeriaApplicantProcessor()
401        result = processor.doImport(
402            self.outfile,
403            ['aggregate','ignore_applicant_id','application_date',
404            'ignore_application_number','course1','course2',
405            'course_admitted','date_of_birth','ignore3','email','emp2_end',
406            'emp2_position','emp2_reason','emp2_start','emp_end','emp_position',
407            'emp_reason','emp_start','employer','employer2','firstname','ignore4',
408            'hq_degree','hq_disc','hq_matric_no','hq_school','hq_session','hq_type',
409            'jamb_score','jamb_subjects','lastname','lga','locked','middlename',
410            'nationality','notice','nysc_lga',
411            'nysc_year','password','phone','pp_school','presently_inst',
412            'reg_number','result_uploaded','screening_date','screening_score',
413            'screening_venue','sex',
414            'state','student_id','suspended','ignore_container_code'],
415            mode='update')
416        num_succ, num_fail, finished_path, failed_path = result
417        self.assertEqual(num_succ,1)
418        self.assertEqual(num_fail,0)
419        return
Note: See TracBrowser for help on using the repository browser.