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

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

Implement HREFDisplayWidget which renders a persistent object title inside an anchor element
referring to the object.

  • Property svn:keywords set to Id
File size: 60.3 KB
Line 
1## $Id: test_browser.py 12119 2014-12-02 14:38:31Z 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 (
43    IUserAccount, IJobManager, APPROVED, SUBMITTED)
44from waeup.ikoba.authentication import LocalRoleSetEvent
45from waeup.ikoba.tests.test_async import FunctionalAsyncTestCase
46from waeup.ikoba.documents.workflow import VERIFIED
47from waeup.ikoba.browser.tests.test_pdf import samples_dir
48
49PH_LEN = 15911  # Length of placeholder file
50
51SAMPLE_IMAGE = os.path.join(os.path.dirname(__file__), 'test_image.jpg')
52SAMPLE_IMAGE_BMP = os.path.join(os.path.dirname(__file__), 'test_image.bmp')
53SAMPLE_PDF = os.path.join(os.path.dirname(__file__), 'test_pdf.pdf')
54
55def lookup_submit_value(name, value, browser):
56    """Find a button with a certain value."""
57    for num in range(0, 100):
58        try:
59            button = browser.getControl(name=name, index=num)
60            if button.value.endswith(value):
61                return button
62        except IndexError:
63            break
64    return None
65
66class CustomersFullSetup(FunctionalTestCase):
67    # A test case that only contains a setup and teardown
68    #
69    # Complete setup for customers handlings is rather complex and
70    # requires lots of things created before we can start. This is a
71    # setup that does all this, creates a company etc.
72    # so that we do not have to bother with that in different
73    # test cases.
74
75    layer = FunctionalLayer
76
77    def setUp(self):
78        super(CustomersFullSetup, self).setUp()
79
80        # Setup a sample site for each test
81        app = Company()
82        self.dc_root = tempfile.mkdtemp()
83        app['datacenter'].setStoragePath(self.dc_root)
84
85        # Prepopulate the ZODB...
86        self.getRootFolder()['app'] = app
87        # we add the site immediately after creation to the
88        # ZODB. Catalogs and other local utilities are not setup
89        # before that step.
90        self.app = self.getRootFolder()['app']
91        # Set site here. Some of the following setup code might need
92        # to access grok.getSite() and should get our new app then
93        setSite(app)
94
95        # Add some products
96        self.product = createObject('waeup.Product')
97        self.product.product_id = u'SAM'
98        self.product.title = u'Our Samle Product'
99        self.product.contract_category = u'sample'
100        self.app['products'].addProduct(self.product)
101
102        # Add customer with subobjects
103        customer = createObject('waeup.Customer')
104        customer.firstname = u'Anna'
105        customer.lastname = u'Tester'
106        customer.reg_number = u'123'
107        customer.sex = u'm'
108        customer.email = 'aa@aa.ng'
109        customer.phone = u'1234'
110        customer.date_of_birth = date(1981, 2, 4)
111        self.app['customers'].addCustomer(customer)
112        self.customer_id = customer.customer_id
113        self.customer = self.app['customers'][self.customer_id]
114        self.document = createObject('waeup.CustomerSampleDocument')
115        self.document.title = u'My first document'
116        self.customer['documents'].addDocument(self.document)
117        self.contract = createObject('waeup.SampleContract')
118        self.contract.title = u'My first contract'
119        self.customer['contracts'].addContract(self.contract)
120
121        # Set password
122        IUserAccount(
123            self.app['customers'][self.customer_id]).setPassword('cpwd')
124
125        self.login_path = 'http://localhost/app/login'
126        self.container_path = 'http://localhost/app/customers'
127        self.manage_container_path = self.container_path + '/@@manage'
128        self.add_customer_path = self.container_path + '/addcustomer'
129        self.customer_path = self.container_path + '/' + self.customer_id
130        self.manage_customer_path = self.customer_path + '/manage_base'
131        self.trigtrans_path = self.customer_path + '/trigtrans'
132        self.history_path = self.customer_path + '/history'
133        self.documents_path = self.customer_path + '/documents'
134        self.contracts_path = self.customer_path + '/contracts'
135
136        self.app['configuration'].carry_over = True
137        configuration = createObject('waeup.SessionConfiguration')
138        self.app['configuration'].addSessionConfiguration(configuration)
139
140        # Update the catalog
141        notify(grok.ObjectModifiedEvent(self.customer))
142
143        # Put the prepopulated site into test ZODB and prepare test
144        # browser
145        self.browser = Browser()
146        self.browser.handleErrors = False
147
148    def tearDown(self):
149        super(CustomersFullSetup, self).tearDown()
150        clearSite()
151        shutil.rmtree(self.dc_root)
152
153
154
155class CustomersContainerUITests(CustomersFullSetup):
156    # Tests for CustomersContainer class views and pages
157
158    layer = FunctionalLayer
159
160    def test_anonymous_access(self):
161        # Anonymous users can't access customers containers
162        self.assertRaises(
163            Unauthorized, self.browser.open, self.container_path)
164        self.assertRaises(
165            Unauthorized, self.browser.open, self.manage_container_path)
166        return
167
168    def test_manage_access(self):
169        # Managers can access the view page of customers
170        # containers and can perform actions
171        self.browser.addHeader('Authorization', 'Basic mgr:mgrpw')
172        self.browser.open(self.container_path)
173        self.assertEqual(self.browser.headers['Status'], '200 Ok')
174        self.assertEqual(self.browser.url, self.container_path)
175        self.browser.getLink("Manage customer section").click()
176        self.assertEqual(self.browser.headers['Status'], '200 Ok')
177        self.assertEqual(self.browser.url, self.manage_container_path)
178        return
179
180    def test_add_search_delete_customers(self):
181        # Managers can add search and remove customers
182        self.browser.addHeader('Authorization', 'Basic mgr:mgrpw')
183        self.browser.open(self.manage_container_path)
184        self.browser.getLink("Add customer").click()
185        self.assertEqual(self.browser.headers['Status'], '200 Ok')
186        self.assertEqual(self.browser.url, self.add_customer_path)
187        self.browser.getControl(name="form.firstname").value = 'Bob'
188        self.browser.getControl(name="form.lastname").value = 'Tester'
189        self.browser.getControl(name="form.reg_number").value = '123'
190        self.browser.getControl("Create customer record").click()
191        self.assertTrue('Registration number exists already'
192            in self.browser.contents)
193        self.browser.getControl(name="form.reg_number").value = '1234'
194        self.browser.getControl("Create customer record").click()
195        self.assertTrue('Customer record created' in self.browser.contents)
196
197        # Registration must be unique
198        self.browser.getLink("Manage").click()
199        self.browser.getControl(name="form.reg_number").value = '123'
200        self.browser.getControl("Save").click()
201        self.assertMatches('...Registration number exists...',
202                           self.browser.contents)
203
204        # We can find a customer with a certain customer_id
205        self.browser.open(self.container_path)
206        self.browser.getControl("Find customer(s)").click()
207        self.assertTrue('Empty search string' in self.browser.contents)
208        self.browser.getControl(name="searchtype").value = ['customer_id']
209        self.browser.getControl(name="searchterm").value = self.customer_id
210        self.browser.getControl("Find customer(s)").click()
211        self.assertTrue('Anna Tester' in self.browser.contents)
212
213        # We can find a customer by searching for all kind of name parts
214        self.browser.open(self.manage_container_path)
215        self.browser.getControl("Find customer(s)").click()
216        self.assertTrue('Empty search string' in self.browser.contents)
217        self.browser.getControl(name="searchtype").value = ['fullname']
218        self.browser.getControl(name="searchterm").value = 'Anna Tester'
219        self.browser.getControl("Find customer(s)").click()
220        self.assertTrue('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 = 'Anna'
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 = 'An'
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 = 'An*'
239        self.browser.getControl("Find customer(s)").click()
240        self.assertTrue('Anna Tester' in self.browser.contents)
241        self.browser.open(self.manage_container_path)
242        self.browser.getControl(name="searchtype").value = ['fullname']
243        self.browser.getControl(name="searchterm").value = 'tester'
244        self.browser.getControl("Find customer(s)").click()
245        self.assertTrue('Anna Tester' in self.browser.contents)
246        self.browser.open(self.manage_container_path)
247        self.browser.getControl(name="searchtype").value = ['fullname']
248        self.browser.getControl(name="searchterm").value = 'Tester Ana'
249        self.browser.getControl("Find customer(s)").click()
250        self.assertFalse('Anna Tester' in self.browser.contents)
251        self.browser.open(self.manage_container_path)
252        self.browser.getControl(name="searchtype").value = ['fullname']
253        self.browser.getControl(name="searchterm").value = 'Tester Anna'
254        self.browser.getControl("Find customer(s)").click()
255        self.assertTrue('Anna Tester' in self.browser.contents)
256        # The old searchterm will be used again
257        self.browser.getControl("Find customer(s)").click()
258        self.assertTrue('Anna Tester' in self.browser.contents)
259
260        # We can find suspended customers
261        self.customer.suspended = True
262        notify(grok.ObjectModifiedEvent(self.customer))
263        self.browser.open(self.manage_container_path)
264        self.browser.getControl(name="searchtype").value = ['suspended']
265        self.browser.getControl("Find customer(s)").click()
266        self.assertTrue('Anna Tester' in self.browser.contents)
267
268        # Removed customers won't be found
269        ctrl = self.browser.getControl(name='entries')
270        ctrl.getControl(value=self.customer_id).selected = True
271        self.browser.getControl("Remove selected", index=0).click()
272        self.assertTrue('Successfully removed' in self.browser.contents)
273        self.browser.getControl(name="searchtype").value = ['customer_id']
274        self.browser.getControl(name="searchterm").value = self.customer_id
275        self.browser.getControl("Find customer(s)").click()
276        self.assertTrue('No customer found' in self.browser.contents)
277        return
278
279class OfficerUITests(CustomersFullSetup):
280    # Tests for Customer class views and pages
281
282    def test_basic_auth(self):
283        self.browser.addHeader('Authorization', 'Basic mgr:mgrpw')
284        self.browser.open('http://localhost/app')
285        self.browser.getLink("Logout").click()
286        self.assertTrue('You have been logged out' in self.browser.contents)
287        # But we are still logged in since we've used basic authentication here.
288        # Wikipedia says: Existing browsers retain authentication information
289        # until the tab or browser is closed or the user clears the history.
290        # HTTP does not provide a method for a server to direct clients to
291        # discard these cached credentials. This means that there is no
292        # effective way for a server to "log out" the user without closing
293        # the browser. This is a significant defect that requires browser
294        # manufacturers to support a "logout" user interface element ...
295        self.assertTrue('Manager' in self.browser.contents)
296
297    def test_basic_auth_base64(self):
298        auth_token = base64.b64encode('mgr:mgrpw')
299        self.browser.addHeader('Authorization', 'Basic %s' % auth_token)
300        self.browser.open(self.manage_container_path)
301        self.assertEqual(self.browser.headers['Status'], '200 Ok')
302
303    def test_manage_access(self):
304        # Managers can access the pages of customers
305        # and can perform actions
306        self.browser.addHeader('Authorization', 'Basic mgr:mgrpw')
307        self.browser.open(self.customer_path)
308        self.assertEqual(self.browser.headers['Status'], '200 Ok')
309        self.assertEqual(self.browser.url, self.customer_path)
310        self.browser.getLink("Transition").click()
311        self.assertEqual(self.browser.headers['Status'], '200 Ok')
312        # Managers can trigger transitions
313        self.browser.getControl(name="transition").value = ['start']
314        self.browser.getControl("Save").click()
315        # Managers can edit base
316        self.browser.open(self.customer_path)
317        self.browser.getLink("Manage").click()
318        self.assertEqual(self.browser.url, self.manage_customer_path)
319        self.assertEqual(self.browser.headers['Status'], '200 Ok')
320        self.browser.getControl(name="form.firstname").value = 'John'
321        self.browser.getControl(name="form.lastname").value = 'Tester'
322        self.browser.getControl(name="form.reg_number").value = '345'
323        self.browser.getControl(name="password").value = 'secret'
324        self.browser.getControl(name="control_password").value = 'secret'
325        self.browser.getControl("Save").click()
326        self.assertMatches('...Form has been saved...',
327                           self.browser.contents)
328
329    def test_manage_contact_customer(self):
330        # Managers can contact customer
331        self.browser.addHeader('Authorization', 'Basic mgr:mgrpw')
332        self.customer.email = None
333        self.browser.open(self.customer_path)
334        self.browser.getLink("Send email").click()
335        self.browser.getControl(name="form.subject").value = 'Important subject'
336        self.browser.getControl(name="form.body").value = 'Hello!'
337        self.browser.getControl("Send message now").click()
338        self.assertTrue('An smtp server error occurred' in self.browser.contents)
339        self.customer.email = 'xx@yy.zz'
340        self.browser.getControl("Send message now").click()
341        self.assertTrue('Your message has been sent' in self.browser.contents)
342        return
343
344    def test_manage_upload_passport(self):
345        # Managers can upload a file via the CustomerBaseManageFormPage
346        self.browser.addHeader('Authorization', 'Basic mgr:mgrpw')
347        self.browser.open(self.manage_customer_path)
348        image = open(SAMPLE_IMAGE_BMP, 'rb')
349        ctrl = self.browser.getControl(name='passportmanageupload')
350        file_ctrl = ctrl.mech_control
351        file_ctrl.add_file(image, filename='my_photo.bmp')
352        self.browser.getControl(
353            name='upload_passportmanageupload').click()
354        self.assertTrue('jpg file extension expected'
355            in self.browser.contents)
356        ctrl = self.browser.getControl(name='passportmanageupload')
357        file_ctrl = ctrl.mech_control
358        image = open(SAMPLE_IMAGE, 'rb')
359        file_ctrl.add_file(image, filename='my_photo.jpg')
360        self.browser.getControl(
361            name='upload_passportmanageupload').click()
362        self.assertTrue(
363            'src="http://localhost/app/customers/K1000000/passport.jpg"'
364            in self.browser.contents)
365        # We remove the passport file again
366        self.browser.open(self.manage_customer_path)
367        self.browser.getControl('Delete').click()
368        self.assertTrue('passport.jpg deleted' in self.browser.contents)
369
370
371    def test_manage_workflow(self):
372        # Managers can pass through the whole workflow
373        self.browser.addHeader('Authorization', 'Basic mgr:mgrpw')
374        customer = self.app['customers'][self.customer_id]
375        self.browser.open(self.trigtrans_path)
376        self.browser.getControl(name="transition").value = ['start']
377        self.browser.getControl("Save").click()
378        self.browser.getControl(name="transition").value = ['request']
379        self.browser.getControl("Save").click()
380        self.browser.getControl(name="transition").value = ['reject']
381        self.browser.getControl("Save").click()
382        self.browser.getControl(name="transition").value = ['request']
383        self.browser.getControl("Save").click()
384        self.browser.getControl(name="transition").value = ['approve']
385        self.browser.getControl("Save").click()
386        self.browser.getControl(name="transition").value = ['reset1']
387        self.browser.getControl("Save").click()
388        return
389
390    def test_manage_import(self):
391        # Managers can import customer data files
392        datacenter_path = 'http://localhost/app/datacenter'
393        # Prepare a csv file for customers
394        open('customers.csv', 'wb').write(
395"""firstname,lastname,reg_number,date_of_birth,email,phone,sex,password
396Aaren,Pieri,1,1990-01-02,aa@aa.ng,1234,m,mypwd1
397Claus,Finau,2,1990-01-03,aa@aa.ng,1234,m,mypwd1
398Brit,Berson,2,1990-01-04,aa@aa.ng,1234,m,mypwd1
399""")
400        self.browser.addHeader('Authorization', 'Basic mgr:mgrpw')
401        self.browser.open(datacenter_path)
402        self.browser.getLink('Upload data').click()
403        filecontents = StringIO(open('customers.csv', 'rb').read())
404        filewidget = self.browser.getControl(name='uploadfile:file')
405        filewidget.add_file(filecontents, 'text/plain', 'customers.csv')
406        self.browser.getControl(name='SUBMIT').click()
407        self.browser.getLink('Process data').click()
408        button = lookup_submit_value(
409            'select', 'customers_zope.mgr.csv', self.browser)
410        button.click()
411        importerselect = self.browser.getControl(name='importer')
412        modeselect = self.browser.getControl(name='mode')
413        importerselect.getControl('Customer Processor').selected = True
414        modeselect.getControl(value='create').selected = True
415        self.browser.getControl('Proceed to step 3').click()
416        self.assertTrue('Header fields OK' in self.browser.contents)
417        self.browser.getControl('Perform import').click()
418        self.assertTrue('Processing of 1 rows failed' in self.browser.contents)
419        self.assertTrue('Successfully processed 2 rows' in self.browser.contents)
420        self.assertTrue('Batch processing finished' in self.browser.contents)
421
422        # The customers are properly indexed and we can
423        # thus find a customer in  the department
424        self.browser.open(self.manage_container_path)
425        # We can search for a new customer by name ...
426        self.browser.getControl(name="searchtype").value = ['fullname']
427        self.browser.getControl(name="searchterm").value = 'Claus'
428        self.browser.getControl("Find customer(s)").click()
429        self.assertTrue('Claus Finau' in self.browser.contents)
430        # ... and check if the imported password has been properly set
431        ctrl = self.browser.getControl(name='entries')
432        value = ctrl.options[0]
433        claus = self.app['customers'][value]
434        self.assertTrue(IUserAccount(claus).checkPassword('mypwd1'))
435        return
436
437    def test_activate_deactivate_buttons(self):
438        self.browser.addHeader('Authorization', 'Basic mgr:mgrpw')
439        self.browser.open(self.customer_path)
440        self.browser.getLink("Deactivate").click()
441        self.assertTrue(
442            'Customer account has been deactivated.' in self.browser.contents)
443        self.assertTrue(
444            'Base Data (account deactivated)' in self.browser.contents)
445        self.assertTrue(self.customer.suspended)
446        self.browser.getLink("Activate").click()
447        self.assertTrue(
448            'Customer account has been activated.' in self.browser.contents)
449        self.assertFalse(
450            'Base Data (account deactivated)' in self.browser.contents)
451        self.assertFalse(self.customer.suspended)
452        # History messages have been added ...
453        self.browser.getLink("History").click()
454        self.assertTrue(
455            'Customer account deactivated by Manager<br />' in self.browser.contents)
456        self.assertTrue(
457            'Customer account activated by Manager<br />' in self.browser.contents)
458        # ... and actions have been logged.
459        logfile = os.path.join(
460            self.app['datacenter'].storage, 'logs', 'customers.log')
461        logcontent = open(logfile).read()
462        self.assertTrue('zope.mgr - customers.browser.CustomerDeactivatePage - '
463                        'K1000000 - account deactivated' in logcontent)
464        self.assertTrue('zope.mgr - customers.browser.CustomerActivatePage - '
465                        'K1000000 - account activated' in logcontent)
466
467
468    def test_login_as_customer(self):
469        # CustomerImpersonators can login as customer
470        # Create clearance officer
471        self.app['users'].addUser('mrofficer', 'mrofficersecret')
472        self.app['users']['mrofficer'].email = 'mrofficer@foo.ng'
473        self.app['users']['mrofficer'].title = 'Harry Actor'
474        prmglobal = IPrincipalRoleManager(self.app)
475        prmglobal.assignRoleToPrincipal('waeup.CustomerImpersonator', 'mrofficer')
476        prmglobal.assignRoleToPrincipal('waeup.CustomersManager', 'mrofficer')
477        # Login as customer impersonator
478        self.browser.open(self.login_path)
479        self.browser.getControl(name="form.login").value = 'mrofficer'
480        self.browser.getControl(name="form.password").value = 'mrofficersecret'
481        self.browser.getControl("Login").click()
482        self.assertMatches('...You logged in...', self.browser.contents)
483        self.browser.open(self.customer_path)
484        self.browser.getLink("Login as").click()
485        self.browser.getControl("Set password now").click()
486        temp_password = self.browser.getControl(name='form.password').value
487        self.browser.getControl("Login now").click()
488        self.assertMatches(
489            '...You successfully logged in as...', self.browser.contents)
490        # We are logged in as customer and can see the 'My Data' tab
491        self.assertMatches(
492            '...<a href="#" class="dropdown-toggle" data-toggle="dropdown">...',
493            self.browser.contents)
494        self.assertMatches(
495            '...My Data...',
496            self.browser.contents)
497        self.browser.getLink("Logout").click()
498        # The customer can't login with the original password ...
499        self.browser.open(self.login_path)
500        self.browser.getControl(name="form.login").value = self.customer_id
501        self.browser.getControl(name="form.password").value = 'cpwd'
502        self.browser.getControl("Login").click()
503        self.assertMatches(
504            '...Your account has been temporarily deactivated...',
505            self.browser.contents)
506        # ... but with the temporary password
507        self.browser.open(self.login_path)
508        self.browser.getControl(name="form.login").value = self.customer_id
509        self.browser.getControl(name="form.password").value = temp_password
510        self.browser.getControl("Login").click()
511        self.assertMatches('...You logged in...', self.browser.contents)
512        # Creation of temp_password is properly logged
513        logfile = os.path.join(
514            self.app['datacenter'].storage, 'logs', 'customers.log')
515        logcontent = open(logfile).read()
516        self.assertTrue(
517            'mrofficer - customers.browser.LoginAsCustomerStep1 - K1000000 - '
518            'temp_password generated: %s' % temp_password in logcontent)
519
520
521class CustomerUITests(CustomersFullSetup):
522    # Tests for Customer class views and pages
523
524    def test_customer_change_password(self):
525        # Customers can change the password
526        self.customer.personal_updated = datetime.utcnow()
527        self.browser.open(self.login_path)
528        self.browser.getControl(name="form.login").value = self.customer_id
529        self.browser.getControl(name="form.password").value = 'cpwd'
530        self.browser.getControl("Login").click()
531        self.assertEqual(self.browser.url, self.customer_path)
532        self.assertTrue('You logged in' in self.browser.contents)
533        # Change password
534        self.browser.getLink("Change password").click()
535        self.browser.getControl(name="change_password").value = 'pw'
536        self.browser.getControl(
537            name="change_password_repeat").value = 'pw'
538        self.browser.getControl("Save").click()
539        self.assertTrue('Password must have at least' in self.browser.contents)
540        self.browser.getControl(name="change_password").value = 'new_password'
541        self.browser.getControl(
542            name="change_password_repeat").value = 'new_passssword'
543        self.browser.getControl("Save").click()
544        self.assertTrue('Passwords do not match' in self.browser.contents)
545        self.browser.getControl(name="change_password").value = 'new_password'
546        self.browser.getControl(
547            name="change_password_repeat").value = 'new_password'
548        self.browser.getControl("Save").click()
549        self.assertTrue('Password changed' in self.browser.contents)
550        # We are still logged in. Changing the password hasn't thrown us out.
551        self.browser.getLink("Base Data").click()
552        self.assertEqual(self.browser.url, self.customer_path)
553        # We can logout
554        self.browser.getLink("Logout").click()
555        self.assertTrue('You have been logged out' in self.browser.contents)
556        self.assertEqual(self.browser.url, 'http://localhost/app/index')
557        # We can login again with the new password
558        self.browser.getLink("Login").click()
559        self.browser.open(self.login_path)
560        self.browser.getControl(name="form.login").value = self.customer_id
561        self.browser.getControl(name="form.password").value = 'new_password'
562        self.browser.getControl("Login").click()
563        self.assertEqual(self.browser.url, self.customer_path)
564        self.assertTrue('You logged in' in self.browser.contents)
565        return
566
567    def test_customer_upload_passport(self):
568        # Customer cant login if their password is not set
569        IWorkflowInfo(self.customer).fireTransition('start')
570        self.browser.open(self.login_path)
571        self.browser.getControl(name="form.login").value = self.customer_id
572        self.browser.getControl(name="form.password").value = 'cpwd'
573        self.browser.getControl("Login").click()
574        self.assertMatches(
575            '...You logged in...', self.browser.contents)
576        # Admitted customer can upload a passport picture
577        self.browser.getLink("Change portrait").click()
578        ctrl = self.browser.getControl(name='passporteditupload')
579        file_obj = open(SAMPLE_IMAGE, 'rb')
580        file_ctrl = ctrl.mech_control
581        file_ctrl.add_file(file_obj, filename='my_photo.jpg')
582        self.browser.getControl(
583            name='upload_passporteditupload').click()
584        self.assertTrue(
585            'src="http://localhost/app/customers/K1000000/passport.jpg"'
586            in self.browser.contents)
587
588    def test_customer_baseedit(self):
589        # Customers can change the password
590        self.customer.personal_updated = datetime.utcnow()
591        self.browser.open(self.login_path)
592        self.browser.getControl(name="form.login").value = self.customer_id
593        self.browser.getControl(name="form.password").value = 'cpwd'
594        self.browser.getControl("Login").click()
595        self.assertEqual(self.browser.url, self.customer_path)
596        self.assertTrue('You logged in' in self.browser.contents)
597        self.browser.getLink("Edit").click()
598        self.browser.getControl(name="form.email").value = 'new_email@aa.ng'
599        self.browser.getControl("Save").click()
600        self.assertMatches('...Form has been saved...',
601                           self.browser.contents)
602        # Customer can view history
603        self.browser.getLink("History").click()
604        self.assertMatches('...Customer record created by system...',
605            self.browser.contents)
606
607    def test_customer_login(self):
608        # Customer cant login if their password is not set
609        self.customer.password = None
610        self.browser.open(self.login_path)
611        self.browser.getControl(name="form.login").value = self.customer_id
612        self.browser.getControl(name="form.password").value = 'cpwd'
613        self.browser.getControl("Login").click()
614        self.assertTrue(
615            'You entered invalid credentials.' in self.browser.contents)
616        # We set the password again
617        IUserAccount(
618            self.app['customers'][self.customer_id]).setPassword('cpwd')
619        # Customers can't login if their account is suspended/deactivated
620        self.customer.suspended = True
621        self.browser.open(self.login_path)
622        self.browser.getControl(name="form.login").value = self.customer_id
623        self.browser.getControl(name="form.password").value = 'cpwd'
624        self.browser.getControl("Login").click()
625        self.assertMatches(
626            '...<div class="alert alert-warning">'
627            'Your account has been deactivated.</div>...', self.browser.contents)
628        # If suspended_comment is set this message will be flashed instead
629        self.customer.suspended_comment = u'Aetsch baetsch!'
630        self.browser.getControl(name="form.login").value = self.customer_id
631        self.browser.getControl(name="form.password").value = 'cpwd'
632        self.browser.getControl("Login").click()
633        self.assertMatches(
634            '...<div class="alert alert-warning">Aetsch baetsch!</div>...',
635            self.browser.contents)
636        self.customer.suspended = False
637        # Customers can't login if a temporary password has been set and
638        # is not expired
639        self.app['customers'][self.customer_id].setTempPassword(
640            'anybody', 'temp_cpwd')
641        self.browser.open(self.login_path)
642        self.browser.getControl(name="form.login").value = self.customer_id
643        self.browser.getControl(name="form.password").value = 'cpwd'
644        self.browser.getControl("Login").click()
645        self.assertMatches(
646            '...Your account has been temporarily deactivated...',
647            self.browser.contents)
648        # The customer can login with the temporary password
649        self.browser.open(self.login_path)
650        self.browser.getControl(name="form.login").value = self.customer_id
651        self.browser.getControl(name="form.password").value = 'temp_cpwd'
652        self.browser.getControl("Login").click()
653        self.assertMatches(
654            '...You logged in...', self.browser.contents)
655        # Customer can view the base data
656        self.browser.open(self.customer_path)
657        self.assertEqual(self.browser.headers['Status'], '200 Ok')
658        self.assertEqual(self.browser.url, self.customer_path)
659        # When the password expires ...
660        delta = timedelta(minutes=11)
661        self.app['customers'][self.customer_id].temp_password[
662            'timestamp'] = datetime.utcnow() - delta
663        self.app['customers'][self.customer_id]._p_changed = True
664        # ... the customer will be automatically logged out
665        self.assertRaises(
666            Unauthorized, self.browser.open, self.customer_path)
667        # Then the customer can login with the original password
668        self.browser.open(self.login_path)
669        self.browser.getControl(name="form.login").value = self.customer_id
670        self.browser.getControl(name="form.password").value = 'cpwd'
671        self.browser.getControl("Login").click()
672        self.assertMatches(
673            '...You logged in...', self.browser.contents)
674
675    def test_change_password_request(self):
676        self.browser.open('http://localhost/app/changepw')
677        self.browser.getControl(name="form.identifier").value = '123'
678        self.browser.getControl(name="form.email").value = 'aa@aa.ng'
679        self.browser.getControl("Send login credentials").click()
680        self.assertTrue('An email with' in self.browser.contents)
681
682class CustomerRegistrationTests(CustomersFullSetup):
683    # Tests for customer registration
684
685    layer = FunctionalLayer
686
687    def test_request_pw(self):
688        # Customer with wrong number can't be found.
689        self.browser.open('http://localhost/app/requestpw')
690        self.browser.getControl(name="form.firstname").value = 'Anna'
691        self.browser.getControl(name="form.number").value = 'anynumber'
692        self.browser.getControl(name="form.email").value = 'xx@yy.zz'
693        self.browser.getControl("Send login credentials").click()
694        self.assertTrue('No customer record found.'
695            in self.browser.contents)
696        # Anonymous is not informed that firstname verification failed.
697        # It seems that the record doesn't exist.
698        self.browser.open('http://localhost/app/requestpw')
699        self.browser.getControl(name="form.firstname").value = 'Johnny'
700        self.browser.getControl(name="form.number").value = '123'
701        self.browser.getControl(name="form.email").value = 'xx@yy.zz'
702        self.browser.getControl("Send login credentials").click()
703        self.assertTrue('No customer record found.'
704            in self.browser.contents)
705        # Even with the correct firstname we can't register if a
706        # password has been set and used.
707        self.browser.getControl(name="form.firstname").value = 'Anna'
708        self.browser.getControl(name="form.number").value = '123'
709        self.browser.getControl("Send login credentials").click()
710        self.assertTrue('Your password has already been set and used.'
711            in self.browser.contents)
712        self.browser.open('http://localhost/app/requestpw')
713        self.app['customers'][self.customer_id].password = None
714        # The firstname field, used for verification, is not case-sensitive.
715        self.browser.getControl(name="form.firstname").value = 'aNNa'
716        self.browser.getControl(name="form.number").value = '123'
717        self.browser.getControl(name="form.email").value = 'new@yy.zz'
718        self.browser.getControl("Send login credentials").click()
719        # Yeah, we succeded ...
720        self.assertTrue('Your request was successful.'
721            in self.browser.contents)
722        # ... and  customer can be found in the catalog via the email address
723        cat = queryUtility(ICatalog, name='customers_catalog')
724        results = list(
725            cat.searchResults(
726            email=('new@yy.zz', 'new@yy.zz')))
727        self.assertEqual(self.customer,results[0])
728        logfile = os.path.join(
729            self.app['datacenter'].storage, 'logs', 'main.log')
730        logcontent = open(logfile).read()
731        self.assertTrue('zope.anybody - customers.browser.CustomerRequestPasswordPage - '
732                        '123 (K1000000) - new@yy.zz' in logcontent)
733        return
734
735    def test_create_account(self):
736        # Customer with wrong number can't be found.
737        self.browser.open('http://localhost/app/createaccount')
738        self.browser.getControl(name="form.firstname").value = 'Ruben'
739        self.browser.getControl(name="form.lastname").value = 'Gonzales'
740        self.browser.getControl(name="form.email").value = 'newcustomer@xx.zz'
741        self.browser.getControl("Send login credentials").click()
742        self.assertTrue('Your request was successful.'
743            in self.browser.contents)
744        # ... and  customer can be found in the catalog via the email address
745        cat = queryUtility(ICatalog, name='customers_catalog')
746        results = list(
747            cat.searchResults(
748            email=('newcustomer@xx.zz', 'newcustomer@xx.zz')))
749        self.assertEqual(self.app['customers']['K1000001'], results[0])
750        self.assertEqual(self.app['customers']['K1000001'].firstname, 'Ruben')
751        self.assertEqual(self.app['customers']['K1000001'].lastname, 'Gonzales')
752        logfile = os.path.join(
753            self.app['datacenter'].storage, 'logs', 'main.log')
754        logcontent = open(logfile).read()
755        self.assertTrue('zope.anybody - customers.browser.CustomerCreateAccountPage - '
756                        'K1000001 - newcustomer@xx.zz' in logcontent)
757        return
758
759class CustomerDataExportTests(CustomersFullSetup, FunctionalAsyncTestCase):
760    # Tests for CustomersContainer class views and pages
761
762    layer = FunctionalLayer
763
764    def wait_for_export_job_completed(self):
765        # helper function waiting until the current export job is completed
766        manager = getUtility(IJobManager)
767        job_id = self.app['datacenter'].running_exports[0][0]
768        job = manager.get(job_id)
769        wait_for_result(job)
770        return job_id
771
772    def test_datacenter_export(self):
773        self.browser.addHeader('Authorization', 'Basic mgr:mgrpw')
774        self.browser.open('http://localhost/app/datacenter/@@export')
775        self.browser.getControl(name="exporter").value = ['customers']
776        self.browser.getControl("Create CSV file").click()
777
778        # When the job is finished and we reload the page...
779        job_id = self.wait_for_export_job_completed()
780        # ... the csv file can be downloaded ...
781        self.browser.open('http://localhost/app/datacenter/@@export')
782        self.browser.getLink("Download").click()
783        self.assertEqual(self.browser.headers['content-type'],
784            'text/csv; charset=UTF-8')
785        self.assertTrue(
786            'filename="WAeUP.Ikoba_customers_%s.csv' % job_id in
787            self.browser.headers['content-disposition'])
788        self.assertEqual(len(self.app['datacenter'].running_exports), 1)
789        job_id = self.app['datacenter'].running_exports[0][0]
790        # ... and discarded
791        self.browser.open('http://localhost/app/datacenter/@@export')
792        self.browser.getControl("Discard").click()
793        self.assertEqual(len(self.app['datacenter'].running_exports), 0)
794        # Creation, downloading and discarding is logged
795        logfile = os.path.join(
796            self.app['datacenter'].storage, 'logs', 'datacenter.log')
797        logcontent = open(logfile).read()
798        self.assertTrue(
799            'zope.mgr - browser.pages.ExportCSVPage - exported: '
800            'customers, job_id=%s'
801            % job_id in logcontent
802            )
803        self.assertTrue(
804            'zope.mgr - browser.pages.ExportCSVView - downloaded: '
805            'WAeUP.Ikoba_customers_%s.csv, job_id=%s'
806            % (job_id, job_id) in logcontent
807            )
808        self.assertTrue(
809            'zope.mgr - browser.pages.ExportCSVPage - discarded: '
810            'job_id=%s' % job_id in logcontent
811            )
812
813
814class DocumentUITests(CustomersFullSetup):
815    # Tests for CustomerSampleDocument relates views and pages
816
817    def test_manage_document(self):
818        # Managers can access the pages of customer documentsconter
819        # and can perform actions
820        self.browser.addHeader('Authorization', 'Basic mgr:mgrpw')
821        self.browser.open(self.customer_path)
822        self.assertEqual(self.browser.headers['Status'], '200 Ok')
823        self.assertEqual(self.browser.url, self.customer_path)
824        self.browser.open(self.customer_path)
825        self.browser.getLink("Documents").click()
826        self.browser.getLink("Add document").click()
827        self.browser.getControl(name="doctype").value = ['CustomerPDFDocument']
828        self.browser.getControl("Create document").click()
829        self.assertTrue('PDF Document created.' in self.browser.contents)
830        document = self.customer['documents']['d102']
831
832        # Document can be edited
833        self.browser.getLink("d102").click()
834        self.browser.getLink("Manage").click()
835        self.browser.getControl(name="form.title").value = 'My second doc'
836        self.browser.getControl("Save").click()
837        self.assertTrue('Form has been saved.' in self.browser.contents)
838        self.browser.getLink("View").click()
839        self.assertEqual(self.browser.url, self.documents_path + '/d102/index')
840
841        # Transitions can be performed
842        self.browser.getLink("Transition").click()
843        self.browser.getControl(name="transition").value = ['submit']
844        self.browser.getControl("Save").click()
845        self.browser.getControl(name="transition").value = ['verify']
846        self.browser.getControl("Save").click()
847        self.assertEqual(document.state, 'verified')
848
849        # Documents can be removed
850        self.browser.getLink("Documents").click()
851        ctrl = self.browser.getControl(name='val_id')
852        ctrl.getControl(value=document.document_id).selected = True
853        self.browser.getControl("Remove selected", index=0).click()
854        self.assertTrue('Successfully removed' in self.browser.contents)
855
856        # All actions are being logged
857        logfile = os.path.join(
858            self.app['datacenter'].storage, 'logs', 'customers.log')
859        logcontent = open(logfile).read()
860
861        self.assertTrue(
862            'INFO - zope.mgr - customers.browser.DocumentManageFormPage '
863            '- K1000000 - d102 - saved: title'
864            in logcontent)
865        self.assertTrue(
866            'INFO - zope.mgr - customers.browser.DocumentAddFormPage '
867            '- K1000000 - added: PDF Document %s'
868            % document.document_id in logcontent)
869        self.assertTrue(
870            'INFO - zope.mgr - customers.browser.DocumentsManageFormPage '
871            '- K1000000 - removed: %s'
872            % document.document_id in logcontent)
873
874    def test_edit_sample_document(self):
875        # Customers can manage documents under certain conditions
876        self.browser.open(self.login_path)
877        self.browser.getControl(name="form.login").value = self.customer_id
878        self.browser.getControl(name="form.password").value = 'cpwd'
879        self.browser.getControl("Login").click()
880        self.assertMatches(
881            '...You logged in...', self.browser.contents)
882        self.browser.getLink("Documents").click()
883        self.browser.getLink("Add document").click()
884        self.browser.getControl(name="doctype").value = ['CustomerSampleDocument']
885        self.browser.getControl("Create document").click()
886        self.assertTrue('Sample Document created.' in self.browser.contents)
887        document = self.customer['documents']['d102']
888
889        # Document can be edited ...
890        self.browser.getLink("d102").click()
891        self.browser.open(self.documents_path + '/d102/edit')
892        #self.browser.getLink("Edit").click()
893        self.assertTrue('The requested form is locked' in self.browser.contents)
894        # Customer is in wrong state
895        IWorkflowState(self.customer).setState(APPROVED)
896        self.browser.open(self.documents_path + '/d102/edit')
897        self.browser.getControl(name="form.title").value = 'My second doc'
898        self.browser.getControl("Save").click()
899        self.assertEqual(document.title, 'My second doc')
900        self.assertTrue('Form has been saved.' in self.browser.contents)
901        self.browser.getLink("View").click()
902        self.assertEqual(self.browser.url, self.documents_path + '/d102/index')
903        # Costumer can upload a document.
904        self.browser.getLink("Edit").click()
905        ctrl = self.browser.getControl(name='samplescaneditupload')
906        file_obj = open(SAMPLE_IMAGE, 'rb')
907        file_ctrl = ctrl.mech_control
908        file_ctrl.add_file(file_obj, filename='my_document.jpg')
909        self.browser.getControl(
910            name='upload_samplescaneditupload').click()
911        self.assertTrue(
912            'href="http://localhost/app/customers/K1000000/documents/d102/sample"'
913            in self.browser.contents)
914        # Costumer can submit the form. The form is also saved.
915        self.browser.getControl(name="form.title").value = 'My third doc'
916        self.browser.getControl("Final Submit").click()
917        self.assertEqual(document.title, 'My third doc')
918        self.assertEqual(document.state, 'submitted')
919        self.assertTrue('Document State: submitted for verification' in self.browser.contents)
920        # Customer can't edit the document once it has been submitted
921        self.browser.open(self.documents_path + '/d102/edit')
922        self.assertTrue('The requested form is locked' in self.browser.contents)
923
924    def test_manage_upload_sample_file(self):
925        # Managers can upload a file via the DocumentManageFormPage
926        # The image is stored even if form has errors
927        self.browser.addHeader('Authorization', 'Basic mgr:mgrpw')
928        self.browser.open(self.customer_path + '/documents/d101/manage')
929        # Create a pseudo image file and select it to be uploaded
930        image = open(SAMPLE_IMAGE, 'rb')
931        ctrl = self.browser.getControl(name='samplescanmanageupload')
932        file_ctrl = ctrl.mech_control
933        file_ctrl.add_file(image, filename='my_sample_scan.jpg')
934        # The Save action does not upload files
935        self.browser.getControl("Save").click() # submit form
936        self.assertFalse(
937            'href="http://localhost/app/customers/K1000000/documents/d101/sample"'
938            in self.browser.contents)
939        # ... but the correct upload submit button does
940        image = open(SAMPLE_IMAGE)
941        ctrl = self.browser.getControl(name='samplescanmanageupload')
942        file_ctrl = ctrl.mech_control
943        file_ctrl.add_file(image, filename='my_sample_scan.jpg')
944        self.browser.getControl(
945            name='upload_samplescanmanageupload').click()
946        self.assertTrue(
947            'href="http://localhost/app/customers/K1000000/documents/d101/sample"'
948            in self.browser.contents)
949        # Browsing the link shows a real image
950        self.browser.open('sample')
951        self.assertEqual(
952            self.browser.headers['content-type'], 'image/jpeg')
953        self.assertEqual(len(self.browser.contents), 2787)
954        # We can't reupload a file. The existing file must be deleted first.
955        self.browser.open(self.customer_path + '/documents/d101/manage')
956        self.assertFalse(
957            'upload_samplescanmanageupload' in self.browser.contents)
958        # File must be deleted first
959        self.browser.getControl(name='delete_samplescanmanageupload').click()
960        self.assertTrue(
961            'sample deleted' in self.browser.contents)
962        # Uploading a file which is bigger than 150k will raise an error
963        big_image = StringIO(open(SAMPLE_IMAGE, 'rb').read() * 75)
964        ctrl = self.browser.getControl(name='samplescanmanageupload')
965        file_ctrl = ctrl.mech_control
966        file_ctrl.add_file(big_image, filename='my_sample_scan.jpg')
967        self.browser.getControl(
968            name='upload_samplescanmanageupload').click()
969        self.assertTrue(
970            'Uploaded file is too big' in self.browser.contents)
971        # we do not rely on filename extensions given by uploaders
972        image = open(SAMPLE_IMAGE, 'rb') # a jpg-file
973        ctrl = self.browser.getControl(name='samplescanmanageupload')
974        file_ctrl = ctrl.mech_control
975        # tell uploaded file is bmp
976        file_ctrl.add_file(image, filename='my_sample_scan.bmp')
977        self.browser.getControl(
978            name='upload_samplescanmanageupload').click()
979        self.assertTrue(
980            # jpg file was recognized
981            'File sample.jpg uploaded.' in self.browser.contents)
982        # Delete file again
983        self.browser.getControl(name='delete_samplescanmanageupload').click()
984        self.assertTrue(
985            'sample deleted' in self.browser.contents)
986        # File names must meet several conditions
987        bmp_image = open(SAMPLE_IMAGE_BMP, 'rb')
988        ctrl = self.browser.getControl(name='samplescanmanageupload')
989        file_ctrl = ctrl.mech_control
990        file_ctrl.add_file(bmp_image, filename='my_sample_scan.bmp')
991        self.browser.getControl(
992            name='upload_samplescanmanageupload').click()
993        self.assertTrue('Only the following extensions are allowed'
994            in self.browser.contents)
995
996    def test_manage_upload_pdf_file(self):
997        # Managers can upload a file via the DocumentManageFormPage
998        # The image is stored even if form has errors
999        self.browser.addHeader('Authorization', 'Basic mgr:mgrpw')
1000        self.browser.open(self.customer_path + '/documents')
1001        self.browser.getLink("Add document").click()
1002        self.browser.getControl(name="doctype").value = ['CustomerPDFDocument']
1003        self.browser.getControl("Create document").click()
1004        self.browser.open(self.documents_path + '/d102/manage')
1005        # Create a pseudo image file and select it to be uploaded
1006        image = open(SAMPLE_IMAGE, 'rb')
1007        ctrl = self.browser.getControl(name='pdfscanmanageupload')
1008        file_ctrl = ctrl.mech_control
1009        file_ctrl.add_file(image, filename='my_sample_scan.jpg')
1010        self.browser.getControl(
1011            name='upload_pdfscanmanageupload').click()
1012        self.assertTrue(
1013            'pdf file extension expected' in self.browser.contents)
1014        ctrl = self.browser.getControl(name='pdfscanmanageupload')
1015        file_ctrl = ctrl.mech_control
1016        file_ctrl.add_file(image, filename='my_sample_scan.pdf')
1017        self.browser.getControl(
1018            name='upload_pdfscanmanageupload').click()
1019        self.assertTrue(
1020            'Could not determine file type' in self.browser.contents)
1021        pdf = open(SAMPLE_PDF, 'rb')
1022        ctrl = self.browser.getControl(name='pdfscanmanageupload')
1023        file_ctrl = ctrl.mech_control
1024        file_ctrl.add_file(pdf, filename='my_sample_scan.pdf')
1025        self.browser.getControl(
1026            name='upload_pdfscanmanageupload').click()
1027        self.assertTrue(
1028            'href="http://localhost/app/customers/K1000000/documents/d102/sample.pdf">PDF File</a>'
1029            in self.browser.contents)
1030        # Browsing the link shows a real pdf
1031        self.browser.open('sample.pdf')
1032        self.assertEqual(
1033            self.browser.headers['content-type'], 'application/pdf')
1034
1035    def test_view_slips(self):
1036        self.browser.addHeader('Authorization', 'Basic mgr:mgrpw')
1037        # Officers can open the document overview
1038        self.browser.open(self.customer_path + '/documents')
1039        self.browser.getLink("Download documents overview").click()
1040        self.assertEqual(self.browser.headers['Status'], '200 Ok')
1041        self.assertEqual(self.browser.headers['Content-Type'], 'application/pdf')
1042        path = os.path.join(samples_dir(), 'documents_overview_slip.pdf')
1043        open(path, 'wb').write(self.browser.contents)
1044        print "Sample PDF overview_slip.pdf written to %s" % path
1045        # Officers can open document slips
1046        self.browser.open(self.customer_path + '/documents/d101')
1047        self.browser.getLink("Download document slip").click()
1048        self.assertEqual(self.browser.headers['Status'], '200 Ok')
1049        self.assertEqual(self.browser.headers['Content-Type'], 'application/pdf')
1050        path = os.path.join(samples_dir(), 'document_slip.pdf')
1051        open(path, 'wb').write(self.browser.contents)
1052        print "Sample document_slip.pdf written to %s" % path
1053
1054
1055class ContractUITests(CustomersFullSetup):
1056    # Tests for CustomerSampleContract relates views and pages
1057
1058    def test_manage_contract(self):
1059        # Managers can access the pages of customer contractsconter
1060        # and can perform actions
1061        self.browser.addHeader('Authorization', 'Basic mgr:mgrpw')
1062        self.browser.open(self.customer_path)
1063        self.assertEqual(self.browser.headers['Status'], '200 Ok')
1064        self.assertEqual(self.browser.url, self.customer_path)
1065        self.browser.open(self.customer_path)
1066        self.browser.getLink("Contracts").click()
1067        self.browser.getLink("Add contract").click()
1068        self.browser.getControl(name="contype").value = ['SampleContract']
1069        self.browser.getControl("Create contract").click()
1070        self.assertTrue('Sample Contract created.' in self.browser.contents)
1071        contract = self.customer['contracts']['c102']
1072
1073        # Contract can be edited
1074        self.browser.getLink("c102").click()
1075        self.browser.getLink("Manage").click()
1076        self.browser.getControl(name="form.product_object").value = ['SAM']
1077        self.browser.getControl(name="form.title").value = 'My second contract'
1078        self.browser.getControl("Save").click()
1079        self.assertTrue('Form has been saved.' in self.browser.contents)
1080        self.browser.getLink("View").click()
1081        self.assertEqual(self.browser.url, self.contracts_path + '/c102/index')
1082
1083        # Transitions can be performed
1084        self.browser.getLink("Transition").click()
1085        self.browser.getControl(name="transition").value = ['submit']
1086        self.browser.getControl("Save").click()
1087        self.browser.getControl(name="transition").value = ['approve']
1088        self.browser.getControl("Save").click()
1089        self.assertEqual(contract.state, 'approved')
1090
1091        # Contracts can be removed
1092        self.browser.getLink("Contracts").click()
1093        ctrl = self.browser.getControl(name='val_id')
1094        ctrl.getControl(value=contract.contract_id).selected = True
1095        self.browser.getControl("Remove selected", index=0).click()
1096        self.assertTrue('Successfully removed' in self.browser.contents)
1097
1098        # All actions are being logged
1099        logfile = os.path.join(
1100            self.app['datacenter'].storage, 'logs', 'customers.log')
1101        logcontent = open(logfile).read()
1102        self.assertTrue(
1103            'INFO - zope.mgr - customers.browser.ContractManageFormPage '
1104            '- K1000000 - c102 - saved: title'
1105            in logcontent)
1106        self.assertTrue(
1107            'INFO - zope.mgr - customers.browser.ContractAddFormPage '
1108            '- K1000000 - added: Sample Contract %s'
1109            % contract.contract_id in logcontent)
1110        self.assertTrue(
1111            'INFO - zope.mgr - customers.browser.ContractsManageFormPage '
1112            '- K1000000 - removed: %s'
1113            % contract.contract_id in logcontent)
1114
1115    def test_edit_sample_contract(self):
1116        # We add a second product.
1117        product = createObject('waeup.Product')
1118        product.product_id = u'LIC'
1119        product.title = u'Our License Product'
1120        product.contract_category = u'license'
1121        self.app['products'].addProduct(product)
1122        # Customers can manage contracts under certain conditions
1123        self.browser.open(self.login_path)
1124        self.browser.getControl(name="form.login").value = self.customer_id
1125        self.browser.getControl(name="form.password").value = 'cpwd'
1126        self.browser.getControl("Login").click()
1127        self.assertMatches(
1128            '...You logged in...', self.browser.contents)
1129        self.browser.getLink("Contracts").click()
1130        self.browser.getLink("Add contract").click()
1131        self.browser.getControl(name="contype").value = ['SampleContract']
1132        self.browser.getControl("Create contract").click()
1133        self.assertTrue('Sample Contract created.' in self.browser.contents)
1134        contract = self.customer['contracts']['c102']
1135        # Contract can be edited ...
1136        self.browser.open(self.contracts_path + '/c102/edit')
1137        #self.browser.getLink("Edit").click()
1138        self.assertTrue('The requested form is locked' in self.browser.contents)
1139        # Customer is in wrong state
1140        IWorkflowState(self.customer).setState(APPROVED)
1141        self.browser.open(self.contracts_path + '/c102/edit')
1142        self.browser.getControl(name="form.title").value = 'My second contract'
1143        # SAM is in the correct contract_category ...
1144        self.assertTrue('<option value="SAM">' in self.browser.contents)
1145        # ... but NOTSAM not.
1146        self.assertFalse('<option value="LIC">' in self.browser.contents)
1147        # So far last_product_id is None.
1148        self.assertTrue(self.customer['contracts']['c102'].last_product_id is None)
1149        self.browser.getControl(name="form.product_object").value = ['SAM']
1150        self.browser.getControl("Save").click()
1151        # Document is a required field on edit form page.
1152        self.assertTrue('Document: <span class="error">Required input is missing.</span>'
1153            in self.browser.contents)
1154        # But our document can't be selected because it's not submitted
1155        self.assertFalse('My first document' in self.browser.contents)
1156        IWorkflowState(self.document).setState(SUBMITTED)
1157        self.browser.open(self.contracts_path + '/c102/edit')
1158        self.browser.getControl(name="form.product_object").value = ['SAM']
1159        self.browser.getControl(name="form.document_object").value = ['d101']
1160        self.browser.getControl(name="form.title").value = 'My second contract'
1161        self.browser.getControl("Save").click()
1162        # After saving the form, last_product_id and other attributes are set
1163        self.assertTrue('Form has been saved.' in self.browser.contents)
1164        self.assertEqual(self.customer['contracts']['c102'].last_product_id, 'SAM')
1165        self.assertEqual(contract.title, 'My second contract')
1166        self.assertEqual(contract.product_object, self.product)
1167        self.assertEqual(contract.document_object, self.document)
1168        # Saving the form again does not unset last_product_id
1169        self.browser.getControl(name="form.title").value = 'My third contract'
1170        self.browser.getControl("Save").click()
1171        self.assertEqual(self.customer['contracts']['c102'].last_product_id, 'SAM')
1172        self.assertTrue('Form has been saved.' in self.browser.contents)
1173        self.browser.getLink("View").click()
1174        self.assertEqual(self.browser.url, self.contracts_path + '/c102/index')
1175        # An href attribute is referring to the document and product objects
1176        self.assertTrue('<a href="http://localhost/app/products/SAM">SAM -'
1177            in self.browser.contents)
1178        self.assertTrue(
1179            '<a href="http://localhost/app/customers/K1000000/documents/d101">d101 -'
1180            in self.browser.contents)
1181        # Customer can submit the form. The form is also saved.
1182        self.browser.getLink("Edit").click()
1183        self.browser.getControl(name="form.title").value = 'My fourth contract'
1184        self.browser.getControl("Apply now").click()
1185        self.assertEqual(contract.title, 'My fourth contract')
1186        self.assertEqual(contract.state, 'submitted')
1187        self.assertTrue('Contract State: submitted for approval' in self.browser.contents)
1188        # Customer can't edit the contract once it has been submitted
1189        self.browser.open(self.contracts_path + '/c102/edit')
1190        self.assertTrue('The requested form is locked' in self.browser.contents)
1191
1192    def test_view_slips(self):
1193        self.browser.addHeader('Authorization', 'Basic mgr:mgrpw')
1194        # Officers can open the contract overview
1195        self.browser.open(self.customer_path + '/contracts')
1196        self.browser.getLink("Download contracts overview").click()
1197        self.assertEqual(self.browser.headers['Status'], '200 Ok')
1198        self.assertEqual(self.browser.headers['Content-Type'], 'application/pdf')
1199        path = os.path.join(samples_dir(), 'contracts_overview_slip.pdf')
1200        open(path, 'wb').write(self.browser.contents)
1201        print "Sample PDF overview_slip.pdf written to %s" % path
1202        # Officers can open contract slips
1203        self.browser.open(self.customer_path + '/contracts/c101')
1204        self.browser.getLink("Download contract slip").click()
1205        self.assertEqual(self.browser.headers['Status'], '200 Ok')
1206        self.assertEqual(self.browser.headers['Content-Type'], 'application/pdf')
1207        path = os.path.join(samples_dir(), 'contract_slip.pdf')
1208        open(path, 'wb').write(self.browser.contents)
1209        print "Sample contract_slip.pdf written to %s" % path
1210
Note: See TracBrowser for help on using the repository browser.