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

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

Test assigning of local roles.

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