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

Last change on this file since 6583 was 6583, checked in by uli, 13 years ago

Add test to prove that uploaded images if not changed are equal
(although not identical).

File size: 29.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        return
111
112    def tearDown(self):
113        super(ApplicantsFullSetup, self).tearDown()
114        clearSite()
115        shutil.rmtree(self.dc_root)
116        #import pdb; pdb.set_trace()
117
118class ApplicantsUITests(ApplicantsFullSetup):
119    # Tests for ApplicantsRoot class
120
121    layer = FunctionalLayer
122
123    def test_anonymous_access(self):
124        # Anonymous users can access applicants root and applicants containers
125        self.browser.open(self.root_path)
126        self.assertEqual(self.browser.headers['Status'], '200 Ok')
127        self.assertFalse(
128            'Manage' in self.browser.contents)
129        self.browser.open(self.container_path)
130        self.assertEqual(self.browser.headers['Status'], '200 Ok')
131        self.assertFalse(
132            'Manage' in self.browser.contents)
133        return
134
135    def test_manage_cert_access(self):
136        # Managers can access CERT1
137        cert_path = 'http://localhost/app/faculties/fac1/dep1/certificates/CERT1'
138        self.browser.addHeader('Authorization', 'Basic mgr:mgrpw')
139        self.browser.open(cert_path)
140        self.assertEqual(self.browser.headers['Status'], '200 Ok')
141
142    def test_manage_access(self):
143        # Managers can access the manage pages of applicants root and
144        # applicants containers
145        self.browser.addHeader('Authorization', 'Basic mgr:mgrpw')
146        self.browser.open(self.root_path)
147        self.assertTrue(
148            'Manage application section' in self.browser.contents)
149        self.manage_root_path = self.root_path + '/@@manage'
150        self.manage_container_path = self.container_path + '/@@manage'
151        self.browser.open(self.manage_root_path)
152        self.assertEqual(self.browser.headers['Status'], '200 Ok')
153        self.assertEqual(self.browser.url, self.manage_root_path)
154        self.browser.open(self.manage_container_path)
155        self.assertEqual(self.browser.headers['Status'], '200 Ok')
156        self.assertEqual(self.browser.url, self.manage_container_path)
157        return
158
159    def test_add_delete_container(self):
160        # Managers can add and delete applicants containers
161        self.browser.addHeader('Authorization', 'Basic mgr:mgrpw')
162        self.browser.open(self.root_path)
163        self.add_container_path = self.root_path + '/@@add'
164        self.browser.open(self.add_container_path)
165        self.assertEqual(self.browser.headers['Status'], '200 Ok')
166        self.assertEqual(self.browser.url, self.add_container_path)
167        self.browser.getControl(name="form.prefix").value = ['app']
168        self.browser.getControl("Add applicants container").click()
169        self.assertTrue(
170            'There were errors' in self.browser.contents)
171        self.browser.getControl(name="form.prefix").value = ['app']
172        self.browser.getControl(name="form.year").value = ['2010']
173        self.browser.getControl(name="form.provider").value = [
174            'waeup.sirp.applicants.ApplicantsContainer']
175        self.browser.getControl(name="form.ac_prefix").value = ['APP']
176        self.browser.getControl(name="form.application_category").value = ['basic']
177        self.browser.getControl("Add applicants container").click()
178        self.assertTrue('Added:' in self.browser.contents)
179        ctrl = self.browser.getControl(name='val_id')
180        ctrl.getControl(value='app2010').selected = True
181        self.browser.getControl("Remove selected", index=0).click()
182        self.assertTrue('Successfully removed:' in self.browser.contents)
183        return
184
185    def test_add_delete_applicants(self):
186        # Managers can add and delete applicants
187        self.browser.addHeader('Authorization', 'Basic mgr:mgrpw')
188        self.add_applicant_path = self.container_path + '/addapplicant'
189        self.container_manage_path = self.container_path + '/@@manage'
190        self.browser.open(self.add_applicant_path)
191        self.assertEqual(self.browser.headers['Status'], '200 Ok')
192        self.assertEqual(self.browser.url, self.add_applicant_path)
193        self.browser.getControl(name="form.ac_series").value = self.existing_series
194        self.browser.getControl(name="form.ac_number").value = self.existing_number
195        self.browser.getControl("Create application record").click()
196        self.assertTrue('Application initialized' in self.browser.contents)
197        self.browser.open(self.container_manage_path)
198        self.assertEqual(self.browser.headers['Status'], '200 Ok')
199        ctrl = self.browser.getControl(name='val_id')
200        ctrl.getControl(value=self.existing_pin).selected = True
201        self.browser.getControl("Remove selected", index=0).click()
202        self.assertTrue('Successfully removed:' in self.browser.contents)
203        return
204
205    def test_manage_applicant(self):
206        # Managers can manage applicants
207        self.browser.addHeader('Authorization', 'Basic mgr:mgrpw')
208        self.applicant_path = 'http://localhost/app/applicants/app2009/%s' % self.pin_applicant
209        self.applicant_view_path = self.applicant_path + '/index'
210        self.applicant_manage_path = self.applicant_path + '/edit_full'
211        self.applicant_slip_path = self.applicant_path + '/application_slip.pdf'
212        self.browser.open(self.applicant_view_path)
213        self.assertEqual(self.browser.headers['Status'], '200 Ok')
214        self.browser.open(self.applicant_slip_path)
215        self.assertEqual(self.browser.headers['Status'], '200 Ok')
216        self.assertEqual(self.browser.headers['Content-Type'], 'application/pdf')
217        self.browser.open(self.applicant_manage_path)
218        self.assertEqual(self.browser.headers['Status'], '200 Ok')
219        self.browser.getControl(name="form.firstname").value = 'John'
220        self.browser.getControl(name="form.lastname").value = 'Tester'
221        self.browser.getControl(name="form.course1").value = ['CERT1']
222        self.browser.getControl(name="form.course_admitted").value = ['CERT1']
223        self.browser.getControl(name="form.date_of_birth").value = '09/09/1988'
224        self.browser.getControl(name="form.lga").value = ['foreigner']
225        self.browser.getControl(name="form.sex").value = ['m']
226        self.browser.getControl("Save").click()
227        self.assertMatches('...Form has been saved...', self.browser.contents)
228        return
229
230    def test_view_applicant(self):
231        # Applicants can login and view their application
232        self.login_path = 'http://localhost/app/applicants/app2009/login'
233        self.browser.open(self.login_path)
234        pin = self.pins[2]
235        parts = pin.split('-')[1:]
236        existing_series, existing_number = parts
237        ac_series = self.browser.getControl(name="form.ac_series")
238        ac_series.value = existing_series
239        ac_number = self.browser.getControl(name="form.ac_number")
240        ac_number.value = existing_number
241        self.browser.getControl(name="SUBMIT").click()
242        self.assertTrue(self.browser.url != self.login_path)
243        self.assertEqual(self.browser.headers['Status'], '200 Ok')
244        return
245
246    def test_passport_edit_view(self):
247        # We get a default image after login
248        login_path = 'http://localhost/app/applicants/app2009/login'
249        self.browser.open(login_path)
250        pin = self.pins[2]
251        parts = pin.split('-')[1:]
252        existing_series, existing_number = parts
253        ac_series = self.browser.getControl(name="form.ac_series")
254        ac_series.value = existing_series
255        ac_number = self.browser.getControl(name="form.ac_number")
256        ac_number.value = existing_number
257        self.browser.getControl(name="SUBMIT").click()
258
259        pin = self.pins[2]
260        appl = self.getRootFolder()['app']['applicants']['app2009']
261        appl = appl[pin]
262        passp = appl.passport
263        #import pdb; pdb.set_trace()
264        passp_len = len(passp.file.read())
265        self.assertEqual(passp_len, PH_LEN)
266
267
268        #image_url = "%s/%s" % (self.browser.url, 'placeholder.jpg')
269        image_url = "%s/%s" % (self.browser.url, 'passport.jpg')
270        #self.browser.open(image_url)
271        self.browser.open('passport.jpg')
272        self.assertEqual(self.browser.headers['status'], '200 Ok')
273        self.assertEqual(self.browser.headers['content-type'], 'image/jpeg')
274
275
276        self.assertTrue('JFIF' in self.browser.contents)
277        self.assertEqual(
278            self.browser.headers['content-length'], str(PH_LEN))
279
280
281    def test_edit_applicant(self):
282        # Applicants can edit their record
283        self.login_path = 'http://localhost/app/applicants/app2009/login'
284        self.browser.open(self.login_path)
285        pin = self.pins[2]
286        parts = pin.split('-')[1:]
287        existing_series, existing_number = parts
288        ac_series = self.browser.getControl(name="form.ac_series")
289        ac_series.value = existing_series
290        ac_number = self.browser.getControl(name="form.ac_number")
291        ac_number.value = existing_number
292        self.browser.getControl(name="SUBMIT").click()
293        self.assertTrue(self.browser.url != self.login_path)
294        self.assertEqual(self.browser.headers['Status'], '200 Ok')
295        self.browser.getControl(name="form.firstname").value = 'John'
296        self.browser.getControl(name="form.lastname").value = 'Tester'
297        self.browser.getControl(name="form.course1").value = ['CERT1']
298        self.browser.getControl(name="form.date_of_birth").value = '09/09/1988'
299        self.browser.getControl(name="form.lga").value = ['foreigner']
300        self.browser.getControl(name="form.sex").value = ['m']
301        self.browser.getControl("Save").click()
302        self.assertMatches('...Form has been saved...', self.browser.contents)
303        return
304
305class LoginTest(FunctionalTestCase):
306    # Here we check login view of applicants containers.
307    #
308    # Tests in here do only cover login attempts without any PINs
309    # created before.
310
311    layer = FunctionalLayer
312
313    def setUp(self):
314        super(LoginTest, self).setUp()
315
316        # Setup a sample site for each test
317        app = University()
318        self.dc_root = tempfile.mkdtemp()
319        app['datacenter'].setStoragePath(self.dc_root)
320        self.login_path = 'http://localhost/app/applicants/testapplicants/login'
321
322        # Add an applicants container where we can login (or not)
323        applicantscontainer = ApplicantsContainer()
324        applicantscontainer.ac_prefix = 'APP'
325        app['applicants']['testapplicants'] = applicantscontainer
326
327        # Put the prepopulated site into test ZODB and prepare test
328        # browser
329        self.getRootFolder()['app'] = app
330        self.browser = Browser()
331        self.browser.handleErrors = False
332
333    def tearDown(self):
334        super(LoginTest, self).tearDown()
335        shutil.rmtree(self.dc_root)
336
337    def test_anonymous_access(self):
338        # Anonymous users can access a login page
339        self.browser.open(self.login_path)
340        self.assertEqual(self.browser.headers['Status'], '200 Ok')
341        return
342
343    def test_anonymous_invalid_creds(self):
344        # Anonymous users giving invalid credentials stay at the page
345        self.browser.open(self.login_path)
346        # We do not give credentials but send the form as-is
347        submit = self.browser.getControl(name='SUBMIT')
348        submit.click()
349        # We are still at the same page...
350        self.assertEqual(self.browser.url, self.login_path)
351        self.assertEqual(self.browser.headers['Status'], '200 Ok')
352        return
353
354    def test_anonymous_invalid_creds_warning(self):
355        # Entering wrong credentials will yield a warning
356        self.browser.open(self.login_path)
357        # We do not give credentials but send the form as-is
358        submit = self.browser.getControl(name='SUBMIT')
359        submit.click()
360        self.assertTrue(
361            'Entered credentials are invalid' in self.browser.contents)
362        return
363
364    def test_manager_no_warnings(self):
365        # Browsing the login screen as a manager, won't raise warnings
366        # Authenticate ourself as manager
367        self.browser.addHeader('Authorization', 'Basic mgr:mgrpw')
368        self.browser.open(self.login_path)
369        # Submit the form w/o any credentials
370        self.browser.getControl(name="SUBMIT").click()
371        self.assertTrue(
372            'Entered credentials are invalid' not in self.browser.contents)
373        return
374
375    def test_manager_no_redirect(self):
376        # Browsing the login screen as a manager won't trigger a redirect
377        # Authenticate ourself as manager
378        self.browser.addHeader('Authorization', 'Basic mgr:mgrpw')
379        self.browser.open(self.login_path)
380        # Submit the form w/o any credentials
381        self.browser.getControl(name="SUBMIT").click()
382        self.assertEqual(self.browser.url, self.login_path)
383        return
384
385    def test_display_entered_values(self):
386        # After submit the entered values are displayed in the form
387        self.browser.open(self.login_path)
388        # Enter some value we can look for after submit
389        ac_series = self.browser.getControl(name="form.ac_series")
390        ac_series.value = '666'
391        self.browser.getControl(name="SUBMIT").click()
392        self.assertTrue('666' in self.browser.contents)
393        return
394
395class LoginTestWithPINs(LoginTest):
396    # Here we check login view of applicants containers with PINs provided.
397
398    # As setting up pins is time-consuming we only set them up when
399    # really needed (i.e. in this separate TestCase).
400
401    layer = FunctionalLayer
402
403    def setUp(self):
404        super(LoginTestWithPINs, self).setUp()
405
406        # Create 5 access codes with prefix'FOO' and cost 9.99 each
407        pin_container = self.getRootFolder()['app']['accesscodes']
408        pin_container.createBatch(
409            datetime.now(), 'some_userid', 'APP', 9.99, 5)
410        pins = pin_container[pin_container.keys()[0]].values()
411        self.pins = [x.representation for x in pins]
412        self.existing_pin = self.pins[0]
413        parts = self.existing_pin.split('-')[1:]
414        self.existing_series, self.existing_number = parts
415        self.browser.handleErrors = False
416
417    def tearDown(self):
418        super(LoginTestWithPINs, self).tearDown()
419
420    def test_anonymous_valid_login(self):
421        # If we enter valid credentials, we get to the applicants form
422        self.browser.open(self.login_path)
423        # Enter some value we can look for after submit
424        ac_series = self.browser.getControl(name="form.ac_series")
425        ac_series.value = self.existing_series
426        ac_number = self.browser.getControl(name="form.ac_number")
427        ac_number.value = self.existing_number
428        self.browser.getControl(name="SUBMIT").click()
429        # We should be redirected to applicants form.
430        self.assertTrue(self.browser.url != self.login_path)
431        return
432
433    def test_anonymous_invalid_login(self):
434        # If we enter wrong credentials we won't get far
435        self.browser.open(self.login_path)
436        # Enter some value we can look for after submit
437        ac_series = self.browser.getControl(name="form.ac_series")
438        ac_series.value = 'illegal series'
439        ac_number = self.browser.getControl(name="form.ac_number")
440        ac_number.value = 'invalid number'
441        self.browser.getControl(name="SUBMIT").click()
442        # We get a warning message
443        self.assertTrue(
444            'Entered credentials are invalid' in self.browser.contents)
445        # We stay at the login page (no redirect)
446        self.assertTrue(self.browser.url == self.login_path)
447        return
448
449class ApplicantsPassportTests(ApplicantsFullSetup):
450    # Tests for uploading/browsing the passport image of appplicants
451
452    layer = FunctionalLayer
453
454    def setUp(self):
455        super(ApplicantsPassportTests, self).setUp()
456        self.login_path = 'http://localhost/app/applicants/app2009/login'
457        self.pin = self.pins[2]
458        self.existing_series, self.existing_number = self.pin.split('-')[1:]
459        self.edit_path = 'http://localhost/app/applicants/app2009/%s/edit' % (
460            self.pin)
461        self.edit_full_path = 'http://localhost/app/applicants/%s/%s/%s' % (
462            'app2009', self.pin, 'edit_full')
463
464    def tearDown(self):
465        super(ApplicantsPassportTests, self).tearDown()
466
467    def login(self):
468        # Perform an applicant login. This creates an applicant record.
469        #
470        # This helper also sets `self.applicant`, which is the
471        # applicant object created.
472        self.browser.open(self.login_path)
473        ac_series = self.browser.getControl(name="form.ac_series")
474        ac_series.value = self.existing_series
475        ac_number = self.browser.getControl(name="form.ac_number")
476        ac_number.value = self.existing_number
477        self.browser.getControl(name="SUBMIT").click()
478        self.applicant = self.app['applicants']['app2009'][self.pin]
479
480    def fill_correct_values(self):
481        # Fill the edit form with suitable values
482        self.browser.getControl(name="form.firstname").value = 'John'
483        self.browser.getControl(name="form.lastname").value = 'Tester'
484        self.browser.getControl(name="form.course1").value = ['CERT1']
485        self.browser.getControl(name="form.date_of_birth").value = '09/09/1988'
486        self.browser.getControl(name="form.lga").value = ['foreigner']
487        self.browser.getControl(name="form.sex").value = ['m']
488
489    def image_url(self, filename):
490        return self.edit_path.replace('edit', filename)
491
492    def test_after_login_default_browsable(self):
493        # After login we see the placeholder image in the edit view
494        self.login()
495        self.assertEqual(self.browser.url, self.edit_path)
496        # There is a correct <img> link included
497        self.assertTrue(
498            '<img src="placeholder_m.jpg" />' in self.browser.contents)
499        # Browsing the link shows a real image
500        self.browser.open(self.image_url('placeholder_m.jpg'))
501        self.assertEqual(
502            self.browser.headers['content-type'], 'image/jpeg')
503        self.assertEqual(len(self.browser.contents), PH_LEN)
504
505    def test_after_login_default_stored_in_imagestorage(self):
506        # After login the applicants placeholder image is stored in
507        # an imagestorage
508        storage = self.app['images']
509        # In the beginning, the storage is empty
510        self.assertEqual([x for x in storage.keys()], [])
511        self.login()
512        # After login, it is filled
513        self.assertEqual(
514            [x for x in storage.keys()],
515            [u'b48a1d39bbcb32e955d9ff2dea4ed0e6'])
516        file_id = self.applicant.passport.data
517        self.assertEqual(
518            file_id, u'b48a1d39bbcb32e955d9ff2dea4ed0e6-1')
519        # The stored image can be fetched
520        fd = storage.retrieveFile(file_id)
521        file_len = len(fd.read())
522        self.assertEqual(file_len, PH_LEN)
523
524    def test_after_submit_default_browsable(self):
525        # After submitting an applicant form the default image is
526        # still visible
527        self.login()
528        self.browser.getControl("Save").click() # submit form
529        # There is a correct <img> link included
530        self.assertTrue(
531            '<img src="placeholder_m.jpg" />' in self.browser.contents)
532        # Browsing the link shows a real image
533        self.browser.open(self.image_url('placeholder_m.jpg'))
534        self.assertEqual(
535            self.browser.headers['content-type'], 'image/jpeg')
536        self.assertEqual(len(self.browser.contents), PH_LEN)
537
538    def test_after_submit_default_stored_in_imagestorage(self):
539        # After submitting an applicant form the default image is
540        # correctly stored in an imagestorage
541        self.login()
542        self.browser.getControl("Save").click() # submit form
543        storage = self.app['images']
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    # XXX: Make this test work again
556    def DISABLEDtest_uploaded_image_browsable_w_errors(self):
557        # We can upload a different image and browse it after submit,
558        # even if there are still errors in the form
559        self.login()
560        # Create a pseudo image file and select it to be uploaded in form
561        pseudo_image = StringIO('I pretend to be a graphics file')
562        ctrl = self.browser.getControl(name='form.passport')
563        file_ctrl = ctrl.mech_control
564        file_ctrl.add_file(pseudo_image, filename='myphoto.jpg')
565        self.browser.getControl("Save").click() # submit form
566        # There is a correct <img> link included
567        self.assertTrue(
568            '<img src="myphoto.jpg" />' in self.browser.contents)
569        # Browsing the link shows a real image
570        self.browser.open(self.image_url('myphoto.jpg'))
571        self.assertEqual(
572            self.browser.headers['content-type'], 'image/jpeg')
573        self.assertEqual(len(self.browser.contents), PH_LEN)
574
575    def test_uploaded_image_stored_in_imagestorage_w_errors(self):
576        # After uploading a new passport pic the file is correctly
577        # stored in an imagestorage
578        self.login()
579        # Create a pseudo image file and select it to be uploaded in form
580        pseudo_image = StringIO('I pretend to be a graphics file')
581        ctrl = self.browser.getControl(name='form.passport')
582        file_ctrl = ctrl.mech_control
583        file_ctrl.add_file(pseudo_image, filename='myphoto.jpg')
584        self.browser.getControl("Save").click() # submit form
585        storage = self.app['images']
586        self.assertTrue(
587            u'18e57c7eac6ca7fb15b54b5b2bd4106d' in storage.keys())
588        # The stored image can be fetched
589        fd = storage.retrieveFile(u'18e57c7eac6ca7fb15b54b5b2bd4106d-1')
590        #fd = storage.retrieveFile(file_id)
591        file_len = len(fd.read())
592        self.assertEqual(file_len, 31)
593        # The image uploaded belongs to the applicant
594        # XXX: When there are errors in form, then the applicant is not
595        #      changed. This (failing) test is here to remember us that
596        #      we have to care for images when form submits fail.
597        file_id = self.applicant.passport.data
598        self.assertEqual(
599            file_id, u'18e57c7eac6ca7fb15b54b5b2bd4106d-1')
600
601    def test_uploaded_image_browsable_wo_errors(self):
602        # We can upload a different image and browse it after submit,
603        # if there are no errors in form
604        self.login()
605        self.fill_correct_values() # fill other fields with correct values
606        # Create a pseudo image file and select it to be uploaded in form
607        pseudo_image = StringIO('I pretend to be a graphics file')
608        ctrl = self.browser.getControl(name='form.passport')
609        file_ctrl = ctrl.mech_control
610        file_ctrl.add_file(pseudo_image, filename='myphoto.jpg')
611        self.browser.getControl("Save").click() # submit form
612        # There is a correct <img> link included
613        self.assertTrue(
614            '<img src="myphoto.jpg" />' in self.browser.contents)
615        # Browsing the link shows a real image
616        self.browser.open(self.image_url('myphoto.jpg'))
617        self.assertEqual(
618            self.browser.headers['content-type'], 'image/jpeg')
619        self.assertEqual(len(self.browser.contents), 31)
620
621    def test_uploaded_image_stored_in_imagestorage_wo_errors(self):
622        # After uploading a new passport pic the file is correctly
623        # stored in an imagestorage if form contains no errors
624        self.login()
625        self.fill_correct_values() # fill other fields with correct values
626        # Create a pseudo image file and select it to be uploaded in form
627        pseudo_image = StringIO('I pretend to be a graphics file')
628        ctrl = self.browser.getControl(name='form.passport')
629        file_ctrl = ctrl.mech_control
630        file_ctrl.add_file(pseudo_image, filename='myphoto.jpg')
631        self.browser.getControl("Save").click() # submit form
632        storage = self.app['images']
633        self.assertTrue(
634            u'18e57c7eac6ca7fb15b54b5b2bd4106d' in storage.keys())
635        # The stored image can be fetched
636        fd = storage.retrieveFile(u'18e57c7eac6ca7fb15b54b5b2bd4106d-1')
637        #fd = storage.retrieveFile(file_id)
638        file_len = len(fd.read())
639        self.assertEqual(file_len, 31)
640        # The image uploaded belongs to the applicant
641        file_id = self.applicant.passport.data
642        self.assertEqual(
643            file_id, u'18e57c7eac6ca7fb15b54b5b2bd4106d-1')
644
645    def test_uploaded_images_equal(self):
646        # Make sure uploaded images do really differ if we eject a
647        # change notfication (and do not if we don't)
648        self.login() # Create applicant form
649        self.fill_correct_values() # fill other fields with correct values
650        self.browser.getControl("Save").click() # submit form
651        # Now go on as an officer
652        self.browser.addHeader('Authorization', 'Basic mgr:mgrpw')
653        self.browser.open(self.edit_full_path)
654
655        # Create a pseudo image file and select it to be uploaded in form
656        pseudo_image = StringIO('I pretend to be a graphics file')
657        ctrl = self.browser.getControl(name='form.passport')
658        file_ctrl = ctrl.mech_control
659        file_ctrl.add_file(pseudo_image, filename='myphoto.jpg')
660        passport0 = self.applicant.passport
661        self.browser.getControl("Save").click() # submit form with changed pic
662        passport1 = self.applicant.passport
663        self.browser.getControl("Save").click() # submit form w/o changes
664        passport2 = self.applicant.passport
665        self.assertTrue(passport0 != passport1)
666        self.assertTrue(passport1 == passport2)
667        self.assertTrue(passport1 is not passport2)
668        return
Note: See TracBrowser for help on using the repository browser.