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

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

This test fails because fire_transition does not return False if the AC doesn't exist.

File size: 33.5 KB
Line 
1##
2## test_browser.py
3## Login : <uli@pu.smp.net>
4## Started on  Tue Mar 29 11:31:11 2011 Uli Fouquet
5## $Id$
6##
7## Copyright (C) 2011 Uli Fouquet & Henrik Bettermann
8## This program is free software; you can redistribute it and/or modify
9## it under the terms of the GNU General Public License as published by
10## the Free Software Foundation; either version 2 of the License, or
11## (at your option) any later version.
12##
13## This program is distributed in the hope that it will be useful,
14## but WITHOUT ANY WARRANTY; without even the implied warranty of
15## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16## GNU General Public License for more details.
17##
18## You should have received a copy of the GNU General Public License
19## along with this program; if not, write to the Free Software
20## Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
21##
22"""
23Test the applicant-related UI components.
24"""
25import shutil
26import tempfile
27from StringIO import StringIO
28from datetime import datetime
29from zope.component import createObject
30from zope.component.hooks import setSite, clearSite
31from zope.testbrowser.testing import Browser
32from waeup.sirp.testing import FunctionalLayer, FunctionalTestCase
33from waeup.sirp.app import University
34from waeup.sirp.applicants.container import ApplicantsContainer
35from waeup.sirp.applicants.applicants import Applicant
36from waeup.sirp.university.faculty import Faculty
37from waeup.sirp.university.department import Department
38
39PH_LEN = 2059  # Length of placeholder file
40
41class ApplicantsFullSetup(FunctionalTestCase):
42    # A test case that only contains a setup and teardown
43    #
44    # Complete setup for applicants handlings is rather complex and
45    # requires lots of things created before we can start. This is a
46    # setup that does all this, creates a university, creates PINs,
47    # etc.  so that we do not have to bother with that in different
48    # test cases.
49
50    layer = FunctionalLayer
51
52    def setUp(self):
53        super(ApplicantsFullSetup, self).setUp()
54
55        # Setup a sample site for each test
56        app = University()
57        self.dc_root = tempfile.mkdtemp()
58        app['datacenter'].setStoragePath(self.dc_root)
59
60        # Prepopulate the ZODB...
61        self.getRootFolder()['app'] = app
62        # we add the site immediately after creation to the
63        # ZODB. Catalogs and other local utilities are not setup
64        # before that step.
65        self.app = self.getRootFolder()['app']
66        # Set site here. Some of the following setup code might need
67        # to access grok.getSite() and should get our new app then
68        setSite(app)
69
70        self.root_path = 'http://localhost/app/applicants'
71        self.container_path = 'http://localhost/app/applicants/app2009'
72
73        # Add an applicants container
74        applicantscontainer = ApplicantsContainer()
75        applicantscontainer.ac_prefix = 'APP'
76        applicantscontainer.prefix = 'app'
77        applicantscontainer.year = 2009
78        applicantscontainer.application_category = 'basic'
79        self.app['applicants']['app2009'] = applicantscontainer
80
81        # Populate university
82        certificate = createObject('waeup.Certificate')
83        certificate.code = 'CERT1'
84        certificate.application_category = 'basic'
85        self.app['faculties']['fac1'] = Faculty()
86        self.app['faculties']['fac1']['dep1'] = Department()
87        self.app['faculties']['fac1']['dep1'].certificates.addCertificate(
88            certificate)
89
90        # Put the prepopulated site into test ZODB and prepare test
91        # browser
92        self.browser = Browser()
93        self.browser.handleErrors = False
94
95        # Create 5 access codes with prefix'FOO' and cost 9.99 each
96        pin_container = self.app['accesscodes']
97        pin_container.createBatch(
98            datetime.now(), 'some_userid', 'APP', 9.99, 5)
99        pins = pin_container[pin_container.keys()[0]].values()
100        self.pins = [x.representation for x in pins]
101        self.existing_pin = self.pins[0]
102        parts = self.existing_pin.split('-')[1:]
103        self.existing_series, self.existing_number = parts
104
105        # Add an applicant
106        self.applicant = Applicant()
107        self.pin_applicant = unicode(self.pins[1])
108        self.applicant.access_code = self.pin_applicant
109        app['applicants']['app2009'][self.pin_applicant] = self.applicant
110
111        # Add an officer
112        myusers = self.app['users']
113        myusers.addUser('bob', 'bobssecret')
114        return
115
116    def tearDown(self):
117        super(ApplicantsFullSetup, self).tearDown()
118        clearSite()
119        shutil.rmtree(self.dc_root)
120        #import pdb; pdb.set_trace()
121
122class ApplicantsUITests(ApplicantsFullSetup):
123    # Tests for ApplicantsRoot class
124
125    layer = FunctionalLayer
126
127    def test_anonymous_access(self):
128        # Anonymous users can access applicants root and applicants containers
129        self.browser.open(self.root_path)
130        self.assertEqual(self.browser.headers['Status'], '200 Ok')
131        self.assertFalse(
132            'Manage' in self.browser.contents)
133        self.browser.open(self.container_path)
134        self.assertEqual(self.browser.headers['Status'], '200 Ok')
135        self.assertFalse(
136            'Manage' in self.browser.contents)
137        return
138
139    def test_manage_cert_access(self):
140        # Managers can access CERT1
141        cert_path = 'http://localhost/app/faculties/fac1/dep1/certificates/CERT1'
142        self.browser.addHeader('Authorization', 'Basic mgr:mgrpw')
143        self.browser.open(cert_path)
144        self.assertEqual(self.browser.headers['Status'], '200 Ok')
145
146    def test_manage_access(self):
147        # Managers can access the manage pages of applicants root and
148        # applicants containers and can perform actions
149        self.browser.addHeader('Authorization', 'Basic mgr:mgrpw')
150        self.browser.open(self.root_path)
151        self.assertTrue(
152            'Manage application section' in self.browser.contents)
153        self.manage_root_path = self.root_path + '/@@manage'
154        self.manage_container_path = self.container_path + '/@@manage'
155        self.browser.open(self.manage_root_path)
156        self.assertEqual(self.browser.headers['Status'], '200 Ok')
157        self.assertEqual(self.browser.url, self.manage_root_path)
158        self.browser.open(self.manage_container_path)
159        self.assertEqual(self.browser.headers['Status'], '200 Ok')
160        self.assertEqual(self.browser.url, self.manage_container_path)
161        self.browser.getControl("Save").click()
162        self.assertTrue(
163            'Data saved' in self.browser.contents)
164        self.browser.getControl("Remove selected", index=0).click()
165        self.assertTrue(
166            'No applicant selected' in self.browser.contents)
167        self.browser.getControl("Cancel", index=0).click()
168        self.assertEqual(self.browser.url, self.container_path)
169        return
170
171    def test_add_delete_container(self):
172        # Managers can add and delete applicants containers
173        self.manage_root_path = self.root_path + '/@@manage'
174        self.add_container_path = self.root_path + '/@@add'
175        self.browser.addHeader('Authorization', 'Basic mgr:mgrpw')
176        self.browser.open(self.manage_root_path)
177        self.browser.getControl("Cancel").click()
178        self.assertEqual(self.browser.url, self.root_path)
179        self.browser.open(self.manage_root_path)
180        self.browser.getControl("Add applicants container").click()
181        self.assertEqual(self.browser.headers['Status'], '200 Ok')
182        self.assertEqual(self.browser.url, self.add_container_path)
183        self.browser.getControl(name="form.prefix").value = ['app']
184        self.browser.getControl("Add applicants container").click()
185        self.assertTrue(
186            'There were errors' in self.browser.contents)
187        self.browser.getControl(name="form.prefix").value = ['app']
188        self.browser.getControl(name="form.year").value = ['2010']
189        self.browser.getControl(name="form.provider").value = [
190            'waeup.sirp.applicants.ApplicantsContainer']
191        self.browser.getControl(name="form.ac_prefix").value = ['APP']
192        self.browser.getControl(name="form.application_category").value = ['basic']
193        self.browser.getControl("Add applicants container").click()
194        self.assertTrue('Added:' in self.browser.contents)
195        self.browser.open(self.add_container_path)
196        self.browser.getControl(name="form.prefix").value = ['app']
197        self.browser.getControl(name="form.year").value = ['2010']
198        self.browser.getControl(name="form.provider").value = [
199            'waeup.sirp.applicants.ApplicantsContainer']
200        self.browser.getControl(name="form.ac_prefix").value = ['APP']
201        self.browser.getControl(name="form.application_category").value = ['basic']
202        self.browser.getControl("Add applicants container").click()
203        self.assertTrue('exists already in the database' in self.browser.contents)
204        self.browser.open(self.manage_root_path)
205        ctrl = self.browser.getControl(name='val_id')
206        ctrl.getControl(value='app2010').selected = True
207        self.browser.getControl("Remove selected", index=0).click()
208        self.assertTrue('Successfully removed:' in self.browser.contents)
209        return
210
211    def test_add_delete_applicants(self):
212        # Managers can add and delete applicants
213        self.browser.addHeader('Authorization', 'Basic mgr:mgrpw')
214        self.add_applicant_path = self.container_path + '/addapplicant'
215        self.container_manage_path = self.container_path + '/@@manage'
216        self.browser.open(self.add_applicant_path)
217        self.assertEqual(self.browser.headers['Status'], '200 Ok')
218        self.assertEqual(self.browser.url, self.add_applicant_path)
219        self.browser.getControl(name="form.ac_series").value = self.existing_series
220        self.browser.getControl(name="form.ac_number").value = self.existing_number
221        self.browser.getControl("Create application record").click()
222        self.assertTrue('Application initialized' in self.browser.contents)
223        self.browser.open(self.add_applicant_path)
224        self.browser.getControl(name="form.ac_series").value = '123'
225        self.browser.getControl(name="form.ac_number").value = '456'
226        self.browser.getControl("Create application record").click()
227        self.assertTrue('is not a valid access code' in self.browser.contents)
228        self.browser.open(self.container_manage_path)
229        self.assertEqual(self.browser.headers['Status'], '200 Ok')
230        ctrl = self.browser.getControl(name='val_id')
231        ctrl.getControl(value=self.existing_pin).selected = True
232        self.browser.getControl("Remove selected", index=0).click()
233        self.assertTrue('Successfully removed:' in self.browser.contents)
234        return
235
236    def test_manage_and_view_applicant(self):
237        # Managers can manage applicants
238        self.browser.addHeader('Authorization', 'Basic mgr:mgrpw')
239        self.applicant_path = 'http://localhost/app/applicants/app2009/%s' % self.pin_applicant
240        self.applicant_view_path = self.applicant_path + '/index'
241        self.applicant_manage_path = self.applicant_path + '/edit_full'
242        self.applicant_slip_path = self.applicant_path + '/application_slip.pdf'
243        self.browser.open(self.applicant_manage_path)
244        self.assertEqual(self.browser.headers['Status'], '200 Ok')
245        self.browser.getControl(name="form.firstname").value = 'John'
246        self.browser.getControl(name="form.lastname").value = 'Tester'
247        self.browser.getControl(name="form.course1").value = ['CERT1']
248        self.browser.getControl(name="form.course_admitted").value = ['CERT1']
249        self.browser.getControl(name="form.date_of_birth").value = '09/09/1988'
250        self.browser.getControl(name="form.lga").value = ['foreigner']
251        self.browser.getControl(name="form.sex").value = ['m']
252        self.browser.getControl("Save").click()
253        self.assertMatches('...Form has been saved...', self.browser.contents)
254        self.browser.open(self.applicant_view_path)
255        self.assertEqual(self.browser.headers['Status'], '200 Ok')
256        self.browser.open(self.applicant_slip_path)
257        self.assertEqual(self.browser.headers['Status'], '200 Ok')
258        self.assertEqual(self.browser.headers['Content-Type'], 'application/pdf')
259        return
260
261    def test_view_applicant(self):
262        # Applicants can login and view their application
263        self.login_path = 'http://localhost/app/applicants/app2009/login'
264        self.browser.open(self.login_path)
265        pin = self.pins[2]
266        parts = pin.split('-')[1:]
267        existing_series, existing_number = parts
268        ac_series = self.browser.getControl(name="form.ac_series")
269        ac_series.value = existing_series
270        ac_number = self.browser.getControl(name="form.ac_number")
271        ac_number.value = existing_number
272        self.browser.getControl(name="SUBMIT").click()
273        self.assertTrue(self.browser.url != self.login_path)
274        self.assertEqual(self.browser.headers['Status'], '200 Ok')
275        return
276
277    def test_passport_edit_view(self):
278        # We get a default image after login
279        login_path = 'http://localhost/app/applicants/app2009/login'
280        self.browser.open(login_path)
281        pin = self.pins[2]
282        parts = pin.split('-')[1:]
283        existing_series, existing_number = parts
284        ac_series = self.browser.getControl(name="form.ac_series")
285        ac_series.value = existing_series
286        ac_number = self.browser.getControl(name="form.ac_number")
287        ac_number.value = existing_number
288        self.browser.getControl(name="SUBMIT").click()
289
290        pin = self.pins[2]
291        appl = self.getRootFolder()['app']['applicants']['app2009']
292        appl = appl[pin]
293        passp = appl.passport
294        #import pdb; pdb.set_trace()
295        passp_len = len(passp.file.read())
296        self.assertEqual(passp_len, PH_LEN)
297
298
299        #image_url = "%s/%s" % (self.browser.url, 'placeholder.jpg')
300        image_url = "%s/%s" % (self.browser.url, 'passport.jpg')
301        #self.browser.open(image_url)
302        self.browser.open('passport.jpg')
303        self.assertEqual(self.browser.headers['status'], '200 Ok')
304        self.assertEqual(self.browser.headers['content-type'], 'image/jpeg')
305
306
307        self.assertTrue('JFIF' in self.browser.contents)
308        self.assertEqual(
309            self.browser.headers['content-length'], str(PH_LEN))
310
311
312    def test_edit_applicant(self):
313        # Applicants can edit their record
314        self.login_path = 'http://localhost/app/applicants/app2009/login'
315        self.browser.open(self.login_path)
316        pin = self.pins[2]
317        parts = pin.split('-')[1:]
318        existing_series, existing_number = parts
319        ac_series = self.browser.getControl(name="form.ac_series")
320        ac_series.value = existing_series
321        ac_number = self.browser.getControl(name="form.ac_number")
322        ac_number.value = existing_number
323        self.browser.getControl(name="SUBMIT").click()
324        self.assertTrue(self.browser.url != self.login_path)
325        self.assertEqual(self.browser.headers['Status'], '200 Ok')
326        self.browser.getControl(name="form.firstname").value = 'John'
327        self.browser.getControl(name="form.lastname").value = 'Tester'
328        self.browser.getControl(name="form.course1").value = ['CERT1']
329        self.browser.getControl(name="form.date_of_birth").value = '09/09/1988'
330        self.browser.getControl(name="form.lga").value = ['foreigner']
331        self.browser.getControl(name="form.sex").value = ['m']
332        self.browser.getControl("Save").click()
333        self.assertMatches('...Form has been saved...', self.browser.contents)
334        return
335
336class LoginTest(FunctionalTestCase):
337    # Here we check login view of applicants containers.
338    #
339    # Tests in here do only cover login attempts without any PINs
340    # created before.
341
342    layer = FunctionalLayer
343
344    def setUp(self):
345        super(LoginTest, self).setUp()
346
347        # Setup a sample site for each test
348        app = University()
349        self.dc_root = tempfile.mkdtemp()
350        app['datacenter'].setStoragePath(self.dc_root)
351        self.login_path = 'http://localhost/app/applicants/testapplicants/login'
352
353        # Add an applicants container where we can login (or not)
354        applicantscontainer = ApplicantsContainer()
355        applicantscontainer.ac_prefix = 'APP'
356        app['applicants']['testapplicants'] = applicantscontainer
357
358        # Put the prepopulated site into test ZODB and prepare test
359        # browser
360        self.getRootFolder()['app'] = app
361        self.browser = Browser()
362        self.browser.handleErrors = False
363
364    def tearDown(self):
365        super(LoginTest, self).tearDown()
366        shutil.rmtree(self.dc_root)
367
368    def test_anonymous_access(self):
369        # Anonymous users can access a login page
370        self.browser.open(self.login_path)
371        self.assertEqual(self.browser.headers['Status'], '200 Ok')
372        return
373
374    def test_anonymous_invalid_creds(self):
375        # Anonymous users giving invalid credentials stay at the page
376        self.browser.open(self.login_path)
377        # We do not give credentials but send the form as-is
378        submit = self.browser.getControl(name='SUBMIT')
379        submit.click()
380        # We are still at the same page...
381        self.assertEqual(self.browser.url, self.login_path)
382        self.assertEqual(self.browser.headers['Status'], '200 Ok')
383        return
384
385    def test_anonymous_invalid_creds_warning(self):
386        # Entering wrong credentials will yield a warning
387        self.browser.open(self.login_path)
388        # We do not give credentials but send the form as-is
389        submit = self.browser.getControl(name='SUBMIT')
390        submit.click()
391        self.assertTrue(
392            'Entered credentials are invalid' in self.browser.contents)
393        return
394
395    def test_manager_no_warnings(self):
396        # Browsing the login screen as a manager, won't raise warnings
397        # Authenticate ourself as manager
398        self.browser.addHeader('Authorization', 'Basic mgr:mgrpw')
399        self.browser.open(self.login_path)
400        # Submit the form w/o any credentials
401        self.browser.getControl(name="SUBMIT").click()
402        self.assertTrue(
403            'Entered credentials are invalid' not in self.browser.contents)
404        return
405
406    def test_manager_no_redirect(self):
407        # Browsing the login screen as a manager won't trigger a redirect
408        # Authenticate ourself as manager
409        self.browser.addHeader('Authorization', 'Basic mgr:mgrpw')
410        self.browser.open(self.login_path)
411        # Submit the form w/o any credentials
412        self.browser.getControl(name="SUBMIT").click()
413        self.assertEqual(self.browser.url, self.login_path)
414        return
415
416    def test_display_entered_values(self):
417        # After submit the entered values are displayed in the form
418        self.browser.open(self.login_path)
419        # Enter some value we can look for after submit
420        ac_series = self.browser.getControl(name="form.ac_series")
421        ac_series.value = '666'
422        self.browser.getControl(name="SUBMIT").click()
423        self.assertTrue('666' in self.browser.contents)
424        return
425
426class LoginTestWithPINs(LoginTest):
427    # Here we check login view of applicants containers with PINs provided.
428
429    # As setting up pins is time-consuming we only set them up when
430    # really needed (i.e. in this separate TestCase).
431
432    layer = FunctionalLayer
433
434    def setUp(self):
435        super(LoginTestWithPINs, self).setUp()
436
437        # Create 5 access codes with prefix'FOO' and cost 9.99 each
438        pin_container = self.getRootFolder()['app']['accesscodes']
439        pin_container.createBatch(
440            datetime.now(), 'some_userid', 'APP', 9.99, 5)
441        pins = pin_container[pin_container.keys()[0]].values()
442        self.pins = [x.representation for x in pins]
443        self.existing_pin = self.pins[0]
444        parts = self.existing_pin.split('-')[1:]
445        self.existing_series, self.existing_number = parts
446        self.browser.handleErrors = False
447
448    def tearDown(self):
449        super(LoginTestWithPINs, self).tearDown()
450
451    def test_anonymous_valid_login(self):
452        # If we enter valid credentials, we get to the applicants form
453        self.browser.open(self.login_path)
454        # Enter some value we can look for after submit
455        ac_series = self.browser.getControl(name="form.ac_series")
456        ac_series.value = self.existing_series
457        ac_number = self.browser.getControl(name="form.ac_number")
458        ac_number.value = self.existing_number
459        self.browser.getControl(name="SUBMIT").click()
460        # We should be redirected to applicants form.
461        self.assertTrue(self.browser.url != self.login_path)
462        return
463
464    def test_anonymous_invalid_login(self):
465        # If we enter wrong credentials we won't get far
466        self.browser.open(self.login_path)
467        # Enter some value we can look for after submit
468        ac_series = self.browser.getControl(name="form.ac_series")
469        ac_series.value = 'illegal series'
470        ac_number = self.browser.getControl(name="form.ac_number")
471        ac_number.value = 'invalid number'
472        self.browser.getControl(name="SUBMIT").click()
473        # We get a warning message
474        self.assertTrue(
475            'Entered credentials are invalid' in self.browser.contents)
476        # We stay at the login page (no redirect)
477        self.assertTrue(self.browser.url == self.login_path)
478        return
479
480class ApplicantsPassportTests(ApplicantsFullSetup):
481    # Tests for uploading/browsing the passport image of appplicants
482
483    layer = FunctionalLayer
484
485    def setUp(self):
486        super(ApplicantsPassportTests, self).setUp()
487        self.login_path = 'http://localhost/app/applicants/app2009/login'
488        self.pin = self.pins[2]
489        self.existing_series, self.existing_number = self.pin.split('-')[1:]
490        self.edit_path = 'http://localhost/app/applicants/app2009/%s/edit' % (
491            self.pin)
492        self.edit_full_path = 'http://localhost/app/applicants/%s/%s/%s' % (
493            'app2009', self.pin, 'edit_full')
494
495    def tearDown(self):
496        super(ApplicantsPassportTests, self).tearDown()
497
498    def login(self):
499        # Perform an applicant login. This creates an applicant record.
500        #
501        # This helper also sets `self.applicant`, which is the
502        # applicant object created.
503        self.browser.open(self.login_path)
504        ac_series = self.browser.getControl(name="form.ac_series")
505        ac_series.value = self.existing_series
506        ac_number = self.browser.getControl(name="form.ac_number")
507        ac_number.value = self.existing_number
508        self.browser.getControl(name="SUBMIT").click()
509        self.applicant = self.app['applicants']['app2009'][self.pin]
510
511    def fill_correct_values(self):
512        # Fill the edit form with suitable values
513        self.browser.getControl(name="form.firstname").value = 'John'
514        self.browser.getControl(name="form.lastname").value = 'Tester'
515        self.browser.getControl(name="form.course1").value = ['CERT1']
516        self.browser.getControl(name="form.date_of_birth").value = '09/09/1988'
517        self.browser.getControl(name="form.lga").value = ['foreigner']
518        self.browser.getControl(name="form.sex").value = ['m']
519
520    def image_url(self, filename):
521        return self.edit_path.replace('edit', filename)
522
523    def test_after_login_default_browsable(self):
524        # After login we see the placeholder image in the edit view
525        self.login()
526        self.assertEqual(self.browser.url, self.edit_path)
527        # There is a correct <img> link included
528        self.assertTrue(
529            '<img src="placeholder_m.jpg" />' in self.browser.contents)
530        # Browsing the link shows a real image
531        self.browser.open(self.image_url('placeholder_m.jpg'))
532        self.assertEqual(
533            self.browser.headers['content-type'], 'image/jpeg')
534        self.assertEqual(len(self.browser.contents), PH_LEN)
535
536    def test_after_login_default_stored_in_imagestorage(self):
537        # After login the applicants placeholder image is stored in
538        # an imagestorage
539        storage = self.app['images']
540        # In the beginning, the storage is empty
541        self.assertEqual([x for x in storage.keys()], [])
542        self.login()
543        # After login, it is filled
544        self.assertEqual(
545            [x for x in storage.keys()],
546            [u'b48a1d39bbcb32e955d9ff2dea4ed0e6'])
547        file_id = self.applicant.passport.data
548        self.assertEqual(
549            file_id, u'b48a1d39bbcb32e955d9ff2dea4ed0e6-1')
550        # The stored image can be fetched
551        fd = storage.retrieveFile(file_id)
552        file_len = len(fd.read())
553        self.assertEqual(file_len, PH_LEN)
554
555    def test_after_submit_default_browsable(self):
556        # After submitting an applicant form the default image is
557        # still visible
558        self.login()
559        self.browser.getControl("Save").click() # submit form
560        # There is a correct <img> link included
561        self.assertTrue(
562            '<img src="placeholder_m.jpg" />' in self.browser.contents)
563        # Browsing the link shows a real image
564        self.browser.open(self.image_url('placeholder_m.jpg'))
565        self.assertEqual(
566            self.browser.headers['content-type'], 'image/jpeg')
567        self.assertEqual(len(self.browser.contents), PH_LEN)
568
569    def test_after_submit_default_stored_in_imagestorage(self):
570        # After submitting an applicant form the default image is
571        # correctly stored in an imagestorage
572        self.login()
573        self.browser.getControl("Save").click() # submit form
574        storage = self.app['images']
575        self.assertEqual(
576            [x for x in storage.keys()],
577            [u'b48a1d39bbcb32e955d9ff2dea4ed0e6'])
578        file_id = self.applicant.passport.data
579        self.assertEqual(
580            file_id, u'b48a1d39bbcb32e955d9ff2dea4ed0e6-1')
581        # The stored image can be fetched
582        fd = storage.retrieveFile(file_id)
583        file_len = len(fd.read())
584        self.assertEqual(file_len, PH_LEN)
585
586    # XXX: Make this test work again
587    def DISABLEDtest_uploaded_image_browsable_w_errors(self):
588        # We can upload a different image and browse it after submit,
589        # even if there are still errors in the form
590        self.login()
591        # Create a pseudo image file and select it to be uploaded in form
592        pseudo_image = StringIO('I pretend to be a graphics file')
593        ctrl = self.browser.getControl(name='form.passport')
594        file_ctrl = ctrl.mech_control
595        file_ctrl.add_file(pseudo_image, filename='myphoto.jpg')
596        self.browser.getControl("Save").click() # submit form
597        # There is a correct <img> link included
598        self.assertTrue(
599            '<img src="myphoto.jpg" />' in self.browser.contents)
600        # Browsing the link shows a real image
601        self.browser.open(self.image_url('myphoto.jpg'))
602        self.assertEqual(
603            self.browser.headers['content-type'], 'image/jpeg')
604        self.assertEqual(len(self.browser.contents), PH_LEN)
605
606    def test_uploaded_image_stored_in_imagestorage_w_errors(self):
607        # After uploading a new passport pic the file is correctly
608        # stored in an imagestorage
609        self.login()
610        # Create a pseudo image file and select it to be uploaded in form
611        pseudo_image = StringIO('I pretend to be a graphics file')
612        ctrl = self.browser.getControl(name='form.passport')
613        file_ctrl = ctrl.mech_control
614        file_ctrl.add_file(pseudo_image, filename='myphoto.jpg')
615        self.browser.getControl("Save").click() # submit form
616        storage = self.app['images']
617        self.assertTrue(
618            u'18e57c7eac6ca7fb15b54b5b2bd4106d' in storage.keys())
619        # The stored image can be fetched
620        fd = storage.retrieveFile(u'18e57c7eac6ca7fb15b54b5b2bd4106d-1')
621        #fd = storage.retrieveFile(file_id)
622        file_len = len(fd.read())
623        self.assertEqual(file_len, 31)
624        # The image uploaded belongs to the applicant
625        # XXX: When there are errors in form, then the applicant is not
626        #      changed. This (failing) test is here to remember us that
627        #      we have to care for images when form submits fail.
628        file_id = self.applicant.passport.data
629        self.assertEqual(
630            file_id, u'18e57c7eac6ca7fb15b54b5b2bd4106d-1')
631
632    def test_uploaded_image_browsable_wo_errors(self):
633        # We can upload a different image and browse it after submit,
634        # if there are no errors in form
635        self.login()
636        self.fill_correct_values() # fill other fields with correct values
637        # Create a pseudo image file and select it to be uploaded in form
638        pseudo_image = StringIO('I pretend to be a graphics file')
639        ctrl = self.browser.getControl(name='form.passport')
640        file_ctrl = ctrl.mech_control
641        file_ctrl.add_file(pseudo_image, filename='myphoto.jpg')
642        self.browser.getControl("Save").click() # submit form
643        # There is a correct <img> link included
644        self.assertTrue(
645            '<img src="myphoto.jpg" />' in self.browser.contents)
646        # Browsing the link shows a real image
647        self.browser.open(self.image_url('myphoto.jpg'))
648        self.assertEqual(
649            self.browser.headers['content-type'], 'image/jpeg')
650        self.assertEqual(len(self.browser.contents), 31)
651
652    def test_uploaded_image_stored_in_imagestorage_wo_errors(self):
653        # After uploading a new passport pic the file is correctly
654        # stored in an imagestorage if form contains no errors
655        self.login()
656        self.fill_correct_values() # fill other fields with correct values
657        # Create a pseudo image file and select it to be uploaded in form
658        pseudo_image = StringIO('I pretend to be a graphics file')
659        ctrl = self.browser.getControl(name='form.passport')
660        file_ctrl = ctrl.mech_control
661        file_ctrl.add_file(pseudo_image, filename='myphoto.jpg')
662        self.browser.getControl("Save").click() # submit form
663        storage = self.app['images']
664        self.assertTrue(
665            u'18e57c7eac6ca7fb15b54b5b2bd4106d' in storage.keys())
666        # The stored image can be fetched
667        fd = storage.retrieveFile(u'18e57c7eac6ca7fb15b54b5b2bd4106d-1')
668        #fd = storage.retrieveFile(file_id)
669        file_len = len(fd.read())
670        self.assertEqual(file_len, 31)
671        # The image uploaded belongs to the applicant
672        file_id = self.applicant.passport.data
673        self.assertEqual(
674            file_id, u'18e57c7eac6ca7fb15b54b5b2bd4106d-1')
675
676    def test_uploaded_images_equal(self):
677        # Make sure uploaded images do really differ if we eject a
678        # change notfication (and do not if we don't)
679        self.login() # Create applicant form
680        self.fill_correct_values() # fill other fields with correct values
681        self.browser.getControl("Save").click() # submit form
682        # Now go on as an officer
683        self.browser.addHeader('Authorization', 'Basic mgr:mgrpw')
684        self.browser.open(self.edit_full_path)
685
686        # Create a pseudo image file and select it to be uploaded in form
687        pseudo_image = StringIO('I pretend to be a graphics file')
688        ctrl = self.browser.getControl(name='form.passport')
689        file_ctrl = ctrl.mech_control
690        file_ctrl.add_file(pseudo_image, filename='myphoto.jpg')
691        passport0 = self.applicant.passport
692        self.browser.getControl("Save").click() # submit form with changed pic
693        passport1 = self.applicant.passport
694        self.browser.getControl("Save").click() # submit form w/o changes
695        passport2 = self.applicant.passport
696        self.assertTrue(passport0 != passport1)
697        self.assertTrue(passport1 == passport2)
698        self.assertTrue(passport1 is passport2)
699        return
700
701    def test_final_submit(self):
702        # Make sure that a correctly filled form with passport picture
703        # can be submitted
704        self.login() # Create applicant form
705        self.fill_correct_values() # fill other fields with correct values
706        # Create a pseudo image file and select it to be uploaded in form
707        pseudo_image = StringIO('I pretend to be a graphics file')
708        ctrl = self.browser.getControl(name='form.passport')
709        file_ctrl = ctrl.mech_control
710        file_ctrl.add_file(pseudo_image, filename='myphoto.jpg')
711        self.browser.getControl("Final Submit").click() # (finally) submit form
712        self.assertEqual(self.browser.headers['Status'], '200 Ok')
713        self.assertTrue(
714            'Passport confirmation box not ticked' in self.browser.contents)
715        self.browser.getControl(name="confirm_passport").value = True
716        self.browser.getControl("Final Submit").click() # submit form again
717        self.assertTrue(
718            '... submitted ...' in self.browser.contents)
719        return
720
721    def test_locking(self):
722        # Make sure that locked forms can't be submitted
723        self.login() # Create applicant form
724        self.fill_correct_values() # fill other fields with correct values
725        # Create a pseudo image file and select it to be uploaded in form
726        pseudo_image = StringIO('I pretend to be a graphics file')
727        ctrl = self.browser.getControl(name='form.passport')
728        file_ctrl = ctrl.mech_control
729        file_ctrl.add_file(pseudo_image, filename='myphoto.jpg')
730        self.browser.getControl("Save").click()
731        self.browser.getLink("Logout").click()
732
733        # Login as manager and lock the form
734        self.browser.addHeader('Authorization', 'Basic mgr:mgrpw')
735        self.browser.open(self.edit_full_path)
736        self.browser.getControl(name="form.locked").value = True
737        self.browser.getControl("Save").click()
738        self.browser.getLink("Logout").click()
739
740        # Login as applicant again and try to open the edit form
741        self.login()
742        self.browser.open(self.edit_path)
743        self.assertEqual(self.browser.headers['Status'], '200 Ok')
744        #print self.browser.contents
745        self.assertTrue(
746            'The requested form is locked' in self.browser.contents)
747        return
Note: See TracBrowser for help on using the repository browser.