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

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

Catch InvalidTransitionError? and flash error message.

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