source: main/waeup.ikoba/trunk/src/waeup/ikoba/customers/tests/test_browser.py @ 12015

Last change on this file since 12015 was 12015, checked in by Henrik Bettermann, 10 years ago

Add first browser components with tests.

  • Property svn:keywords set to Id
File size: 39.4 KB
Line 
1## $Id: test_browser.py 12015 2014-11-20 21:39:40Z henrik $
2##
3## Copyright (C) 2014 Uli Fouquet & Henrik Bettermann
4## This program is free software; you can redistribute it and/or modify
5## it under the terms of the GNU General Public License as published by
6## the Free Software Foundation; either version 2 of the License, or
7## (at your option) any later version.
8##
9## This program is distributed in the hope that it will be useful,
10## but WITHOUT ANY WARRANTY; without even the implied warranty of
11## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12## GNU General Public License for more details.
13##
14## You should have received a copy of the GNU General Public License
15## along with this program; if not, write to the Free Software
16## Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17##
18"""
19Test the customer-related UI components.
20"""
21import shutil
22import tempfile
23import pytz
24import base64
25from datetime import datetime, timedelta, date
26from StringIO import StringIO
27import os
28import grok
29from zc.async.testing import wait_for_result
30from zope.event import notify
31from zope.component import createObject, queryUtility, getUtility
32from zope.component.hooks import setSite, clearSite
33from zope.catalog.interfaces import ICatalog
34from zope.security.interfaces import Unauthorized
35from zope.securitypolicy.interfaces import IPrincipalRoleManager
36from zope.testbrowser.testing import Browser
37from hurry.workflow.interfaces import IWorkflowInfo, IWorkflowState
38from waeup.ikoba.testing import FunctionalLayer, FunctionalTestCase
39from waeup.ikoba.app import Company
40from waeup.ikoba.customers.interfaces import ICustomersUtils
41from waeup.ikoba.customers.customer import Customer
42from waeup.ikoba.interfaces import IUserAccount, IJobManager
43from waeup.ikoba.authentication import LocalRoleSetEvent
44from waeup.ikoba.tests.test_async import FunctionalAsyncTestCase
45
46PH_LEN = 15911  # Length of placeholder file
47
48SAMPLE_IMAGE = os.path.join(os.path.dirname(__file__), 'test_image.jpg')
49SAMPLE_IMAGE_BMP = os.path.join(os.path.dirname(__file__), 'test_image.bmp')
50
51def lookup_submit_value(name, value, browser):
52    """Find a button with a certain value."""
53    for num in range(0, 100):
54        try:
55            button = browser.getControl(name=name, index=num)
56            if button.value.endswith(value):
57                return button
58        except IndexError:
59            break
60    return None
61
62class CustomersFullSetup(FunctionalTestCase):
63    # A test case that only contains a setup and teardown
64    #
65    # Complete setup for customers handlings is rather complex and
66    # requires lots of things created before we can start. This is a
67    # setup that does all this, creates a university, creates PINs,
68    # etc.  so that we do not have to bother with that in different
69    # test cases.
70
71    layer = FunctionalLayer
72
73    def setUp(self):
74        super(CustomersFullSetup, self).setUp()
75
76        # Setup a sample site for each test
77        app = Company()
78        self.dc_root = tempfile.mkdtemp()
79        app['datacenter'].setStoragePath(self.dc_root)
80
81        # Prepopulate the ZODB...
82        self.getRootFolder()['app'] = app
83        # we add the site immediately after creation to the
84        # ZODB. Catalogs and other local utilities are not setup
85        # before that step.
86        self.app = self.getRootFolder()['app']
87        # Set site here. Some of the following setup code might need
88        # to access grok.getSite() and should get our new app then
89        setSite(app)
90
91        # Add customer with subobjects
92        customer = createObject('waeup.Customer')
93        customer.firstname = u'Anna'
94        customer.lastname = u'Tester'
95        customer.reg_number = u'123'
96        customer.sex = u'm'
97        customer.email = 'aa@aa.ng'
98        customer.phone = u'1234'
99        customer.date_of_birth = date(1981, 2, 4)
100        self.app['customers'].addCustomer(customer)
101        self.customer_id = customer.customer_id
102        self.customer = self.app['customers'][self.customer_id]
103        document = createObject('waeup.CustomerDocument')
104        document.title = u'My first document'
105        self.customer['documents'].addDocument(document)
106
107        # Set password
108        IUserAccount(
109            self.app['customers'][self.customer_id]).setPassword('spwd')
110
111        self.login_path = 'http://localhost/app/login'
112        self.container_path = 'http://localhost/app/customers'
113        self.manage_container_path = self.container_path + '/@@manage'
114        self.add_customer_path = self.container_path + '/addcustomer'
115        self.customer_path = self.container_path + '/' + self.customer_id
116        self.manage_customer_path = self.customer_path + '/manage_base'
117        self.trigtrans_path = self.customer_path + '/trigtrans'
118        self.history_path = self.customer_path + '/history'
119        self.documents_path = self.customer_path + '/documents'
120
121        self.app['configuration'].carry_over = True
122        configuration = createObject('waeup.SessionConfiguration')
123        self.app['configuration'].addSessionConfiguration(configuration)
124
125        # Update the catalog
126        notify(grok.ObjectModifiedEvent(self.customer))
127
128        # Put the prepopulated site into test ZODB and prepare test
129        # browser
130        self.browser = Browser()
131        self.browser.handleErrors = False
132
133    def tearDown(self):
134        super(CustomersFullSetup, self).tearDown()
135        clearSite()
136        shutil.rmtree(self.dc_root)
137
138
139
140class CustomersContainerUITests(CustomersFullSetup):
141    # Tests for CustomersContainer class views and pages
142
143    layer = FunctionalLayer
144
145    def test_anonymous_access(self):
146        # Anonymous users can't access customers containers
147        self.assertRaises(
148            Unauthorized, self.browser.open, self.container_path)
149        self.assertRaises(
150            Unauthorized, self.browser.open, self.manage_container_path)
151        return
152
153    def test_manage_access(self):
154        # Managers can access the view page of customers
155        # containers and can perform actions
156        self.browser.addHeader('Authorization', 'Basic mgr:mgrpw')
157        self.browser.open(self.container_path)
158        self.assertEqual(self.browser.headers['Status'], '200 Ok')
159        self.assertEqual(self.browser.url, self.container_path)
160        self.browser.getLink("Manage customer section").click()
161        self.assertEqual(self.browser.headers['Status'], '200 Ok')
162        self.assertEqual(self.browser.url, self.manage_container_path)
163        return
164
165    def test_add_search_delete_customers(self):
166        # Managers can add search and remove customers
167        self.browser.addHeader('Authorization', 'Basic mgr:mgrpw')
168        self.browser.open(self.manage_container_path)
169        self.browser.getLink("Add customer").click()
170        self.assertEqual(self.browser.headers['Status'], '200 Ok')
171        self.assertEqual(self.browser.url, self.add_customer_path)
172        self.browser.getControl(name="form.firstname").value = 'Bob'
173        self.browser.getControl(name="form.lastname").value = 'Tester'
174        self.browser.getControl(name="form.reg_number").value = '123'
175        self.browser.getControl("Create customer record").click()
176        self.assertTrue('Registration number exists already'
177            in self.browser.contents)
178        self.browser.getControl(name="form.reg_number").value = '1234'
179        self.browser.getControl("Create customer record").click()
180        self.assertTrue('Customer record created' in self.browser.contents)
181
182        # Registration must be unique
183        self.browser.getLink("Manage").click()
184        self.browser.getControl(name="form.reg_number").value = '123'
185        self.browser.getControl("Save").click()
186        self.assertMatches('...Registration number exists...',
187                           self.browser.contents)
188
189        # We can find a customer with a certain customer_id
190        self.browser.open(self.container_path)
191        self.browser.getControl("Find customer(s)").click()
192        self.assertTrue('Empty search string' in self.browser.contents)
193        self.browser.getControl(name="searchtype").value = ['customer_id']
194        self.browser.getControl(name="searchterm").value = self.customer_id
195        self.browser.getControl("Find customer(s)").click()
196        self.assertTrue('Anna Tester' in self.browser.contents)
197
198        # We can find a customer by searching for all kind of name parts
199        self.browser.open(self.manage_container_path)
200        self.browser.getControl("Find customer(s)").click()
201        self.assertTrue('Empty search string' in self.browser.contents)
202        self.browser.getControl(name="searchtype").value = ['fullname']
203        self.browser.getControl(name="searchterm").value = 'Anna Tester'
204        self.browser.getControl("Find customer(s)").click()
205        self.assertTrue('Anna Tester' in self.browser.contents)
206        self.browser.open(self.manage_container_path)
207        self.browser.getControl(name="searchtype").value = ['fullname']
208        self.browser.getControl(name="searchterm").value = 'Anna'
209        self.browser.getControl("Find customer(s)").click()
210        self.assertTrue('Anna Tester' in self.browser.contents)
211        self.browser.open(self.manage_container_path)
212        self.browser.getControl(name="searchtype").value = ['fullname']
213        self.browser.getControl(name="searchterm").value = 'Tester'
214        self.browser.getControl("Find customer(s)").click()
215        self.assertTrue('Anna Tester' in self.browser.contents)
216        self.browser.open(self.manage_container_path)
217        self.browser.getControl(name="searchtype").value = ['fullname']
218        self.browser.getControl(name="searchterm").value = 'An'
219        self.browser.getControl("Find customer(s)").click()
220        self.assertFalse('Anna Tester' in self.browser.contents)
221        self.browser.open(self.manage_container_path)
222        self.browser.getControl(name="searchtype").value = ['fullname']
223        self.browser.getControl(name="searchterm").value = 'An*'
224        self.browser.getControl("Find customer(s)").click()
225        self.assertTrue('Anna Tester' in self.browser.contents)
226        self.browser.open(self.manage_container_path)
227        self.browser.getControl(name="searchtype").value = ['fullname']
228        self.browser.getControl(name="searchterm").value = 'tester'
229        self.browser.getControl("Find customer(s)").click()
230        self.assertTrue('Anna Tester' in self.browser.contents)
231        self.browser.open(self.manage_container_path)
232        self.browser.getControl(name="searchtype").value = ['fullname']
233        self.browser.getControl(name="searchterm").value = 'Tester Ana'
234        self.browser.getControl("Find customer(s)").click()
235        self.assertFalse('Anna Tester' in self.browser.contents)
236        self.browser.open(self.manage_container_path)
237        self.browser.getControl(name="searchtype").value = ['fullname']
238        self.browser.getControl(name="searchterm").value = 'Tester Anna'
239        self.browser.getControl("Find customer(s)").click()
240        self.assertTrue('Anna Tester' in self.browser.contents)
241        # The old searchterm will be used again
242        self.browser.getControl("Find customer(s)").click()
243        self.assertTrue('Anna Tester' in self.browser.contents)
244
245        # We can find suspended customers
246        self.customer.suspended = True
247        notify(grok.ObjectModifiedEvent(self.customer))
248        self.browser.open(self.manage_container_path)
249        self.browser.getControl(name="searchtype").value = ['suspended']
250        self.browser.getControl("Find customer(s)").click()
251        self.assertTrue('Anna Tester' in self.browser.contents)
252
253        # Removed customers won't be found
254        ctrl = self.browser.getControl(name='entries')
255        ctrl.getControl(value=self.customer_id).selected = True
256        self.browser.getControl("Remove selected", index=0).click()
257        self.assertTrue('Successfully removed' in self.browser.contents)
258        self.browser.getControl(name="searchtype").value = ['customer_id']
259        self.browser.getControl(name="searchterm").value = self.customer_id
260        self.browser.getControl("Find customer(s)").click()
261        self.assertTrue('No customer found' in self.browser.contents)
262        return
263
264class OfficerUITests(CustomersFullSetup):
265    # Tests for Customer class views and pages
266
267    def test_basic_auth(self):
268        self.browser.addHeader('Authorization', 'Basic mgr:mgrpw')
269        self.browser.open('http://localhost/app')
270        self.browser.getLink("Logout").click()
271        self.assertTrue('You have been logged out' in self.browser.contents)
272        # But we are still logged in since we've used basic authentication here.
273        # Wikipedia says: Existing browsers retain authentication information
274        # until the tab or browser is closed or the user clears the history.
275        # HTTP does not provide a method for a server to direct clients to
276        # discard these cached credentials. This means that there is no
277        # effective way for a server to "log out" the user without closing
278        # the browser. This is a significant defect that requires browser
279        # manufacturers to support a "logout" user interface element ...
280        self.assertTrue('Manager' in self.browser.contents)
281
282    def test_basic_auth_base64(self):
283        auth_token = base64.b64encode('mgr:mgrpw')
284        self.browser.addHeader('Authorization', 'Basic %s' % auth_token)
285        self.browser.open(self.manage_container_path)
286        self.assertEqual(self.browser.headers['Status'], '200 Ok')
287
288    def test_manage_access(self):
289        # Managers can access the pages of customers
290        # and can perform actions
291        self.browser.addHeader('Authorization', 'Basic mgr:mgrpw')
292        self.browser.open(self.customer_path)
293        self.assertEqual(self.browser.headers['Status'], '200 Ok')
294        self.assertEqual(self.browser.url, self.customer_path)
295        self.browser.getLink("Trigger").click()
296        self.assertEqual(self.browser.headers['Status'], '200 Ok')
297        # Managers can trigger transitions
298        self.browser.getControl(name="transition").value = ['start']
299        self.browser.getControl("Save").click()
300        # Managers can edit base
301        self.browser.open(self.customer_path)
302        self.browser.getLink("Manage").click()
303        self.assertEqual(self.browser.url, self.manage_customer_path)
304        self.assertEqual(self.browser.headers['Status'], '200 Ok')
305        self.browser.getControl(name="form.firstname").value = 'John'
306        self.browser.getControl(name="form.lastname").value = 'Tester'
307        self.browser.getControl(name="form.reg_number").value = '345'
308        self.browser.getControl(name="password").value = 'secret'
309        self.browser.getControl(name="control_password").value = 'secret'
310        self.browser.getControl("Save").click()
311        self.assertMatches('...Form has been saved...',
312                           self.browser.contents)
313
314    def test_manage_contact_customer(self):
315        # Managers can contact customer
316        self.browser.addHeader('Authorization', 'Basic mgr:mgrpw')
317        self.customer.email = None
318        self.browser.open(self.customer_path)
319        self.browser.getLink("Send email").click()
320        self.browser.getControl(name="form.subject").value = 'Important subject'
321        self.browser.getControl(name="form.body").value = 'Hello!'
322        self.browser.getControl("Send message now").click()
323        self.assertTrue('An smtp server error occurred' in self.browser.contents)
324        self.customer.email = 'xx@yy.zz'
325        self.browser.getControl("Send message now").click()
326        self.assertTrue('Your message has been sent' in self.browser.contents)
327        return
328
329    def test_manage_upload_passport(self):
330        # Managers can upload a file via the CustomerBaseManageFormPage
331        self.browser.addHeader('Authorization', 'Basic mgr:mgrpw')
332        self.browser.open(self.manage_customer_path)
333        image = open(SAMPLE_IMAGE_BMP, 'rb')
334        ctrl = self.browser.getControl(name='passportuploadmanage')
335        file_ctrl = ctrl.mech_control
336        file_ctrl.add_file(image, filename='my_photo.bmp')
337        self.browser.getControl(
338            name='upload_passportuploadmanage').click()
339        self.assertTrue('jpg file extension expected'
340            in self.browser.contents)
341        ctrl = self.browser.getControl(name='passportuploadmanage')
342        file_ctrl = ctrl.mech_control
343        image = open(SAMPLE_IMAGE, 'rb')
344        file_ctrl.add_file(image, filename='my_photo.jpg')
345        self.browser.getControl(
346            name='upload_passportuploadmanage').click()
347        self.assertTrue(
348            'src="http://localhost/app/customers/K1000000/passport.jpg"'
349            in self.browser.contents)
350        # We remove the passport file again
351        self.browser.open(self.manage_customer_path)
352        self.browser.getControl('Delete').click()
353        self.assertTrue('passport.jpg deleted' in self.browser.contents)
354
355
356    def test_manage_workflow(self):
357        # Managers can pass through the whole workflow
358        self.browser.addHeader('Authorization', 'Basic mgr:mgrpw')
359        customer = self.app['customers'][self.customer_id]
360        self.browser.open(self.trigtrans_path)
361        self.browser.getControl(name="transition").value = ['start']
362        self.browser.getControl("Save").click()
363        self.browser.getControl(name="transition").value = ['request']
364        self.browser.getControl("Save").click()
365        self.browser.getControl(name="transition").value = ['reject']
366        self.browser.getControl("Save").click()
367        self.browser.getControl(name="transition").value = ['request']
368        self.browser.getControl("Save").click()
369        self.browser.getControl(name="transition").value = ['approve']
370        self.browser.getControl("Save").click()
371        self.browser.getControl(name="transition").value = ['reset1']
372        self.browser.getControl("Save").click()
373        return
374
375    def test_manage_import(self):
376        # Managers can import customer data files
377        datacenter_path = 'http://localhost/app/datacenter'
378        # Prepare a csv file for customers
379        open('customers.csv', 'wb').write(
380"""firstname,lastname,reg_number,date_of_birth,email,phone,sex,password
381Aaren,Pieri,1,1990-01-02,aa@aa.ng,1234,m,mypwd1
382Claus,Finau,2,1990-01-03,aa@aa.ng,1234,m,mypwd1
383Brit,Berson,2,1990-01-04,aa@aa.ng,1234,m,mypwd1
384""")
385        self.browser.addHeader('Authorization', 'Basic mgr:mgrpw')
386        self.browser.open(datacenter_path)
387        self.browser.getLink('Upload data').click()
388        filecontents = StringIO(open('customers.csv', 'rb').read())
389        filewidget = self.browser.getControl(name='uploadfile:file')
390        filewidget.add_file(filecontents, 'text/plain', 'customers.csv')
391        self.browser.getControl(name='SUBMIT').click()
392        self.browser.getLink('Process data').click()
393        button = lookup_submit_value(
394            'select', 'customers_zope.mgr.csv', self.browser)
395        button.click()
396        importerselect = self.browser.getControl(name='importer')
397        modeselect = self.browser.getControl(name='mode')
398        importerselect.getControl('Customer Processor').selected = True
399        modeselect.getControl(value='create').selected = True
400        self.browser.getControl('Proceed to step 3').click()
401        self.assertTrue('Header fields OK' in self.browser.contents)
402        self.browser.getControl('Perform import').click()
403        self.assertTrue('Processing of 1 rows failed' in self.browser.contents)
404        self.assertTrue('Successfully processed 2 rows' in self.browser.contents)
405        self.assertTrue('Batch processing finished' in self.browser.contents)
406
407        # The customers are properly indexed and we can
408        # thus find a customer in  the department
409        self.browser.open(self.manage_container_path)
410        # We can search for a new customer by name ...
411        self.browser.getControl(name="searchtype").value = ['fullname']
412        self.browser.getControl(name="searchterm").value = 'Claus'
413        self.browser.getControl("Find customer(s)").click()
414        self.assertTrue('Claus Finau' in self.browser.contents)
415        # ... and check if the imported password has been properly set
416        ctrl = self.browser.getControl(name='entries')
417        value = ctrl.options[0]
418        claus = self.app['customers'][value]
419        self.assertTrue(IUserAccount(claus).checkPassword('mypwd1'))
420        return
421
422    def test_activate_deactivate_buttons(self):
423        self.browser.addHeader('Authorization', 'Basic mgr:mgrpw')
424        self.browser.open(self.customer_path)
425        self.browser.getLink("Deactivate").click()
426        self.assertTrue(
427            'Customer account has been deactivated.' in self.browser.contents)
428        self.assertTrue(
429            'Base Data (account deactivated)' in self.browser.contents)
430        self.assertTrue(self.customer.suspended)
431        self.browser.getLink("Activate").click()
432        self.assertTrue(
433            'Customer account has been activated.' in self.browser.contents)
434        self.assertFalse(
435            'Base Data (account deactivated)' in self.browser.contents)
436        self.assertFalse(self.customer.suspended)
437        # History messages have been added ...
438        self.browser.getLink("History").click()
439        self.assertTrue(
440            'Customer account deactivated by Manager<br />' in self.browser.contents)
441        self.assertTrue(
442            'Customer account activated by Manager<br />' in self.browser.contents)
443        # ... and actions have been logged.
444        logfile = os.path.join(
445            self.app['datacenter'].storage, 'logs', 'customers.log')
446        logcontent = open(logfile).read()
447        self.assertTrue('zope.mgr - customers.browser.CustomerDeactivatePage - '
448                        'K1000000 - account deactivated' in logcontent)
449        self.assertTrue('zope.mgr - customers.browser.CustomerActivatePage - '
450                        'K1000000 - account activated' in logcontent)
451
452
453    def test_login_as_customer(self):
454        # CustomerImpersonators can login as customer
455        # Create clearance officer
456        self.app['users'].addUser('mrofficer', 'mrofficersecret')
457        self.app['users']['mrofficer'].email = 'mrofficer@foo.ng'
458        self.app['users']['mrofficer'].title = 'Harry Actor'
459        prmglobal = IPrincipalRoleManager(self.app)
460        prmglobal.assignRoleToPrincipal('waeup.CustomerImpersonator', 'mrofficer')
461        prmglobal.assignRoleToPrincipal('waeup.CustomersManager', 'mrofficer')
462        # Login as customer impersonator
463        self.browser.open(self.login_path)
464        self.browser.getControl(name="form.login").value = 'mrofficer'
465        self.browser.getControl(name="form.password").value = 'mrofficersecret'
466        self.browser.getControl("Login").click()
467        self.assertMatches('...You logged in...', self.browser.contents)
468        self.browser.open(self.customer_path)
469        self.browser.getLink("Login as").click()
470        self.browser.getControl("Set password now").click()
471        temp_password = self.browser.getControl(name='form.password').value
472        self.browser.getControl("Login now").click()
473        self.assertMatches(
474            '...You successfully logged in as...', self.browser.contents)
475        # We are logged in as customer and can see the 'My Data' tab
476        self.assertMatches(
477            '...<a href="#" class="dropdown-toggle" data-toggle="dropdown">...',
478            self.browser.contents)
479        self.assertMatches(
480            '...My Data...',
481            self.browser.contents)
482        self.browser.getLink("Logout").click()
483        # The customer can't login with the original password ...
484        self.browser.open(self.login_path)
485        self.browser.getControl(name="form.login").value = self.customer_id
486        self.browser.getControl(name="form.password").value = 'spwd'
487        self.browser.getControl("Login").click()
488        self.assertMatches(
489            '...Your account has been temporarily deactivated...',
490            self.browser.contents)
491        # ... but with the temporary password
492        self.browser.open(self.login_path)
493        self.browser.getControl(name="form.login").value = self.customer_id
494        self.browser.getControl(name="form.password").value = temp_password
495        self.browser.getControl("Login").click()
496        self.assertMatches('...You logged in...', self.browser.contents)
497        # Creation of temp_password is properly logged
498        logfile = os.path.join(
499            self.app['datacenter'].storage, 'logs', 'customers.log')
500        logcontent = open(logfile).read()
501        self.assertTrue(
502            'mrofficer - customers.browser.LoginAsCustomerStep1 - K1000000 - '
503            'temp_password generated: %s' % temp_password in logcontent)
504
505class CustomerUITests(CustomersFullSetup):
506    # Tests for Customer class views and pages
507
508    def test_customer_change_password(self):
509        # Customers can change the password
510        self.customer.personal_updated = datetime.utcnow()
511        self.browser.open(self.login_path)
512        self.browser.getControl(name="form.login").value = self.customer_id
513        self.browser.getControl(name="form.password").value = 'spwd'
514        self.browser.getControl("Login").click()
515        self.assertEqual(self.browser.url, self.customer_path)
516        self.assertTrue('You logged in' in self.browser.contents)
517        # Change password
518        self.browser.getLink("Change password").click()
519        self.browser.getControl(name="change_password").value = 'pw'
520        self.browser.getControl(
521            name="change_password_repeat").value = 'pw'
522        self.browser.getControl("Save").click()
523        self.assertTrue('Password must have at least' in self.browser.contents)
524        self.browser.getControl(name="change_password").value = 'new_password'
525        self.browser.getControl(
526            name="change_password_repeat").value = 'new_passssword'
527        self.browser.getControl("Save").click()
528        self.assertTrue('Passwords do not match' in self.browser.contents)
529        self.browser.getControl(name="change_password").value = 'new_password'
530        self.browser.getControl(
531            name="change_password_repeat").value = 'new_password'
532        self.browser.getControl("Save").click()
533        self.assertTrue('Password changed' in self.browser.contents)
534        # We are still logged in. Changing the password hasn't thrown us out.
535        self.browser.getLink("Base Data").click()
536        self.assertEqual(self.browser.url, self.customer_path)
537        # We can logout
538        self.browser.getLink("Logout").click()
539        self.assertTrue('You have been logged out' in self.browser.contents)
540        self.assertEqual(self.browser.url, 'http://localhost/app/index')
541        # We can login again with the new password
542        self.browser.getLink("Login").click()
543        self.browser.open(self.login_path)
544        self.browser.getControl(name="form.login").value = self.customer_id
545        self.browser.getControl(name="form.password").value = 'new_password'
546        self.browser.getControl("Login").click()
547        self.assertEqual(self.browser.url, self.customer_path)
548        self.assertTrue('You logged in' in self.browser.contents)
549        return
550
551    def test_customer_upload_passport(self):
552        # Customer cant login if their password is not set
553        IWorkflowInfo(self.customer).fireTransition('start')
554        self.browser.open(self.login_path)
555        self.browser.getControl(name="form.login").value = self.customer_id
556        self.browser.getControl(name="form.password").value = 'spwd'
557        self.browser.getControl("Login").click()
558        self.assertMatches(
559            '...You logged in...', self.browser.contents)
560        # Admitted customer can upload a passport picture
561        self.browser.getLink("Change portrait").click()
562        ctrl = self.browser.getControl(name='passportuploadedit')
563        file_obj = open(SAMPLE_IMAGE, 'rb')
564        file_ctrl = ctrl.mech_control
565        file_ctrl.add_file(file_obj, filename='my_photo.jpg')
566        self.browser.getControl(
567            name='upload_passportuploadedit').click()
568        self.assertTrue(
569            'src="http://localhost/app/customers/K1000000/passport.jpg"'
570            in self.browser.contents)
571
572    def test_customer_baseedit(self):
573        # Customers can change the password
574        self.customer.personal_updated = datetime.utcnow()
575        self.browser.open(self.login_path)
576        self.browser.getControl(name="form.login").value = self.customer_id
577        self.browser.getControl(name="form.password").value = 'spwd'
578        self.browser.getControl("Login").click()
579        self.assertEqual(self.browser.url, self.customer_path)
580        self.assertTrue('You logged in' in self.browser.contents)
581        self.browser.getLink("Edit").click()
582        self.browser.getControl(name="form.email").value = 'new_email@aa.ng'
583        self.browser.getControl("Save").click()
584        self.assertMatches('...Form has been saved...',
585                           self.browser.contents)
586        # Customer can view history
587        self.browser.getLink("History").click()
588        self.assertMatches('...Customer record created by system...',
589            self.browser.contents)
590
591    def test_customer_login(self):
592        # Customer cant login if their password is not set
593        self.customer.password = None
594        self.browser.open(self.login_path)
595        self.browser.getControl(name="form.login").value = self.customer_id
596        self.browser.getControl(name="form.password").value = 'spwd'
597        self.browser.getControl("Login").click()
598        self.assertTrue(
599            'You entered invalid credentials.' in self.browser.contents)
600        # We set the password again
601        IUserAccount(
602            self.app['customers'][self.customer_id]).setPassword('spwd')
603        # Customers can't login if their account is suspended/deactivated
604        self.customer.suspended = True
605        self.browser.open(self.login_path)
606        self.browser.getControl(name="form.login").value = self.customer_id
607        self.browser.getControl(name="form.password").value = 'spwd'
608        self.browser.getControl("Login").click()
609        self.assertMatches(
610            '...<div class="alert alert-warning">'
611            'Your account has been deactivated.</div>...', self.browser.contents)
612        # If suspended_comment is set this message will be flashed instead
613        self.customer.suspended_comment = u'Aetsch baetsch!'
614        self.browser.getControl(name="form.login").value = self.customer_id
615        self.browser.getControl(name="form.password").value = 'spwd'
616        self.browser.getControl("Login").click()
617        self.assertMatches(
618            '...<div class="alert alert-warning">Aetsch baetsch!</div>...',
619            self.browser.contents)
620        self.customer.suspended = False
621        # Customers can't login if a temporary password has been set and
622        # is not expired
623        self.app['customers'][self.customer_id].setTempPassword(
624            'anybody', 'temp_spwd')
625        self.browser.open(self.login_path)
626        self.browser.getControl(name="form.login").value = self.customer_id
627        self.browser.getControl(name="form.password").value = 'spwd'
628        self.browser.getControl("Login").click()
629        self.assertMatches(
630            '...Your account has been temporarily deactivated...',
631            self.browser.contents)
632        # The customer can login with the temporary password
633        self.browser.open(self.login_path)
634        self.browser.getControl(name="form.login").value = self.customer_id
635        self.browser.getControl(name="form.password").value = 'temp_spwd'
636        self.browser.getControl("Login").click()
637        self.assertMatches(
638            '...You logged in...', self.browser.contents)
639        # Customer can view the base data
640        self.browser.open(self.customer_path)
641        self.assertEqual(self.browser.headers['Status'], '200 Ok')
642        self.assertEqual(self.browser.url, self.customer_path)
643        # When the password expires ...
644        delta = timedelta(minutes=11)
645        self.app['customers'][self.customer_id].temp_password[
646            'timestamp'] = datetime.utcnow() - delta
647        self.app['customers'][self.customer_id]._p_changed = True
648        # ... the customer will be automatically logged out
649        self.assertRaises(
650            Unauthorized, self.browser.open, self.customer_path)
651        # Then the customer can login with the original password
652        self.browser.open(self.login_path)
653        self.browser.getControl(name="form.login").value = self.customer_id
654        self.browser.getControl(name="form.password").value = 'spwd'
655        self.browser.getControl("Login").click()
656        self.assertMatches(
657            '...You logged in...', self.browser.contents)
658
659    def test_change_password_request(self):
660        self.browser.open('http://localhost/app/changepw')
661        self.browser.getControl(name="form.identifier").value = '123'
662        self.browser.getControl(name="form.email").value = 'aa@aa.ng'
663        self.browser.getControl("Send login credentials").click()
664        self.assertTrue('An email with' in self.browser.contents)
665
666class CustomerRequestPWTests(CustomersFullSetup):
667    # Tests for customer registration
668
669    layer = FunctionalLayer
670
671    def test_request_pw(self):
672        # Customer with wrong number can't be found.
673        self.browser.open('http://localhost/app/requestpw')
674        self.browser.getControl(name="form.firstname").value = 'Anna'
675        self.browser.getControl(name="form.number").value = 'anynumber'
676        self.browser.getControl(name="form.email").value = 'xx@yy.zz'
677        self.browser.getControl("Send login credentials").click()
678        self.assertTrue('No customer record found.'
679            in self.browser.contents)
680        # Anonymous is not informed that firstname verification failed.
681        # It seems that the record doesn't exist.
682        self.browser.open('http://localhost/app/requestpw')
683        self.browser.getControl(name="form.firstname").value = 'Johnny'
684        self.browser.getControl(name="form.number").value = '123'
685        self.browser.getControl(name="form.email").value = 'xx@yy.zz'
686        self.browser.getControl("Send login credentials").click()
687        self.assertTrue('No customer record found.'
688            in self.browser.contents)
689        # Even with the correct firstname we can't register if a
690        # password has been set and used.
691        self.browser.getControl(name="form.firstname").value = 'Anna'
692        self.browser.getControl(name="form.number").value = '123'
693        self.browser.getControl("Send login credentials").click()
694        self.assertTrue('Your password has already been set and used.'
695            in self.browser.contents)
696        self.browser.open('http://localhost/app/requestpw')
697        self.app['customers'][self.customer_id].password = None
698        # The firstname field, used for verification, is not case-sensitive.
699        self.browser.getControl(name="form.firstname").value = 'aNNa'
700        self.browser.getControl(name="form.number").value = '123'
701        self.browser.getControl(name="form.email").value = 'new@yy.zz'
702        self.browser.getControl("Send login credentials").click()
703        # Yeah, we succeded ...
704        self.assertTrue('Your password request was successful.'
705            in self.browser.contents)
706        # ... and  customer can be found in the catalog via the email address
707        cat = queryUtility(ICatalog, name='customers_catalog')
708        results = list(
709            cat.searchResults(
710            email=('new@yy.zz', 'new@yy.zz')))
711        self.assertEqual(self.customer,results[0])
712        logfile = os.path.join(
713            self.app['datacenter'].storage, 'logs', 'main.log')
714        logcontent = open(logfile).read()
715        self.assertTrue('zope.anybody - customers.browser.CustomerRequestPasswordPage - '
716                        '123 (K1000000) - new@yy.zz' in logcontent)
717        return
718
719class CustomerDataExportTests(CustomersFullSetup, FunctionalAsyncTestCase):
720    # Tests for CustomersContainer class views and pages
721
722    layer = FunctionalLayer
723
724    def wait_for_export_job_completed(self):
725        # helper function waiting until the current export job is completed
726        manager = getUtility(IJobManager)
727        job_id = self.app['datacenter'].running_exports[0][0]
728        job = manager.get(job_id)
729        wait_for_result(job)
730        return job_id
731
732    def test_datacenter_export(self):
733        self.browser.addHeader('Authorization', 'Basic mgr:mgrpw')
734        self.browser.open('http://localhost/app/datacenter/@@export')
735        self.browser.getControl(name="exporter").value = ['customers']
736        self.browser.getControl("Create CSV file").click()
737
738        # When the job is finished and we reload the page...
739        job_id = self.wait_for_export_job_completed()
740        # ... the csv file can be downloaded ...
741        self.browser.open('http://localhost/app/datacenter/@@export')
742        self.browser.getLink("Download").click()
743        self.assertEqual(self.browser.headers['content-type'],
744            'text/csv; charset=UTF-8')
745        self.assertTrue(
746            'filename="WAeUP.Ikoba_customers_%s.csv' % job_id in
747            self.browser.headers['content-disposition'])
748        self.assertEqual(len(self.app['datacenter'].running_exports), 1)
749        job_id = self.app['datacenter'].running_exports[0][0]
750        # ... and discarded
751        self.browser.open('http://localhost/app/datacenter/@@export')
752        self.browser.getControl("Discard").click()
753        self.assertEqual(len(self.app['datacenter'].running_exports), 0)
754        # Creation, downloading and discarding is logged
755        logfile = os.path.join(
756            self.app['datacenter'].storage, 'logs', 'datacenter.log')
757        logcontent = open(logfile).read()
758        self.assertTrue(
759            'zope.mgr - browser.pages.ExportCSVPage - exported: '
760            'customers, job_id=%s'
761            % job_id in logcontent
762            )
763        self.assertTrue(
764            'zope.mgr - browser.pages.ExportCSVView - downloaded: '
765            'WAeUP.Ikoba_customers_%s.csv, job_id=%s'
766            % (job_id, job_id) in logcontent
767            )
768        self.assertTrue(
769            'zope.mgr - browser.pages.ExportCSVPage - discarded: '
770            'job_id=%s' % job_id in logcontent
771            )
772
773
774class CustomerDocumentUITests(CustomersFullSetup):
775    # Tests for CustomerDocument relates views and pages
776
777    def test_manage_document(self):
778        # Managers can access the pages of customer documentsconter
779        # and can perform actions
780        self.browser.addHeader('Authorization', 'Basic mgr:mgrpw')
781        self.browser.open(self.customer_path)
782        self.assertEqual(self.browser.headers['Status'], '200 Ok')
783        self.assertEqual(self.browser.url, self.customer_path)
784        self.browser.open(self.customer_path)
785        self.browser.getLink("Documents").click()
786        self.browser.getLink("Add document").click()
787        self.browser.getControl(name="doctype").value = ['generic']
788        self.browser.getControl("Create document").click()
789        self.assertTrue('Generic Document created.' in self.browser.contents)
790        document = self.customer['documents']['d102']
791
792        # Documents can be removed
793        ctrl = self.browser.getControl(name='val_id')
794        ctrl.getControl(value=document.document_id).selected = True
795        self.browser.getControl("Remove selected", index=0).click()
796        self.assertTrue('Successfully removed' in self.browser.contents)
797
798        # All actions are being logged
799        logfile = os.path.join(
800            self.app['datacenter'].storage, 'logs', 'customers.log')
801        logcontent = open(logfile).read()
802
803        self.assertTrue(
804            'INFO - zope.mgr - customers.browser.DocumentAddFormPage '
805            '- K1000000 - added: Generic Document %s'
806            % document.document_id in logcontent)
807
808        self.assertTrue(
809            'INFO - zope.mgr - customers.browser.DocumentsManageFormPage '
810            '- K1000000 - removed: %s'
811            % document.document_id in logcontent)
Note: See TracBrowser for help on using the repository browser.