source: main/waeup.sirp/trunk/src/waeup/sirp/applicants/tests/test_browser.py @ 7260

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

Let's generate the applicant_id only when the applicant is added to its container to be compliant with the generic batch processor (importer).

  • Property svn:keywords set to Id
File size: 32.9 KB
Line 
1## $Id: test_browser.py 7260 2011-12-04 07:56:39Z 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##
18"""
19Test the applicant-related UI components.
20"""
21import shutil
22import tempfile
23from StringIO import StringIO
24from datetime import datetime, date, timedelta
25from mechanize import LinkNotFoundError
26from zope.component import createObject, getUtility
27from zope.component.hooks import setSite, clearSite
28from zope.security.interfaces import Unauthorized
29from zope.testbrowser.testing import Browser
30from hurry.workflow.interfaces import IWorkflowInfo, IWorkflowState
31from waeup.sirp.testing import FunctionalLayer, FunctionalTestCase
32from waeup.sirp.app import University
33from waeup.sirp.configuration import SessionConfiguration
34from waeup.sirp.applicants.container import ApplicantsContainer
35from waeup.sirp.applicants.applicant import Applicant
36from waeup.sirp.interfaces import (
37    IExtFileStore, IFileStoreNameChooser, IUserAccount)
38from waeup.sirp.university.faculty import Faculty
39from waeup.sirp.university.department import Department
40
41PH_LEN = 2059  # Length of placeholder file
42
43class ApplicantsFullSetup(FunctionalTestCase):
44    # A test case that only contains a setup and teardown
45    #
46    # Complete setup for applicants handlings is rather complex and
47    # requires lots of things created before we can start. This is a
48    # setup that does all this, creates a university, creates PINs,
49    # etc.  so that we do not have to bother with that in different
50    # test cases.
51
52    layer = FunctionalLayer
53
54    def setUp(self):
55        super(ApplicantsFullSetup, self).setUp()
56
57        # Setup a sample site for each test
58        app = University()
59        self.dc_root = tempfile.mkdtemp()
60        app['datacenter'].setStoragePath(self.dc_root)
61
62        # Prepopulate the ZODB...
63        self.getRootFolder()['app'] = app
64        # we add the site immediately after creation to the
65        # ZODB. Catalogs and other local utilities are not setup
66        # before that step.
67        self.app = self.getRootFolder()['app']
68        # Set site here. Some of the following setup code might need
69        # to access grok.getSite() and should get our new app then
70        setSite(app)
71
72        self.login_path = 'http://localhost/app/login'
73        self.root_path = 'http://localhost/app/applicants'
74        self.manage_root_path = self.root_path + '/@@manage'
75        self.add_container_path = self.root_path + '/@@add'
76        self.container_path = 'http://localhost/app/applicants/app2009'
77        self.manage_container_path = self.container_path + '/@@manage'
78
79        # Add an applicants container
80        applicantscontainer = ApplicantsContainer()
81        applicantscontainer.ac_prefix = 'APP'
82        applicantscontainer.code = u'app2009'
83        applicantscontainer.prefix = 'app'
84        applicantscontainer.year = 2009
85        applicantscontainer.application_category = 'basic'
86        delta = timedelta(days=10)
87        applicantscontainer.startdate = date.today() - delta
88        applicantscontainer.enddate = date.today() + delta
89        self.app['applicants']['app2009'] = applicantscontainer
90        self.applicantscontainer = self.app['applicants']['app2009']
91
92        # Populate university
93        certificate = createObject('waeup.Certificate')
94        certificate.code = 'CERT1'
95        certificate.application_category = 'basic'
96        self.certificate = certificate
97        self.app['faculties']['fac1'] = Faculty()
98        self.app['faculties']['fac1']['dep1'] = Department()
99        self.department = self.app['faculties']['fac1']['dep1']
100        self.app['faculties']['fac1']['dep1'].certificates.addCertificate(
101            certificate)
102
103        # Put the prepopulated site into test ZODB and prepare test
104        # browser
105        self.browser = Browser()
106        self.browser.handleErrors = False
107
108        # Create 5 access codes with prefix'FOO' and cost 9.99 each
109        pin_container = self.app['accesscodes']
110        pin_container.createBatch(
111            datetime.now(), 'some_userid', 'APP', 9.99, 5)
112        pins = pin_container[pin_container.keys()[0]].values()
113        self.pins = [x.representation for x in pins]
114        self.existing_pin = self.pins[0]
115        parts = self.existing_pin.split('-')[1:]
116        self.existing_series, self.existing_number = parts
117
118        # Add an applicant
119        self.applicant = Applicant()
120        app['applicants']['app2009'].addApplicant(self.applicant)
121        IUserAccount(
122            self.app['applicants']['app2009'][
123            self.applicant.application_number]).setPassword('apwd')
124        self.manage_path = 'http://localhost/app/applicants/%s/%s/%s' % (
125            'app2009', self.applicant.application_number, 'manage')
126        self.edit_path = 'http://localhost/app/applicants/%s/%s/%s' % (
127            'app2009', self.applicant.application_number, 'edit')
128        self.view_path = 'http://localhost/app/applicants/%s/%s' % (
129            'app2009', self.applicant.application_number)
130
131    def login(self):
132        # Perform an applicant login. This creates an applicant record.
133        #
134        # This helper also sets `self.applicant`, which is the
135        # applicant object created.
136        self.browser.open(self.login_path)
137        self.browser.getControl(name="form.login").value = self.applicant.applicant_id
138        self.browser.getControl(name="form.password").value = 'apwd'
139        self.browser.getControl("Login").click()
140
141    def fill_correct_values(self):
142        # Fill the edit form with suitable values
143        self.browser.getControl(name="form.firstname").value = 'John'
144        self.browser.getControl(name="form.lastname").value = 'Tester'
145        self.browser.getControl(name="form.course1").value = ['CERT1']
146        self.browser.getControl(name="form.date_of_birth").value = '09/09/1988'
147        self.browser.getControl(name="form.lga").value = ['foreigner']
148        self.browser.getControl(name="form.sex").value = ['m']
149        self.browser.getControl(name="form.email").value = 'xx@yy.zz'
150
151    def tearDown(self):
152        super(ApplicantsFullSetup, self).tearDown()
153        clearSite()
154        shutil.rmtree(self.dc_root)
155
156class ApplicantsRootUITests(ApplicantsFullSetup):
157    # Tests for ApplicantsRoot class
158
159    layer = FunctionalLayer
160
161    def test_anonymous_access(self):
162        # Anonymous users can access applicants root
163        self.browser.open(self.root_path)
164        self.assertEqual(self.browser.headers['Status'], '200 Ok')
165        self.assertFalse(
166            'Manage' in self.browser.contents)
167
168   
169    def test_anonymous_no_actions(self):
170        # Make sure anonymous users cannot access actions
171        self.browser.open(self.root_path)
172        self.assertRaises(
173            LookupError, self.browser.getControl, "Add local role")
174        # Manage screen neither linked nor accessible for anonymous
175        self.assertRaises(
176            LinkNotFoundError,
177            self.browser.getLink, 'Manage application section')
178        self.assertRaises(
179            Unauthorized, self.browser.open, self.manage_root_path)
180        # Add container screen not accessible for anonymous
181        self.assertRaises(
182            Unauthorized, self.browser.open, self.add_container_path)
183        return
184
185    def test_manage_access(self):
186        # Managers can access the manage pages of applicants root
187        self.browser.addHeader('Authorization', 'Basic mgr:mgrpw')
188        self.browser.open(self.root_path)
189        self.assertTrue('Manage application section' in self.browser.contents)
190        # There is a manage link
191        link = self.browser.getLink('Manage application section')
192        link.click()
193        self.assertEqual(self.browser.headers['Status'], '200 Ok')
194        self.assertEqual(self.browser.url, self.manage_root_path)
195
196    def test_manage_actions_access(self):
197        # Managers can access the action on manage screen
198        self.browser.addHeader('Authorization', 'Basic mgr:mgrpw')
199        self.browser.open(self.manage_root_path)
200        self.browser.getControl("Add local role").click()
201        self.assertTrue('No user selected' in self.browser.contents)
202        return
203
204    # We have no local roles yet
205    #def test_local_roles_add_delete(self):
206    #    # Managers can assign and delete local roles of applicants root
207    #    myusers = self.app['users']
208    #    myusers.addUser('bob', 'bobssecret')
209    #    self.browser.addHeader('Authorization', 'Basic mgr:mgrpw')
210    #    self.browser.open(self.manage_root_path)
211    #    self.browser.getControl(name="user").value = ['bob']
212    #    self.browser.getControl(name="local_role").value = [
213    #        'waeup.local.ApplicationsOfficer']
214    #    self.browser.getControl("Add local role").click()
215    #    self.assertTrue('<td>bob</td>' in self.browser.contents)
216    #    # Remove the role assigned
217    #    ctrl = self.browser.getControl(name='role_id')
218    #    ctrl.getControl(value='bob|waeup.ApplicationsOfficer').selected = True
219    #    self.browser.getControl("Remove selected local roles").click()
220    #    self.assertTrue('Successfully removed:' in self.browser.contents)
221    #    self.assertFalse('<td>bob</td>' in self.browser.contents)
222    #    return
223
224    def test_add_delete_container(self):
225        # Managers can add and delete applicants containers
226        self.browser.addHeader('Authorization', 'Basic mgr:mgrpw')
227        self.browser.open(self.manage_root_path)
228        self.browser.getControl("Cancel").click()
229        self.assertEqual(self.browser.url, self.root_path)
230        self.browser.open(self.manage_root_path)
231        self.browser.getControl("Add applicants container").click()
232        self.assertEqual(self.browser.headers['Status'], '200 Ok')
233        self.assertEqual(self.browser.url, self.add_container_path)
234        self.browser.getControl(name="form.prefix").value = ['app']
235        self.browser.getControl("Add applicants container").click()
236        self.assertTrue(
237            'There were errors' in self.browser.contents)
238        self.browser.getControl(name="form.prefix").value = ['app']
239        self.browser.getControl(name="form.year").value = ['2010']
240        self.browser.getControl(name="form.provider").value = [
241            'waeup.sirp.applicants.ApplicantsContainer']
242        self.browser.getControl(name="form.ac_prefix").value = ['APP']
243        self.browser.getControl(name="form.application_category").value = ['basic']
244        self.browser.getControl("Add applicants container").click()
245        self.assertTrue('Added:' in self.browser.contents)
246        self.browser.open(self.add_container_path)
247        self.browser.getControl("Cancel").click()
248        self.assertEqual(self.browser.url, self.manage_root_path + '#tab-1')
249        self.browser.open(self.add_container_path)
250        self.browser.getControl(name="form.prefix").value = ['app']
251        self.browser.getControl(name="form.year").value = ['2010']
252        self.browser.getControl(name="form.provider").value = [
253            'waeup.sirp.applicants.ApplicantsContainer']
254        self.browser.getControl(name="form.ac_prefix").value = ['APP']
255        self.browser.getControl(name="form.application_category").value = ['basic']
256        self.browser.getControl("Add applicants container").click()
257        self.assertTrue('exists already in the database' in self.browser.contents)
258        self.browser.open(self.manage_root_path)
259        ctrl = self.browser.getControl(name='val_id')
260        ctrl.getControl(value='app2010').selected = True
261        self.browser.getControl("Remove selected", index=0).click()
262        self.assertTrue('Successfully removed:' in self.browser.contents)
263        self.browser.open(self.add_container_path)
264        self.browser.getControl(name="form.prefix").value = ['app']
265        self.browser.getControl(name="form.year").value = ['2010']
266        self.browser.getControl(name="form.provider").value = [
267            'waeup.sirp.applicants.ApplicantsContainer']
268        self.browser.getControl(name="form.ac_prefix").value = ['APP']
269        self.browser.getControl(name="form.application_category").value = ['basic']
270        self.browser.getControl("Add applicants container").click()
271        del self.app['applicants']['app2010']
272        ctrl = self.browser.getControl(name='val_id')
273        ctrl.getControl(value='app2010').selected = True
274        self.browser.getControl("Remove selected", index=0).click()
275        self.assertMatches('...Could not delete...', self.browser.contents)
276        return
277
278    def test_add_delete_applicants(self):
279        # Managers can add and delete applicants
280        self.browser.addHeader('Authorization', 'Basic mgr:mgrpw')
281        self.add_applicant_path = self.container_path + '/addapplicant'
282        self.container_manage_path = self.container_path + '/@@manage'
283        self.browser.open(self.container_manage_path)
284        self.browser.getControl("Add applicant").click()
285        self.assertEqual(self.browser.headers['Status'], '200 Ok')
286        self.assertEqual(self.browser.url, self.add_applicant_path)
287        self.browser.getControl(name="form.firstname").value = 'Alois'
288        self.browser.getControl(name="form.middlenames").value = 'Kofi'
289        self.browser.getControl(name="form.lastname").value = 'Bettermann'
290        self.browser.getControl(name="form.email").value = 'xx@yy.zz'
291        self.browser.getControl("Create application record").click()
292        self.assertTrue('Application initialized' in self.browser.contents)
293        self.browser.open(self.container_manage_path)
294        self.assertEqual(self.browser.headers['Status'], '200 Ok')
295        ctrl = self.browser.getControl(name='val_id')
296        value = ctrl.options[0]
297        ctrl.getControl(value=value).selected = True
298        self.browser.getControl("Remove selected", index=0).click()
299        self.assertTrue('Successfully removed:' in self.browser.contents)
300        self.browser.open(self.add_applicant_path)
301        self.browser.getControl(name="form.firstname").value = 'Albert'
302        self.browser.getControl(name="form.lastname").value = 'Einstein'
303        self.browser.getControl(name="form.email").value = 'xx@yy.zz'
304        self.browser.getControl("Create application record").click()
305        self.assertTrue('Application initialized' in self.browser.contents)
306        return
307
308    def test_manage_and_view_applicant(self):
309        # Managers can manage applicants
310        self.browser.addHeader('Authorization', 'Basic mgr:mgrpw')
311        self.slip_path = self.view_path + '/application_slip.pdf'
312        self.browser.open(self.manage_path)
313        self.assertEqual(self.browser.headers['Status'], '200 Ok')
314        self.fill_correct_values()
315        # Fire transition
316        self.browser.getControl(name="transition").value = ['start']
317        self.browser.getControl("Save").click()
318        self.assertMatches('...Form has been saved...', self.browser.contents)
319        self.assertMatches('...Application started by zope.mgr...', self.browser.contents)
320        self.browser.open(self.view_path)
321        self.assertEqual(self.browser.headers['Status'], '200 Ok')
322        # Change course_admitted
323        self.browser.open(self.manage_path)
324        self.browser.getControl(name="form.course_admitted").value = []
325        self.browser.getControl("Save").click()
326        self.assertMatches('...Form has been saved...', self.browser.contents)
327        # Change password
328        self.browser.getControl(name="password").value = 'secret'
329        self.browser.getControl(name="control_password").value = 'secre'
330        self.browser.getControl("Save").click()
331        self.assertMatches('...Passwords do not match...', self.browser.contents)
332        self.browser.getControl(name="password").value = 'secret'
333        self.browser.getControl(name="control_password").value = 'secret'
334        self.browser.getControl("Save").click()
335        self.assertMatches('...Form has been saved...', self.browser.contents)
336        # Open pdf slip
337        self.browser.open(self.slip_path)
338        self.assertEqual(self.browser.headers['Status'], '200 Ok')
339        self.assertEqual(self.browser.headers['Content-Type'], 'application/pdf')
340        return
341
342    def test_passport_edit_view(self):
343        # We get a default image after login
344        self.browser.open(self.login_path)
345        self.login()
346        self.browser.open(self.browser.url + '/passport.jpg')
347        self.assertEqual(self.browser.headers['status'], '200 Ok')
348        self.assertEqual(self.browser.headers['content-type'], 'image/jpeg')
349        self.assertTrue('JFIF' in self.browser.contents)
350        self.assertEqual(
351            self.browser.headers['content-length'], str(PH_LEN))
352
353    def test_edit_applicant(self):
354        # Applicants can edit their record
355        self.browser.open(self.login_path)
356        self.login()
357        self.browser.open(self.edit_path)
358        self.assertTrue(self.browser.url != self.login_path)
359        self.assertEqual(self.browser.headers['Status'], '200 Ok')
360        self.fill_correct_values()
361        self.browser.getControl("Save").click()
362        self.assertMatches('...Form has been saved...', self.browser.contents)
363        return
364
365class ApplicantsContainerUITests(ApplicantsFullSetup):
366    # Tests for ApplicantsContainer class views and pages
367
368    layer = FunctionalLayer
369
370    def test_anonymous_access(self):
371        # Anonymous users can access applicants containers
372        self.browser.open(self.container_path)
373        self.assertEqual(self.browser.headers['Status'], '200 Ok')
374        self.assertFalse(
375            'Manage' in self.browser.contents)
376        return
377
378    def test_manage_access(self):
379        # Managers can access the manage pages of applicants
380        # containers and can perform actions
381        self.browser.addHeader('Authorization', 'Basic mgr:mgrpw')
382        self.browser.open(self.manage_container_path)
383        self.assertEqual(self.browser.headers['Status'], '200 Ok')
384        self.assertEqual(self.browser.url, self.manage_container_path)
385        self.browser.getControl("Save").click()
386        self.assertTrue('Data saved' in self.browser.contents)
387        self.browser.getControl("Remove selected", index=0).click()
388        self.assertTrue('No applicant selected' in self.browser.contents)
389        self.browser.getControl("Add local role").click()
390        self.assertTrue('No user selected' in self.browser.contents)
391        self.browser.getControl("Cancel", index=0).click()
392        self.assertEqual(self.browser.url, self.container_path)
393        return
394
395class ApplicantsPassportTests(ApplicantsFullSetup):
396    # Tests for uploading/browsing the passport image of appplicants
397
398    layer = FunctionalLayer
399
400    def image_url(self, filename):
401        return self.edit_path.replace('edit', filename)
402
403    def test_after_login_default_browsable(self):
404        # After login we see the placeholder image in the edit view
405        #import pdb; pdb.set_trace()
406        self.login()
407        self.assertEqual(self.browser.url, self.view_path)
408        self.browser.open(self.edit_path)
409        # There is a correct <img> link included
410        self.assertTrue(
411              '<img src="passport.jpg" />' in self.browser.contents)
412        # Browsing the link shows a real image
413        self.browser.open(self.image_url('passport.jpg'))
414        self.assertEqual(
415            self.browser.headers['content-type'], 'image/jpeg')
416        self.assertEqual(len(self.browser.contents), PH_LEN)
417
418    def test_after_submit_default_browsable(self):
419        # After submitting an applicant form the default image is
420        # still visible
421        self.login()
422        self.browser.open(self.edit_path)
423        self.browser.getControl("Save").click() # submit form
424        # There is a correct <img> link included
425        self.assertTrue(
426            '<img src="passport.jpg" />' in self.browser.contents)
427        # Browsing the link shows a real image
428        self.browser.open(self.image_url('passport.jpg'))
429        self.assertEqual(
430            self.browser.headers['content-type'], 'image/jpeg')
431        self.assertEqual(len(self.browser.contents), PH_LEN)
432
433    def test_uploaded_image_respects_file_size_restriction(self):
434        # When we upload an image that is too big ( > 10 KB) we will
435        # get an error message
436        self.login()
437        self.browser.open(self.edit_path)
438        # Create a pseudo image file and select it to be uploaded in form
439        photo_content = 'A' * 1024 * 21  # A string of 21 KB size
440        pseudo_image = StringIO(photo_content)
441        ctrl = self.browser.getControl(name='form.passport')
442        file_ctrl = ctrl.mech_control
443        file_ctrl.add_file(pseudo_image, filename='myphoto.jpg')
444        self.browser.getControl("Save").click() # submit form
445        # There is a correct <img> link included
446        self.assertTrue(
447            '<img src="passport.jpg" />' in self.browser.contents)
448        # We get a warning message
449        self.assertTrue(
450            'Uploaded image is too big' in self.browser.contents)
451        # Browsing the image gives us the default image, not the
452        # uploaded one.
453        self.browser.open(self.image_url('passport.jpg'))
454        self.assertEqual(
455            self.browser.headers['content-type'], 'image/jpeg')
456        self.assertEqual(len(self.browser.contents), PH_LEN)
457        # There is really no file stored for the applicant
458        img = getUtility(IExtFileStore).getFile(
459            IFileStoreNameChooser(self.applicant).chooseName())
460        self.assertTrue(img is None)
461
462    def test_uploaded_image_browsable_w_errors(self):
463        # We can upload a different image and browse it after submit,
464        # even if there are still errors in the form
465        self.login()
466        self.browser.open(self.edit_path)
467        # Create a pseudo image file and select it to be uploaded in form
468        photo_content = 'I pretend to be a graphics file'
469        pseudo_image = StringIO(photo_content)
470        ctrl = self.browser.getControl(name='form.passport')
471        file_ctrl = ctrl.mech_control
472        file_ctrl.add_file(pseudo_image, filename='myphoto.jpg')
473        self.browser.getControl("Save").click() # submit form
474        # There is a correct <img> link included
475        self.assertTrue(
476            '<img src="passport.jpg" />' in self.browser.contents)
477        # Browsing the link shows a real image
478        self.browser.open(self.image_url('passport.jpg'))
479        self.assertEqual(
480            self.browser.headers['content-type'], 'image/jpeg')
481        self.assertEqual(self.browser.contents, photo_content)
482
483    def test_uploaded_image_stored_in_imagestorage_w_errors(self):
484        # After uploading a new passport pic the file is correctly
485        # stored in an imagestorage
486        self.login()
487        self.browser.open(self.edit_path)
488        # Create a pseudo image file and select it to be uploaded in form
489        pseudo_image = StringIO('I pretend to be a graphics file')
490        ctrl = self.browser.getControl(name='form.passport')
491        file_ctrl = ctrl.mech_control
492        file_ctrl.add_file(pseudo_image, filename='myphoto.jpg')
493        self.browser.getControl("Save").click() # submit form
494        storage = getUtility(IExtFileStore)
495        file_id = IFileStoreNameChooser(self.applicant).chooseName()
496        pseudo_image.seek(0) # reset our file data source
497        self.assertEqual(
498            storage.getFile(file_id).read(), pseudo_image.read())
499        return
500
501    def test_uploaded_image_browsable_wo_errors(self):
502        # We can upload a different image and browse it after submit,
503        # if there are no errors in form
504        self.login()
505        self.browser.open(self.edit_path)
506        self.fill_correct_values() # fill other fields with correct values
507        # Create a pseudo image file and select it to be uploaded in form
508        pseudo_image = StringIO('I pretend to be a graphics file')
509        ctrl = self.browser.getControl(name='form.passport')
510        file_ctrl = ctrl.mech_control
511        file_ctrl.add_file(pseudo_image, filename='myphoto.jpg')
512        self.browser.getControl("Save").click() # submit form
513        # There is a correct <img> link included
514        self.assertTrue(
515            '<img src="passport.jpg" />' in self.browser.contents)
516        # Browsing the link shows a real image
517        self.browser.open(self.image_url('passport.jpg'))
518        self.assertEqual(
519            self.browser.headers['content-type'], 'image/jpeg')
520        self.assertEqual(len(self.browser.contents), 31)
521
522    def test_uploaded_image_stored_in_imagestorage_wo_errors(self):
523        # After uploading a new passport pic the file is correctly
524        # stored in an imagestorage if form contains no errors
525        self.login()
526        self.browser.open(self.edit_path)
527        self.fill_correct_values() # fill other fields with correct values
528        # Create a pseudo image file and select it to be uploaded in form
529        pseudo_image = StringIO('I pretend to be a graphics file')
530        ctrl = self.browser.getControl(name='form.passport')
531        file_ctrl = ctrl.mech_control
532        file_ctrl.add_file(pseudo_image, filename='myphoto.jpg')
533        self.browser.getControl("Save").click() # submit form
534        storage = getUtility(IExtFileStore)
535        file_id = IFileStoreNameChooser(self.applicant).chooseName()
536        # The stored image can be fetched
537        fd = storage.getFile(file_id)
538        file_len = len(fd.read())
539        self.assertEqual(file_len, 31)
540
541    def test_uploaded_images_equal(self):
542        # Make sure uploaded images do really differ if we eject a
543        # change notfication (and do not if we don't)
544        self.login()
545        self.browser.open(self.edit_path)
546        self.fill_correct_values() # fill other fields with correct values
547        self.browser.getControl("Save").click() # submit form
548        # Now go on as an officer
549        self.browser.addHeader('Authorization', 'Basic mgr:mgrpw')
550        self.browser.open(self.manage_path)
551
552        # Create a pseudo image file and select it to be uploaded in form
553        pseudo_image = StringIO('I pretend to be a graphics file')
554        ctrl = self.browser.getControl(name='form.passport')
555        file_ctrl = ctrl.mech_control
556        file_ctrl.add_file(pseudo_image, filename='myphoto.jpg')
557        file_id = IFileStoreNameChooser(self.applicant).chooseName()
558        setSite(self.app)
559        passport0 = getUtility(IExtFileStore).getFile(file_id)
560        self.browser.getControl("Save").click() # submit form with changed pic
561        passport1 = getUtility(IExtFileStore).getFile(file_id).read()
562        self.browser.getControl("Save").click() # submit form w/o changes
563        passport2 = getUtility(IExtFileStore).getFile(file_id).read()
564        self.assertTrue(passport0 is None)
565        self.assertTrue(passport0 != passport1)
566        self.assertTrue(passport1 == passport2)
567        return
568
569    def test_pay_acceptance_fee(self):
570        self.login()
571        self.browser.open(self.edit_path)
572        # Payment tickets can't be created before the form has been validated
573        self.browser.getControl("Add online payment ticket").click()
574        self.assertTrue('Required input is missing' in self.browser.contents)
575        self.fill_correct_values()
576        # We have to savethe form otherwise the filled fields will be cleared
577        # after adding an online payment, because adding an online payment
578        # requires a filled form but does not save it
579        self.browser.getControl("Save").click()
580        self.browser.getControl("Add online payment ticket").click()
581        # Session object missing
582        self.assertTrue(
583            'Session configuration object is not available'
584            in self.browser.contents)
585        configuration = SessionConfiguration()
586        configuration.academic_session = 2009
587        configuration.acceptance_fee = 200
588        self.app['configuration'].addSessionConfiguration(configuration)
589        self.browser.open(self.edit_path)
590        self.fill_correct_values()
591        self.browser.getControl("Add online payment ticket").click()
592        self.assertMatches('...Payment ticket created...', self.browser.contents)
593        # Payment ticket can be removed if they haven't received a valid callback
594        ctrl = self.browser.getControl(name='val_id')
595        value = ctrl.options[0]
596        ctrl.getControl(value=value).selected = True
597        self.browser.getControl("Remove selected", index=0).click()
598        self.assertMatches('...Successfully removed...', self.browser.contents)
599        # We will try the callback request view
600        self.browser.getControl("Add online payment ticket").click()
601        ctrl = self.browser.getControl(name='val_id')
602        value = ctrl.options[0]
603        self.browser.getLink(value).click()
604        self.assertMatches('...Amount Authorized...',
605                           self.browser.contents)
606        payment_url = self.browser.url
607        # The pdf payment receipt can't yet be opened
608        self.browser.open(payment_url + '/payment_receipt.pdf')
609        self.assertMatches('...Ticket not yet paid...',
610                           self.browser.contents)
611        # Request callback
612        self.browser.open(payment_url)
613        self.browser.getLink("Request callback").click()
614        self.assertMatches('...Valid callback received...',
615                          self.browser.contents)
616        # Callback can't be applied twice
617        self.browser.open(payment_url + '/callback')
618        self.assertMatches('...This ticket has already been paid...',
619                          self.browser.contents)
620        # The payment receipt can be downloaded now
621        self.browser.open(payment_url)
622        self.browser.getLink("Download payment receipt").click()
623        self.assertEqual(self.browser.headers['Status'], '200 Ok')
624        self.assertEqual(self.browser.headers['Content-Type'], 'application/pdf')
625        # Applicant is is in state 'paid'
626        self.browser.open(self.view_path)
627        self.assertMatches('...paid...',
628                           self.browser.contents)
629        state = IWorkflowState(self.applicant).getState()
630        self.assertTrue(state == 'paid')
631
632    def test_final_submit(self):
633        # Make sure that a correctly filled form with passport picture
634        # can be submitted (only) after payment
635        self.login()
636        self.browser.getLink("Edit application record").click()
637        self.assertFalse('Final Submit' in self.browser.contents)
638        IWorkflowInfo(self.applicant).fireTransition('pay')
639        self.browser.open(self.edit_path)
640        self.assertTrue('Final Submit' in self.browser.contents)
641        self.fill_correct_values() # fill other fields with correct values
642        self.browser.getControl("Final Submit").click()
643        # We forgot to upload a passport picture
644        self.assertTrue(
645            'No passport picture uploaded' in self.browser.contents)
646        # Create a pseudo image file and select it to be uploaded in form
647        pseudo_image = StringIO('I pretend to be a graphics file')
648        ctrl = self.browser.getControl(name='form.passport')
649        file_ctrl = ctrl.mech_control
650        file_ctrl.add_file(pseudo_image, filename='myphoto.jpg')
651        self.browser.getControl("Final Submit").click() # (finally) submit form
652        # The picture has been uploaded but the form cannot be submitted
653        # since the passport confirmation box was not ticked
654        self.assertTrue(
655            'Passport picture confirmation box not ticked' in self.browser.contents)
656        self.browser.getControl(name="confirm_passport").value = True
657        self.browser.getControl("Final Submit").click()
658        self.assertTrue(
659            '... submitted ...' in self.browser.contents)
660        self.browser.goBack(count=1)
661        self.browser.getControl("Save").click()
662        self.assertTrue(
663            'The requested form is locked' in self.browser.contents)
664        self.browser.goBack(count=1)
665        #import pdb; pdb.set_trace()
666        self.browser.getControl("Final Submit").click()
667        self.assertTrue(
668            'The requested form is locked' in self.browser.contents)
669        return
670
671    def test_locking(self):
672        # Make sure that locked forms can't be submitted
673        self.login()
674        self.browser.open(self.edit_path)
675        self.fill_correct_values() # fill other fields with correct values
676        # Create a pseudo image file and select it to be uploaded in form
677        pseudo_image = StringIO('I pretend to be a graphics file')
678        ctrl = self.browser.getControl(name='form.passport')
679        file_ctrl = ctrl.mech_control
680        file_ctrl.add_file(pseudo_image, filename='myphoto.jpg')
681        self.browser.getControl("Save").click()
682        # Now we lock the form
683        self.applicant.locked = True
684        self.browser.open(self.edit_path)
685        self.assertEqual(self.browser.headers['Status'], '200 Ok')
686        #print self.browser.contents
687        self.assertTrue(
688            'The requested form is locked' in self.browser.contents)
689        return
Note: See TracBrowser for help on using the repository browser.