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

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

The term 'application' should really not be used in Python-based portal software.

Replace 'application' by 'contract': batch 1

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