## $Id: test_browser.py 12803 2015-03-20 18:51:29Z henrik $ ## ## Copyright (C) 2014 Uli Fouquet & Henrik Bettermann ## This program is free software; you can redistribute it and/or modify ## it under the terms of the GNU General Public License as published by ## the Free Software Foundation; either version 2 of the License, or ## (at your option) any later version. ## ## This program is distributed in the hope that it will be useful, ## but WITHOUT ANY WARRANTY; without even the implied warranty of ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ## GNU General Public License for more details. ## ## You should have received a copy of the GNU General Public License ## along with this program; if not, write to the Free Software ## Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ## """ Document browser and functional tests. """ import os import grok import datetime from cStringIO import StringIO from zope.component import queryUtility, getUtility, createObject from zope.event import notify from zope.interface.verify import verifyObject, verifyClass from zope.testbrowser.testing import Browser from hurry.workflow.interfaces import IWorkflowState from waeup.ikoba.customers.tests.test_batching import CustomerImportExportSetup from waeup.ikoba.customers.tests.test_browser import CustomersFullSetup from ikobacustom.pcn.customers.export import ( PCNCustomerExporter, PCNCustomerPDFDocumentExporter, PCNCustomerJPGDocumentExporter, RONContractExporter, ROPContractExporter) from ikobacustom.pcn.customers.batching import ( PCNCustomerProcessor, PCNCustomerPDFDocumentProcessor, PCNCustomerJPGDocumentProcessor, RONContractProcessor, ROPContractProcessor) from ikobacustom.pcn.testing import FunctionalLayer, samples_dir SAMPLE_IMAGE = os.path.join(os.path.dirname(__file__), 'test_image.jpg') SAMPLE_IMAGE_BMP = os.path.join(os.path.dirname(__file__), 'test_image.bmp') SAMPLE_PDF = os.path.join(os.path.dirname(__file__), 'test_pdf.pdf') class CustomerImportExportTest(CustomerImportExportSetup): layer = FunctionalLayer def setup_customizable_params(self): self._contract_category = u'ron' return def setup_for_export(self): customer = createObject(u'waeup.Customer') customer.firstname = u'Beate' customer.lastname = u'Mueller' customer.reg_number = u'123' customer.sex = u'f' customer.email = u'aa@aa.aa' customer.res_address = u'My address' customer.date_of_birth = datetime.date(1981, 2, 4) IWorkflowState(customer).setState('started') self.app['customers'].addCustomer(customer) document1 = createObject(u'waeup.PCNCustomerPDFDocument') document1.title = u'My first document' document2 = createObject(u'waeup.PCNCustomerJPGDocument') document2.title = u'My second document' customer['documents'].addDocument(document1) customer['documents'].addDocument(document2) contract1 = createObject(u'waeup.RONContract') contract1.tc_dict = {'en':u'Hello World'} customer['contracts'].addContract(contract1) contract2 = createObject(u'waeup.ROPContract') contract2.tc_dict = {'en':u'Hello World'} customer['contracts'].addContract(contract2) self.customer = customer self.document1 = document1 self.document2 = document2 self.contract1 = contract1 self.contract2 = contract2 self.outfile = os.path.join(self.workdir, 'myoutput.csv') return def test_export_reimport_customers(self): # we can export all customers in a portal # set values we can expect in export file self.setup_for_export() exporter = PCNCustomerExporter() exporter.export_all(self.app, self.outfile) result = open(self.outfile, 'rb').read() self.assertEqual(result, 'customer_id,date_of_birth,email,firstname,lastname,middlename,phone,' 'reg_number,res_address,sex,suspended,suspended_comment,password,state,history\r\n' 'K1000000,1981-02-04#,aa@aa.aa,Beate,Mueller,,,123,My address,f,0,,,started,[]\r\n') # We can reimport the file ... processor = PCNCustomerProcessor() result = processor.doImport( self.outfile, ['customer_id','date_of_birth','email','firstname','lastname','middlename','phone', 'reg_number','res_address','sex','suspended','suspended_comment','password','state'], mode='create') num, num_fail, finished_path, failed_path = result self.assertEqual(num_fail,1) # ... if we remove the original customer. del self.app['customers']['K1000000'] result = processor.doImport( self.outfile, ['customer_id','date_of_birth','email','firstname','lastname','middlename','phone', 'reg_number','res_address','sex','suspended','suspended_comment','password','state'], mode='create') num_succ, num_fail, finished_path, failed_path = result self.assertEqual(num_fail,0) # We can import the same file in update mode if we ignore # the reg_number and email address result = processor.doImport( self.outfile, ['customer_id','date_of_birth','xx_email','firstname','lastname','middlename','phone', 'xx_reg_number','res_address','sex','suspended','suspended_comment','password','state'], mode='update') num_succ, num_fail, finished_path, failed_path = result self.assertEqual(num_succ,1) self.assertEqual(num_fail,0) return def test_export_reimport_pdf_documents(self): # we can export all documents in a portal # set values we can expect in export file self.setup_for_export() exporter = PCNCustomerPDFDocumentExporter() exporter.export_all(self.app, self.outfile) result = open(self.outfile, 'rb').read() self.assertMatches(result, 'class_name,document_id,history,state,title,user_id\r\n' 'PCNCustomerPDFDocument,%s,' '[u\'2014-12-21 17:00:36 WAT - Document created by system\'],' 'created,My first document,K1000000\r\n' % self.document1.document_id) # We can reimport the file if we change the header (user_id -> customer_id) processor = PCNCustomerPDFDocumentProcessor() open(self.outfile, 'wb').write( 'customer_id,class_name,document_id,state,title\r\n' 'K1000000,PCNCustomerPDFDocument,%s,started,My first title\r\n' % self.document1.document_id) result = processor.doImport( self.outfile, ['customer_id','class_name','document_id','state','title'], mode='create') num, num_fail, finished_path, failed_path = result # The object exists. self.assertEqual(num_fail,1) # We remove the original document. del self.customer['documents'][self.document1.document_id] result = processor.doImport( self.outfile, ['customer_id','class_name','document_id','state','title'], mode='create') num_succ, num_fail, finished_path, failed_path = result self.assertEqual(num_fail,0) # We can import the same file in update mode. result = processor.doImport( self.outfile, ['customer_id','class_name','document_id','state','title'], mode='update') num_succ, num_fail, finished_path, failed_path = result self.assertEqual(num_succ,1) self.assertEqual(num_fail,0) return def test_export_reimport_jpg_documents(self): # we can export all documents in a portal # set values we can expect in export file self.setup_for_export() exporter = PCNCustomerJPGDocumentExporter() exporter.export_all(self.app, self.outfile) result = open(self.outfile, 'rb').read() self.assertMatches(result, 'class_name,document_id,history,state,title,user_id\r\n' 'PCNCustomerJPGDocument,%s,' '[u\'2014-12-21 17:00:36 WAT - Document created by system\'],' 'created,My second document,K1000000\r\n' % self.document2.document_id) # We can reimport the file if we change the header (user_id -> customer_id) processor = PCNCustomerJPGDocumentProcessor() open(self.outfile, 'wb').write( 'customer_id,class_name,document_id,state,title\r\n' 'K1000000,PCNCustomerJPGDocument,%s,started,My second title\r\n' % self.document2.document_id) result = processor.doImport( self.outfile, ['customer_id','class_name','document_id','state','title'], mode='create') num, num_fail, finished_path, failed_path = result # The object exists. self.assertEqual(num_fail,1) # We remove the original document. del self.customer['documents'][self.document2.document_id] result = processor.doImport( self.outfile, ['customer_id','class_name','document_id','state','title'], mode='create') num_succ, num_fail, finished_path, failed_path = result self.assertEqual(num_fail,0) # We can import the same file in update mode. result = processor.doImport( self.outfile, ['customer_id','class_name','document_id','state','title'], mode='update') num_succ, num_fail, finished_path, failed_path = result self.assertEqual(num_succ,1) self.assertEqual(num_fail,0) return def test_export_reimport_roncontracts(self): # we can export all contracts in a portal # set values we can expect in export file self.setup_for_export() exporter = RONContractExporter() exporter.export_all(self.app, self.outfile) result = open(self.outfile, 'rb').read() self.assertMatches(result, 'categories_practice,class_name,comment,contract_category,' 'contract_id,contract_year,fee_based,history,last_product_id,' 'lga,nationality,product_object,product_options,' 'qualification_year,state,superintendent,tc_dict,' 'title,user_id,valid_from,valid_to,work_address,' 'work_email,work_phone\r\n' '[],RONContract,,ron,%s,,0,' '[u\'2015-03-20 19:13:53 WAT - License created by system\']' ',,,,,[],,created,,{\'en\': u\'Hello World\'},,K1000000,,,,,\r\n' % self.contract1.contract_id) # We can reimport the file if we change the header # (user_id -> customer_id). Not all columns are necessary. processor = RONContractProcessor() open(self.outfile, 'wb').write( 'class_name,contract_category,contract_id,document_object,' 'history,last_product_id,product_object,product_options,' 'state,tc_dict,title,user_id\r\n' 'RONContract,license,%s,,' '[u\'2014-12-21 22:26:00 WAT - License created by system\']' ',,,[],created,{\'en\': u\'Hello World\'},,K1000000\r\n' % self.contract1.contract_id) result = processor.doImport( self.outfile, ['class_name','contract_category','contract_id','document_object', 'history','last_product_id','product_object','product_options', 'state','tc_dict','title','customer_id'], mode='create') num, num_fail, finished_path, failed_path = result # The object exists. self.assertEqual(num_fail,1) # We remove the original contract. del self.customer['contracts'][self.contract1.contract_id] result = processor.doImport( self.outfile, ['class_name','contract_category','contract_id','document_object', 'history','last_product_id','product_object','product_options', 'state','tc_dict','title','customer_id'], mode='create') num_succ, num_fail, finished_path, failed_path = result self.assertEqual(num_fail,0) # We can import the same file in update mode. result = processor.doImport( self.outfile, ['class_name','contract_category','contract_id','document_object', 'history','last_product_id','product_object','product_options', 'state','tc_dict','title','customer_id'], mode='update') num_succ, num_fail, finished_path, failed_path = result self.assertEqual(num_succ,1) self.assertEqual(num_fail,0) return def test_export_reimport_ropcontracts(self): # we can export all contracts in a portal # set values we can expect in export file self.setup_for_export() exporter = ROPContractExporter() exporter.export_all(self.app, self.outfile) result = open(self.outfile, 'rb').read() self.assertMatches(result, 'categories_practice,class_name,contract_category,' 'contract_id,contract_year,date_of_qualification,' 'fee_based,history,inspected,last_license_number,' 'last_product_id,official_in_state,other_directors,' 'pharmacists_directors,premises_address,premises_certificate,' 'product_object,product_options,recommended,state,' 'superintendent,tc_dict,title,user_id,valid_from,' 'valid_to,work_address\r\n' '[],ROPContract,rop,%s,,,0,' '[u\'2015-03-20 19:18:30 WAT - License created by system\']' ',,,,,,,,,,[],,created,,{\'en\': u\'Hello World\'},,K1000000,,,\r\n' % self.contract2.contract_id) # We can reimport the file if we change the header # (user_id -> customer_id). Not all columns are necessary. processor = ROPContractProcessor() open(self.outfile, 'wb').write( 'class_name,contract_category,contract_id,document_object,' 'history,last_product_id,product_object,product_options,' 'state,tc_dict,title,user_id\r\n' 'ROPContract,rop,%s,,' '[u\'2014-12-21 22:26:00 WAT - License created by system\']' ',,,[],created,{\'en\': u\'Hello World\'},,K1000000\r\n' % self.contract2.contract_id) result = processor.doImport( self.outfile, ['class_name','contract_category','contract_id','document_object', 'history','last_product_id','product_object','product_options', 'state','tc_dict','title','customer_id'], mode='create') num, num_fail, finished_path, failed_path = result # The object exists. self.assertEqual(num_fail,1) # We remove the original contract. del self.customer['contracts'][self.contract2.contract_id] result = processor.doImport( self.outfile, ['class_name','contract_category','contract_id','document_object', 'history','last_product_id','product_object','product_options', 'state','tc_dict','title','customer_id'], mode='create') num_succ, num_fail, finished_path, failed_path = result self.assertEqual(num_fail,0) # We can import the same file in update mode. result = processor.doImport( self.outfile, ['class_name','contract_category','contract_id','document_object', 'history','last_product_id','product_object','product_options', 'state','tc_dict','title','customer_id'], mode='update') num_succ, num_fail, finished_path, failed_path = result self.assertEqual(num_succ,1) self.assertEqual(num_fail,0) return class CustomerUITests(CustomersFullSetup): layer = FunctionalLayer def setup_customizable_params(self): self._contract_category = u'ron' self._document_factory = 'waeup.PCNCustomerPDFDocument' self._contract_factory = 'waeup.RONContract' return def test_customer_edit_upload_upload_and_request(self): # Customer cant login if their password is not set self.browser.open(self.login_path) self.browser.getControl(name="form.login").value = self.customer_id self.browser.getControl(name="form.password").value = 'cpwd' self.browser.getControl("Login").click() self.assertMatches( '...You logged in...', self.browser.contents) self.browser.getLink("Edit").click() self.browser.getControl(name="form.email").value = 'new_email@aa.ng' self.browser.getControl(name="form.res_address").value = 'My address' self.browser.getControl("Save", index=0).click() self.assertMatches('...Form has been saved...', self.browser.contents) self.browser.getControl("Save and request registration").click() self.assertMatches('...Passport picture is missing...', self.browser.contents) self.assertEqual(self.customer.state, 'started') # Customer must upload a passport picture. We are already on # the upload page. ctrl = self.browser.getControl(name='passporteditupload') file_obj = open(SAMPLE_IMAGE, 'rb') file_ctrl = ctrl.mech_control file_ctrl.add_file(file_obj, filename='my_photo.jpg') self.browser.getControl( name='upload_passporteditupload').click() self.assertTrue( 'src="http://localhost/app/customers/K1000000/passport.jpg"' in self.browser.contents) self.browser.getControl(name="CANCEL").click() self.assertEqual(self.browser.url, self.customer_path) self.browser.getLink("Edit").click() self.browser.getControl("Save and request registration").click() self.assertMatches('...Birth certificate is missing...', self.browser.contents) self.assertEqual(self.customer.state, 'started') ctrl = self.browser.getControl(name='birthcertificateeditupload') file_obj = open(SAMPLE_PDF, 'rb') file_ctrl = ctrl.mech_control file_ctrl.add_file(file_obj, filename='my_bc.pdf') self.browser.getControl( name='upload_birthcertificateeditupload').click() self.assertTrue( 'href="http://localhost/app/customers/K1000000/birth_certificate.pdf"' in self.browser.contents) self.browser.getControl(name="CANCEL").click() self.browser.getLink("Edit").click() self.browser.getControl("Save and request registration").click() self.assertMatches('...Registration form has been submitted...', self.browser.contents) self.assertEqual(self.customer.state, 'requested') # Customer can view history self.browser.getLink("History").click() self.assertMatches('...Registration record created by system...', self.browser.contents) class DocumentUITests(CustomersFullSetup): # Tests for customer document related views and pages layer = FunctionalLayer def setup_customizable_params(self): self._contract_category = u'ron' self._document_factory = 'waeup.PCNCustomerPDFDocument' self._contract_factory = 'waeup.RONContract' return def test_manage_upload_pdf_file(self): # Managers can upload a file via the DocumentManageFormPage # The image is stored even if form has errors self.browser.addHeader('Authorization', 'Basic mgr:mgrpw') self.browser.open(self.customer_path + '/documents') self.browser.getControl("Add document").click() self.browser.getControl(name="doctype").value = ['PCNCustomerPDFDocument'] self.browser.getControl(name="form.title").value = 'My PCN Document' self.browser.getControl("Add document").click() docid = [i for i in self.customer['documents'].keys() if len(i) > 10][0] self.browser.open(self.documents_path + '/%s/manage' % docid) # Create a pseudo image file and select it to be uploaded image = open(SAMPLE_IMAGE, 'rb') ctrl = self.browser.getControl(name='pdfscanmanageupload') file_ctrl = ctrl.mech_control file_ctrl.add_file(image, filename='my_sample_scan.jpg') self.browser.getControl( name='upload_pdfscanmanageupload').click() self.assertTrue( 'pdf file format expected' in self.browser.contents) ctrl = self.browser.getControl(name='pdfscanmanageupload') file_ctrl = ctrl.mech_control file_ctrl.add_file(image, filename='my_sample_scan.pdf') self.browser.getControl( name='upload_pdfscanmanageupload').click() self.assertTrue( 'Could not determine file type' in self.browser.contents) pdf = open(SAMPLE_PDF, 'rb') ctrl = self.browser.getControl(name='pdfscanmanageupload') file_ctrl = ctrl.mech_control file_ctrl.add_file(pdf, filename='my_sample_scan.pdf') self.browser.getControl( name='upload_pdfscanmanageupload').click() self.assertTrue( 'href="http://localhost/app/customers/K1000000/documents/%s/scan.pdf">%s.pdf' % (docid, docid[:9]) in self.browser.contents) # Browsing the link shows a real pdf self.browser.open('scan.pdf') self.assertEqual( self.browser.headers['content-type'], 'application/pdf') # The name of the downloaded file will be different self.assertEqual( self.browser.headers['Content-Disposition'], 'attachment; filename="%s.pdf' % docid[:9]) class ContractUITests(CustomersFullSetup): # Tests for contract related views and pages layer = FunctionalLayer def setup_customizable_params(self): self._contract_category = u'ron' self._document_factory = 'waeup.PCNCustomerPDFDocument' self._contract_factory = 'waeup.RONContract' return def test_view_slips(self): self.browser.addHeader('Authorization', 'Basic mgr:mgrpw') # Officers can open contract slips. # First we add a submitted document and a product. IWorkflowState(self.document).setState('submitted') self.contract.title = u'Contract Title' self.contract.document_object = self.document self.contract.product_object = self.product self.contract.tc_dict = {'en': u'Hello world'} self.browser.open(self.customer_path + '/contracts/CON1') self.browser.getLink("Download license slip").click() self.assertEqual(self.browser.headers['Status'], '200 Ok') self.assertEqual(self.browser.headers['Content-Type'], 'application/pdf') path = os.path.join(samples_dir(), 'contract_slip.pdf') open(path, 'wb').write(self.browser.contents) print "Sample contract_slip.pdf written to %s" % path