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

Last change on this file since 6592 was 6591, checked in by Henrik Bettermann, 14 years ago

Test workflow transition.

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