source: main/ikobacustom.pcn/trunk/src/ikobacustom/pcn/customers/tests/test_browser.py @ 15369

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

Prepare products and contracts for annual payments.

  • Property svn:keywords set to Id
File size: 22.7 KB
Line 
1## $Id: test_browser.py 12803 2015-03-20 18:51:29Z 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"""
19Document browser and functional tests.
20"""
21import os
22import grok
23import datetime
24from cStringIO import StringIO
25from zope.component import queryUtility, getUtility, createObject
26from zope.event import notify
27from zope.interface.verify import verifyObject, verifyClass
28from zope.testbrowser.testing import Browser
29from hurry.workflow.interfaces import IWorkflowState
30from waeup.ikoba.customers.tests.test_batching import CustomerImportExportSetup
31from waeup.ikoba.customers.tests.test_browser import CustomersFullSetup
32from ikobacustom.pcn.customers.export import (
33    PCNCustomerExporter,
34    PCNCustomerPDFDocumentExporter,
35    PCNCustomerJPGDocumentExporter,
36    RONContractExporter,
37    ROPContractExporter)
38from ikobacustom.pcn.customers.batching import (
39    PCNCustomerProcessor,
40    PCNCustomerPDFDocumentProcessor,
41    PCNCustomerJPGDocumentProcessor,
42    RONContractProcessor,
43    ROPContractProcessor)
44from ikobacustom.pcn.testing import FunctionalLayer, samples_dir
45
46SAMPLE_IMAGE = os.path.join(os.path.dirname(__file__), 'test_image.jpg')
47SAMPLE_IMAGE_BMP = os.path.join(os.path.dirname(__file__), 'test_image.bmp')
48SAMPLE_PDF = os.path.join(os.path.dirname(__file__), 'test_pdf.pdf')
49
50class CustomerImportExportTest(CustomerImportExportSetup):
51
52    layer = FunctionalLayer
53
54    def setup_customizable_params(self):
55        self._contract_category = u'ron'
56        return
57
58    def setup_for_export(self):
59        customer = createObject(u'waeup.Customer')
60        customer.firstname = u'Beate'
61        customer.lastname = u'Mueller'
62        customer.reg_number = u'123'
63        customer.sex = u'f'
64        customer.email = u'aa@aa.aa'
65        customer.res_address = u'My address'
66        customer.date_of_birth = datetime.date(1981, 2, 4)
67        IWorkflowState(customer).setState('started')
68        self.app['customers'].addCustomer(customer)
69        document1 = createObject(u'waeup.PCNCustomerPDFDocument')
70        document1.title = u'My first document'
71        document2 = createObject(u'waeup.PCNCustomerJPGDocument')
72        document2.title = u'My second document'
73        customer['documents'].addDocument(document1)
74        customer['documents'].addDocument(document2)
75        contract1 = createObject(u'waeup.RONContract')
76        contract1.tc_dict = {'en':u'Hello World'}
77        customer['contracts'].addContract(contract1)
78        contract2 = createObject(u'waeup.ROPContract')
79        contract2.tc_dict = {'en':u'Hello World'}
80        customer['contracts'].addContract(contract2)
81        self.customer = customer
82        self.document1 = document1
83        self.document2 = document2
84        self.contract1 = contract1
85        self.contract2 = contract2
86        self.outfile = os.path.join(self.workdir, 'myoutput.csv')
87        return
88
89    def test_export_reimport_customers(self):
90        # we can export all customers in a portal
91        # set values we can expect in export file
92        self.setup_for_export()
93        exporter = PCNCustomerExporter()
94        exporter.export_all(self.app, self.outfile)
95        result = open(self.outfile, 'rb').read()
96        self.assertEqual(result,
97            'customer_id,date_of_birth,email,firstname,lastname,middlename,phone,'
98            'reg_number,res_address,sex,suspended,suspended_comment,password,state,history\r\n'
99            'K1000000,1981-02-04#,aa@aa.aa,Beate,Mueller,,,123,My address,f,0,,,started,[]\r\n')
100        # We can reimport the file ...
101        processor = PCNCustomerProcessor()
102        result = processor.doImport(
103            self.outfile,
104            ['customer_id','date_of_birth','email','firstname','lastname','middlename','phone',
105            'reg_number','res_address','sex','suspended','suspended_comment','password','state'],
106            mode='create')
107        num, num_fail, finished_path, failed_path = result
108        self.assertEqual(num_fail,1)
109        # ... if we remove the original customer.
110        del self.app['customers']['K1000000']
111        result = processor.doImport(
112            self.outfile,
113            ['customer_id','date_of_birth','email','firstname','lastname','middlename','phone',
114            'reg_number','res_address','sex','suspended','suspended_comment','password','state'],
115            mode='create')
116        num_succ, num_fail, finished_path, failed_path = result
117        self.assertEqual(num_fail,0)
118        # We can import the same file in update mode if we ignore
119        # the reg_number and email address
120        result = processor.doImport(
121            self.outfile,
122            ['customer_id','date_of_birth','xx_email','firstname','lastname','middlename','phone',
123            'xx_reg_number','res_address','sex','suspended','suspended_comment','password','state'],
124            mode='update')
125        num_succ, num_fail, finished_path, failed_path = result
126        self.assertEqual(num_succ,1)
127        self.assertEqual(num_fail,0)
128        return
129
130    def test_export_reimport_pdf_documents(self):
131        # we can export all documents in a portal
132        # set values we can expect in export file
133        self.setup_for_export()
134        exporter = PCNCustomerPDFDocumentExporter()
135        exporter.export_all(self.app, self.outfile)
136        result = open(self.outfile, 'rb').read()
137        self.assertMatches(result,
138            'class_name,document_id,history,state,title,user_id\r\n'
139            'PCNCustomerPDFDocument,%s,'
140            '[u\'2014-12-21 17:00:36 WAT - Document created by system\'],'
141            'created,My first document,K1000000\r\n'
142            % self.document1.document_id)
143        # We can reimport the file if we change the header (user_id -> customer_id)
144        processor = PCNCustomerPDFDocumentProcessor()
145        open(self.outfile, 'wb').write(
146            'customer_id,class_name,document_id,state,title\r\n'
147            'K1000000,PCNCustomerPDFDocument,%s,started,My first title\r\n'
148            % self.document1.document_id)
149        result = processor.doImport(
150            self.outfile,
151            ['customer_id','class_name','document_id','state','title'],
152            mode='create')
153        num, num_fail, finished_path, failed_path = result
154        # The object exists.
155        self.assertEqual(num_fail,1)
156        # We remove the original document.
157        del self.customer['documents'][self.document1.document_id]
158        result = processor.doImport(
159            self.outfile,
160            ['customer_id','class_name','document_id','state','title'],
161            mode='create')
162        num_succ, num_fail, finished_path, failed_path = result
163        self.assertEqual(num_fail,0)
164        # We can import the same file in update mode.
165        result = processor.doImport(
166            self.outfile,
167            ['customer_id','class_name','document_id','state','title'],
168            mode='update')
169        num_succ, num_fail, finished_path, failed_path = result
170        self.assertEqual(num_succ,1)
171        self.assertEqual(num_fail,0)
172        return
173
174    def test_export_reimport_jpg_documents(self):
175        # we can export all documents in a portal
176        # set values we can expect in export file
177        self.setup_for_export()
178        exporter = PCNCustomerJPGDocumentExporter()
179        exporter.export_all(self.app, self.outfile)
180        result = open(self.outfile, 'rb').read()
181        self.assertMatches(result,
182            'class_name,document_id,history,state,title,user_id\r\n'
183            'PCNCustomerJPGDocument,%s,'
184            '[u\'2014-12-21 17:00:36 WAT - Document created by system\'],'
185            'created,My second document,K1000000\r\n'
186            % self.document2.document_id)
187        # We can reimport the file if we change the header (user_id -> customer_id)
188        processor = PCNCustomerJPGDocumentProcessor()
189        open(self.outfile, 'wb').write(
190            'customer_id,class_name,document_id,state,title\r\n'
191            'K1000000,PCNCustomerJPGDocument,%s,started,My second title\r\n'
192            % self.document2.document_id)
193        result = processor.doImport(
194            self.outfile,
195            ['customer_id','class_name','document_id','state','title'],
196            mode='create')
197        num, num_fail, finished_path, failed_path = result
198        # The object exists.
199        self.assertEqual(num_fail,1)
200        # We remove the original document.
201        del self.customer['documents'][self.document2.document_id]
202        result = processor.doImport(
203            self.outfile,
204            ['customer_id','class_name','document_id','state','title'],
205            mode='create')
206        num_succ, num_fail, finished_path, failed_path = result
207        self.assertEqual(num_fail,0)
208        # We can import the same file in update mode.
209        result = processor.doImport(
210            self.outfile,
211            ['customer_id','class_name','document_id','state','title'],
212            mode='update')
213        num_succ, num_fail, finished_path, failed_path = result
214        self.assertEqual(num_succ,1)
215        self.assertEqual(num_fail,0)
216        return
217
218    def test_export_reimport_roncontracts(self):
219        # we can export all contracts in a portal
220        # set values we can expect in export file
221        self.setup_for_export()
222        exporter = RONContractExporter()
223        exporter.export_all(self.app, self.outfile)
224        result = open(self.outfile, 'rb').read()
225        self.assertMatches(result,
226            'categories_practice,class_name,comment,contract_category,'
227            'contract_id,contract_year,fee_based,history,last_product_id,'
228            'lga,nationality,product_object,product_options,'
229            'qualification_year,state,superintendent,tc_dict,'
230            'title,user_id,valid_from,valid_to,work_address,'
231            'work_email,work_phone\r\n'
232            '[],RONContract,,ron,%s,,0,'
233            '[u\'2015-03-20 19:13:53 WAT - License created by system\']'
234            ',,,,,[],,created,,{\'en\': u\'Hello World\'},,K1000000,,,,,\r\n'
235            % self.contract1.contract_id)
236        # We can reimport the file if we change the header
237        # (user_id -> customer_id). Not all columns are necessary.
238        processor = RONContractProcessor()
239        open(self.outfile, 'wb').write(
240            'class_name,contract_category,contract_id,document_object,'
241            'history,last_product_id,product_object,product_options,'
242            'state,tc_dict,title,user_id\r\n'
243            'RONContract,license,%s,,'
244            '[u\'2014-12-21 22:26:00 WAT - License created by system\']'
245            ',,,[],created,{\'en\': u\'Hello World\'},,K1000000\r\n'
246            % self.contract1.contract_id)
247        result = processor.doImport(
248            self.outfile,
249            ['class_name','contract_category','contract_id','document_object',
250            'history','last_product_id','product_object','product_options',
251            'state','tc_dict','title','customer_id'],
252            mode='create')
253        num, num_fail, finished_path, failed_path = result
254        # The object exists.
255        self.assertEqual(num_fail,1)
256        # We remove the original contract.
257        del self.customer['contracts'][self.contract1.contract_id]
258        result = processor.doImport(
259            self.outfile,
260            ['class_name','contract_category','contract_id','document_object',
261            'history','last_product_id','product_object','product_options',
262            'state','tc_dict','title','customer_id'],
263            mode='create')
264        num_succ, num_fail, finished_path, failed_path = result
265        self.assertEqual(num_fail,0)
266        # We can import the same file in update mode.
267        result = processor.doImport(
268            self.outfile,
269            ['class_name','contract_category','contract_id','document_object',
270            'history','last_product_id','product_object','product_options',
271            'state','tc_dict','title','customer_id'],
272            mode='update')
273        num_succ, num_fail, finished_path, failed_path = result
274        self.assertEqual(num_succ,1)
275        self.assertEqual(num_fail,0)
276        return
277
278    def test_export_reimport_ropcontracts(self):
279        # we can export all contracts in a portal
280        # set values we can expect in export file
281        self.setup_for_export()
282        exporter = ROPContractExporter()
283        exporter.export_all(self.app, self.outfile)
284        result = open(self.outfile, 'rb').read()
285        self.assertMatches(result,
286            'categories_practice,class_name,contract_category,'
287            'contract_id,contract_year,date_of_qualification,'
288            'fee_based,history,inspected,last_license_number,'
289            'last_product_id,official_in_state,other_directors,'
290            'pharmacists_directors,premises_address,premises_certificate,'
291            'product_object,product_options,recommended,state,'
292            'superintendent,tc_dict,title,user_id,valid_from,'
293            'valid_to,work_address\r\n'
294
295            '[],ROPContract,rop,%s,,,0,'
296            '[u\'2015-03-20 19:18:30 WAT - License created by system\']'
297            ',,,,,,,,,,[],,created,,{\'en\': u\'Hello World\'},,K1000000,,,\r\n'
298            % self.contract2.contract_id)
299        # We can reimport the file if we change the header
300        # (user_id -> customer_id). Not all columns are necessary.
301        processor = ROPContractProcessor()
302        open(self.outfile, 'wb').write(
303            'class_name,contract_category,contract_id,document_object,'
304            'history,last_product_id,product_object,product_options,'
305            'state,tc_dict,title,user_id\r\n'
306            'ROPContract,rop,%s,,'
307            '[u\'2014-12-21 22:26:00 WAT - License created by system\']'
308            ',,,[],created,{\'en\': u\'Hello World\'},,K1000000\r\n'
309            % self.contract2.contract_id)
310        result = processor.doImport(
311            self.outfile,
312            ['class_name','contract_category','contract_id','document_object',
313            'history','last_product_id','product_object','product_options',
314            'state','tc_dict','title','customer_id'],
315            mode='create')
316        num, num_fail, finished_path, failed_path = result
317        # The object exists.
318        self.assertEqual(num_fail,1)
319        # We remove the original contract.
320        del self.customer['contracts'][self.contract2.contract_id]
321        result = processor.doImport(
322            self.outfile,
323            ['class_name','contract_category','contract_id','document_object',
324            'history','last_product_id','product_object','product_options',
325            'state','tc_dict','title','customer_id'],
326            mode='create')
327        num_succ, num_fail, finished_path, failed_path = result
328        self.assertEqual(num_fail,0)
329        # We can import the same file in update mode.
330        result = processor.doImport(
331            self.outfile,
332            ['class_name','contract_category','contract_id','document_object',
333            'history','last_product_id','product_object','product_options',
334            'state','tc_dict','title','customer_id'],
335            mode='update')
336        num_succ, num_fail, finished_path, failed_path = result
337        self.assertEqual(num_succ,1)
338        self.assertEqual(num_fail,0)
339        return
340
341
342class CustomerUITests(CustomersFullSetup):
343
344    layer = FunctionalLayer
345
346    def setup_customizable_params(self):
347        self._contract_category = u'ron'
348        self._document_factory = 'waeup.PCNCustomerPDFDocument'
349        self._contract_factory = 'waeup.RONContract'
350        return
351
352    def test_customer_edit_upload_upload_and_request(self):
353        # Customer cant login if their password is not set
354        self.browser.open(self.login_path)
355        self.browser.getControl(name="form.login").value = self.customer_id
356        self.browser.getControl(name="form.password").value = 'cpwd'
357        self.browser.getControl("Login").click()
358        self.assertMatches(
359            '...You logged in...', self.browser.contents)
360        self.browser.getLink("Edit").click()
361        self.browser.getControl(name="form.email").value = 'new_email@aa.ng'
362        self.browser.getControl(name="form.res_address").value = 'My address'
363        self.browser.getControl("Save", index=0).click()
364        self.assertMatches('...Form has been saved...',
365                           self.browser.contents)
366        self.browser.getControl("Save and request registration").click()
367        self.assertMatches('...Passport picture is missing...',
368                           self.browser.contents)
369        self.assertEqual(self.customer.state, 'started')
370        # Customer must upload a passport picture. We are already on
371        # the upload page.
372        ctrl = self.browser.getControl(name='passporteditupload')
373        file_obj = open(SAMPLE_IMAGE, 'rb')
374        file_ctrl = ctrl.mech_control
375        file_ctrl.add_file(file_obj, filename='my_photo.jpg')
376        self.browser.getControl(
377            name='upload_passporteditupload').click()
378        self.assertTrue(
379            'src="http://localhost/app/customers/K1000000/passport.jpg"'
380            in self.browser.contents)
381        self.browser.getControl(name="CANCEL").click()
382        self.assertEqual(self.browser.url, self.customer_path)
383        self.browser.getLink("Edit").click()
384        self.browser.getControl("Save and request registration").click()
385        self.assertMatches('...Birth certificate is missing...',
386                           self.browser.contents)
387        self.assertEqual(self.customer.state, 'started')
388        ctrl = self.browser.getControl(name='birthcertificateeditupload')
389        file_obj = open(SAMPLE_PDF, 'rb')
390        file_ctrl = ctrl.mech_control
391        file_ctrl.add_file(file_obj, filename='my_bc.pdf')
392        self.browser.getControl(
393            name='upload_birthcertificateeditupload').click()
394        self.assertTrue(
395            'href="http://localhost/app/customers/K1000000/birth_certificate.pdf"'
396            in self.browser.contents)
397        self.browser.getControl(name="CANCEL").click()
398        self.browser.getLink("Edit").click()
399        self.browser.getControl("Save and request registration").click()
400        self.assertMatches('...Registration form has been submitted...',
401                           self.browser.contents)
402        self.assertEqual(self.customer.state, 'requested')
403        # Customer can view history
404        self.browser.getLink("History").click()
405        self.assertMatches('...Registration record created by system...',
406            self.browser.contents)
407
408
409class DocumentUITests(CustomersFullSetup):
410    # Tests for customer document related views and pages
411
412    layer = FunctionalLayer
413
414    def setup_customizable_params(self):
415        self._contract_category = u'ron'
416        self._document_factory = 'waeup.PCNCustomerPDFDocument'
417        self._contract_factory = 'waeup.RONContract'
418        return
419
420    def test_manage_upload_pdf_file(self):
421        # Managers can upload a file via the DocumentManageFormPage
422        # The image is stored even if form has errors
423        self.browser.addHeader('Authorization', 'Basic mgr:mgrpw')
424        self.browser.open(self.customer_path + '/documents')
425        self.browser.getControl("Add document").click()
426        self.browser.getControl(name="doctype").value = ['PCNCustomerPDFDocument']
427        self.browser.getControl(name="form.title").value = 'My PCN Document'
428        self.browser.getControl("Add document").click()
429        docid = [i for i in self.customer['documents'].keys() if len(i) > 10][0]
430        self.browser.open(self.documents_path + '/%s/manage' % docid)
431        # Create a pseudo image file and select it to be uploaded
432        image = open(SAMPLE_IMAGE, 'rb')
433        ctrl = self.browser.getControl(name='pdfscanmanageupload')
434        file_ctrl = ctrl.mech_control
435        file_ctrl.add_file(image, filename='my_sample_scan.jpg')
436        self.browser.getControl(
437            name='upload_pdfscanmanageupload').click()
438        self.assertTrue(
439            'pdf file format expected' in self.browser.contents)
440        ctrl = self.browser.getControl(name='pdfscanmanageupload')
441        file_ctrl = ctrl.mech_control
442        file_ctrl.add_file(image, filename='my_sample_scan.pdf')
443        self.browser.getControl(
444            name='upload_pdfscanmanageupload').click()
445        self.assertTrue(
446            'Could not determine file type' in self.browser.contents)
447        pdf = open(SAMPLE_PDF, 'rb')
448        ctrl = self.browser.getControl(name='pdfscanmanageupload')
449        file_ctrl = ctrl.mech_control
450        file_ctrl.add_file(pdf, filename='my_sample_scan.pdf')
451        self.browser.getControl(
452            name='upload_pdfscanmanageupload').click()
453        self.assertTrue(
454            'href="http://localhost/app/customers/K1000000/documents/%s/scan.pdf">%s.pdf</a>'
455            % (docid, docid[:9]) in self.browser.contents)
456        # Browsing the link shows a real pdf
457        self.browser.open('scan.pdf')
458        self.assertEqual(
459            self.browser.headers['content-type'], 'application/pdf')
460        # The name of the downloaded file will be different
461        self.assertEqual(
462            self.browser.headers['Content-Disposition'],
463            'attachment; filename="%s.pdf' % docid[:9])
464
465
466class ContractUITests(CustomersFullSetup):
467    # Tests for contract related views and pages
468
469    layer = FunctionalLayer
470
471    def setup_customizable_params(self):
472        self._contract_category = u'ron'
473        self._document_factory = 'waeup.PCNCustomerPDFDocument'
474        self._contract_factory = 'waeup.RONContract'
475        return
476
477    def test_view_slips(self):
478        self.browser.addHeader('Authorization', 'Basic mgr:mgrpw')
479        # Officers can open contract slips.
480        # First we add a submitted document and a product.
481        IWorkflowState(self.document).setState('submitted')
482        self.contract.title = u'Contract Title'
483        self.contract.document_object = self.document
484        self.contract.product_object = self.product
485        self.contract.tc_dict = {'en': u'<strong>Hello world</strong>'}
486        self.browser.open(self.customer_path + '/contracts/CON1')
487        self.browser.getLink("Download license slip").click()
488        self.assertEqual(self.browser.headers['Status'], '200 Ok')
489        self.assertEqual(self.browser.headers['Content-Type'], 'application/pdf')
490        path = os.path.join(samples_dir(), 'contract_slip.pdf')
491        open(path, 'wb').write(self.browser.contents)
492        print "Sample contract_slip.pdf written to %s" % path
Note: See TracBrowser for help on using the repository browser.