diff --git a/master/bt5/slapos_wechat/TestTemplateItem/portal_components/test.erp5.testSlapOSWechatWorkflow.py b/master/bt5/slapos_wechat/TestTemplateItem/portal_components/test.erp5.testSlapOSWechatWorkflow.py new file mode 100644 index 0000000000000000000000000000000000000000..96f4c78cb96145c002ac147d2f8ab68bb8ae8e65 --- /dev/null +++ b/master/bt5/slapos_wechat/TestTemplateItem/portal_components/test.erp5.testSlapOSWechatWorkflow.py @@ -0,0 +1,330 @@ +# Copyright (c) 2002-2012 Nexedi SA and Contributors. All Rights Reserved. +from erp5.component.test.SlapOSTestCaseMixin import SlapOSTestCaseMixinWithAbort + +from DateTime import DateTime +from Products.ERP5Type.tests.utils import createZODBPythonScript +import difflib + +HARDCODED_PRICE = 99.6 + +vads_url_cancel = 'http://example.org/cancel' +vads_url_error = 'http://example.org/error' +vads_url_referral = 'http://example.org/referral' +vads_url_refused = 'http://example.org/refused' +vads_url_success = 'http://example.org/success' +vads_url_return = 'http://example.org/return' + +class TestSlapOSWechatInterfaceWorkflow(SlapOSTestCaseMixinWithAbort): + + def _simulatePaymentTransaction_getTotalPayablePrice(self): + script_name = 'PaymentTransaction_getTotalPayablePrice' + if script_name in self.portal.portal_skins.custom.objectIds(): + raise ValueError('Precondition failed: %s exists in custom' % script_name) + createZODBPythonScript(self.portal.portal_skins.custom, + script_name, + '*args, **kwargs', + '# Script body\nreturn %f' % HARDCODED_PRICE) + + def _dropPaymentTransaction_getTotalPayablePrice(self): + script_name = 'PaymentTransaction_getTotalPayablePrice' + if script_name in self.portal.portal_skins.custom.objectIds(): + self.portal.portal_skins.custom.manage_delObjects(script_name) + + def test_generateManualPaymentPage_mandatoryParameters(self): + event = self.createWechatEvent() + # vads_url_cancel + self.assertRaises(TypeError, event.generateManualPaymentPage, + vads_url_error=vads_url_error, + vads_url_referral=vads_url_referral, + vads_url_refused=vads_url_refused, + vads_url_success=vads_url_success, + vads_url_return=vads_url_return, + ) + # vads_url_error + self.assertRaises(TypeError, event.generateManualPaymentPage, + vads_url_cancel=vads_url_cancel, + vads_url_referral=vads_url_referral, + vads_url_refused=vads_url_refused, + vads_url_success=vads_url_success, + vads_url_return=vads_url_return, + ) + # vads_url_referral + self.assertRaises(TypeError, event.generateManualPaymentPage, + vads_url_cancel=vads_url_cancel, + vads_url_error=vads_url_error, + vads_url_refused=vads_url_refused, + vads_url_success=vads_url_success, + vads_url_return=vads_url_return, + ) + # vads_url_refused + self.assertRaises(TypeError, event.generateManualPaymentPage, + vads_url_cancel=vads_url_cancel, + vads_url_error=vads_url_error, + vads_url_referral=vads_url_referral, + vads_url_success=vads_url_success, + vads_url_return=vads_url_return, + ) + # vads_url_success + self.assertRaises(TypeError, event.generateManualPaymentPage, + vads_url_cancel=vads_url_cancel, + vads_url_error=vads_url_error, + vads_url_referral=vads_url_referral, + vads_url_refused=vads_url_refused, + vads_url_return=vads_url_return, + ) + # vads_url_return + self.assertRaises(TypeError, event.generateManualPaymentPage, + vads_url_cancel=vads_url_cancel, + vads_url_error=vads_url_error, + vads_url_referral=vads_url_referral, + vads_url_refused=vads_url_refused, + vads_url_success=vads_url_success, + ) + + def test_generateManualPaymentPage_noAccountingTransaction(self): + event = self.createWechatEvent() + self.assertRaises(AttributeError, event.generateManualPaymentPage, + vads_url_cancel=vads_url_cancel, + vads_url_error=vads_url_error, + vads_url_referral=vads_url_referral, + vads_url_refused=vads_url_refused, + vads_url_success=vads_url_success, + vads_url_return=vads_url_return, + ) + + def test_generateManualPaymentPage_registeredTransaction(self): + event = self.createWechatEvent() + payment = self.createPaymentTransaction() + event.edit(destination_value=payment) + _ , _ = payment.PaymentTransaction_generateWechatId() + self.assertRaises(ValueError, event.generateManualPaymentPage, + vads_url_cancel=vads_url_cancel, + vads_url_error=vads_url_error, + vads_url_referral=vads_url_referral, + vads_url_refused=vads_url_refused, + vads_url_success=vads_url_success, + vads_url_return=vads_url_return, + ) + + def test_generateManualPaymentPage_noPaymentService(self): + event = self.createWechatEvent() + payment = self.createPaymentTransaction() + event.edit(destination_value=payment) + self.assertRaises(AttributeError, event.generateManualPaymentPage, + vads_url_cancel=vads_url_cancel, + vads_url_error=vads_url_error, + vads_url_referral=vads_url_referral, + vads_url_refused=vads_url_refused, + vads_url_success=vads_url_success, + vads_url_return=vads_url_return, + ) + + def test_generateManualPaymentPage_noCurrency(self): + event = self.createWechatEvent() + payment = self.createPaymentTransaction() + event.edit( + destination_value=payment, + source="portal_secure_payments/slapos_wechat_test", + ) + self.assertRaises(AttributeError, event.generateManualPaymentPage, + vads_url_cancel=vads_url_cancel, + vads_url_error=vads_url_error, + vads_url_referral=vads_url_referral, + vads_url_refused=vads_url_refused, + vads_url_success=vads_url_success, + vads_url_return=vads_url_return, + ) + + def test_generateManualPaymentPage_defaultUseCase(self): + event = self.createWechatEvent() + payment = self.createPaymentTransaction() + payment.edit( + resource="currency_module/EUR", + ) + event.edit( + destination_value=payment, + source="portal_secure_payments/slapos_wechat_test", + ) + + before_date = DateTime() + self._simulatePaymentTransaction_getTotalPayablePrice() + try: + event.generateManualPaymentPage( + vads_url_cancel=vads_url_cancel, + vads_url_error=vads_url_error, + vads_url_referral=vads_url_referral, + vads_url_refused=vads_url_refused, + vads_url_success=vads_url_success, + vads_url_return=vads_url_return, + ) + finally: + self._dropPaymentTransaction_getTotalPayablePrice() + after_date = DateTime() + + # Payment start date is modified + self.assertTrue(payment.getStartDate() >= before_date) + self.assertTrue(payment.getStopDate() <= after_date) + + # Payment is registered + transaction_date, transaction_id = \ + payment.PaymentTransaction_getWechatId() + self.assertNotEqual(transaction_date, None) + self.assertNotEqual(transaction_id, None) + + # Event state + self.assertEqual(event.getValidationState(), "acknowledged") + + data_dict = { + 'vads_language': 'en', + 'vads_url_cancel': vads_url_cancel, + 'vads_url_error': vads_url_error, + 'vads_url_referral': vads_url_referral, + 'vads_url_refused': vads_url_refused, + 'vads_url_success': vads_url_success, + 'vads_url_return': vads_url_return, + 'vads_trans_date': payment.getStartDate().toZone('UTC')\ + .asdatetime().strftime('%Y%m%d%H%M%S'), + 'vads_amount': str(int(HARDCODED_PRICE * -100)), + 'vads_currency': 978, + 'vads_trans_id': transaction_id, + 'vads_site_id': 'foo', + } + # Calculate the signature... + self.portal.portal_secure_payments.slapos_wechat_test._getFieldList(data_dict) + data_dict['action'] = 'https://secure.wechat.eu/vads-payment/' + + expected_html_page = \ + '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w'\ + '3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">\n<html xmlns="http://www.w3.or'\ + 'g/1999/xhtml" xml:lang="en" lang="en">\n<head>\n <meta http-equiv="Co'\ + 'ntent-Type" content="text/html; charset=utf-8" />\n <meta http-equiv='\ + '"Content-Script-Type" content="text/javascript" />\n <meta http-equiv'\ + '="Content-Style-Type" content="text/css" />\n <title>title</title>\n<'\ + '/head>\n<body onload="document.payment.submit();">\n<form method="POST'\ + '" id="payment" name="payment"\n action="%(action)s">\n\n <input '\ + 'type="hidden" name="vads_url_return"\n value="'\ + '%(vads_url_return)s">\n\n\n <input type="hidden" name="vads_site_id" '\ + 'value="%(vads_site_id)s">\n\n\n <input type="hidden" name="vads_url_e'\ + 'rror"\n value="%(vads_url_error)s">\n\n\n <input type="hidden'\ + '" name="vads_trans_id" value="%(vads_trans_id)s">\n\n\n <input type="'\ + 'hidden" name="vads_action_mode"\n value="INTERACTIVE">\n\n\n '\ + '<input type="hidden" name="vads_url_success"\n value="'\ + '%(vads_url_success)s">\n\n\n <input type="hidden" name="vads_url_refe'\ + 'rral"\n value="%(vads_url_referral)s">\n\n\n <input type="hid'\ + 'den" name="vads_page_action"\n value="PAYMENT">\n\n\n <input '\ + 'type="hidden" name="vads_trans_date"\n value="'\ + '%(vads_trans_date)s">\n\n\n <input type="hidden" name="vads_url_refus'\ + 'ed"\n value="%(vads_url_refused)s">\n\n\n <input type="hidden'\ + '" name="vads_url_cancel"\n value="%(vads_url_cancel)s">\n\n\n '\ + ' <input type="hidden" name="vads_ctx_mode" value="TEST">\n\n\n <input '\ + 'type="hidden" name="vads_payment_config"\n value="SINGLE">\n\n'\ + '\n <input type="hidden" name="vads_contrib" value="ERP5">\n\n\n <inp'\ + 'ut type="hidden" name="signature"\n value="%(signature)s">\n\n'\ + '\n <input type="hidden" name="vads_language" value="%(vads_language)s">\n\n\n <inpu'\ + 't type="hidden" name="vads_currency" value="%(vads_currency)s">\n\n\n '\ + ' <input type="hidden" name="vads_amount" value="%(vads_amount)s">\n\n\n'\ + ' <input type="hidden" name="vads_version" value="V2">\n\n<input type="s'\ + 'ubmit" value="Click to pay">\n</form>\n</body>\n</html>' % data_dict + + # Event message state + event_message_list = event.contentValues(portal_type="Wechat Event Message") + self.assertEqual(len(event_message_list), 1) + message = event_message_list[0] + self.assertEqual(message.getTitle(), 'Shown Page') + self.assertEqual(message.getTextContent(), expected_html_page, + '\n'.join([q for q in difflib.unified_diff(expected_html_page.split('\n'), + message.getTextContent().split('\n'))])) + + def test_updateStatus_noAccountingTransaction(self): + event = self.createWechatEvent() + self.assertRaises(AttributeError, event.updateStatus) + + def test_updateStatus_notRegisteredTransaction(self): + event = self.createWechatEvent() + payment = self.createPaymentTransaction() + event.edit( + destination_value=payment, + ) + self.assertRaises(ValueError, event.updateStatus) + + def test_updateStatus_noPaymentService(self): + event = self.createWechatEvent() + payment = self.createPaymentTransaction() + event.edit( + destination_value=payment, + ) + _ , _ = payment.PaymentTransaction_generateWechatId() + self.assertRaises(AttributeError, event.updateStatus) + + def mockSoapGetInfo(self, method_to_call, expected_args, result_tuple): + payment_service = self.portal.portal_secure_payments.slapos_wechat_test + def mocksoad_getInfo(arg1, arg2): + self.assertEqual(arg1, expected_args[0]) + self.assertEqual(arg2, expected_args[1]) + return result_tuple + setattr(payment_service, 'soap_getInfo', mocksoad_getInfo) + try: + return method_to_call() + finally: + del payment_service.soap_getInfo + + def _simulateWechatEvent_processUpdate(self): + script_name = 'WechatEvent_processUpdate' + if script_name in self.portal.portal_skins.custom.objectIds(): + raise ValueError('Precondition failed: %s exists in custom' % script_name) + createZODBPythonScript(self.portal.portal_skins.custom, + script_name, + '*args, **kwargs', + '# Script body\n' +"""portal_workflow = context.portal_workflow +portal_workflow.doActionFor(context, action='edit_action', comment='Visited by WechatEvent_processUpdate') """ ) + self.commit() + + def _dropWechatEvent_processUpdate(self): + script_name = 'WechatEvent_processUpdate' + if script_name in self.portal.portal_skins.custom.objectIds(): + self.portal.portal_skins.custom.manage_delObjects(script_name) + self.commit() + + def test_updateStatus_defaultUseCase(self): + event = self.createWechatEvent() + payment = self.createPaymentTransaction() + event.edit( + destination_value=payment, + source="portal_secure_payments/slapos_wechat_test", + ) + transaction_date, transaction_id = \ + payment.PaymentTransaction_generateWechatId() + + mocked_data_kw = 'mocked_data_kw' + mocked_signature = 'mocked_signature' + mocked_sent_text = 'mocked_sent_text' + mocked_received_text = 'mocked_received_text' + + self._simulateWechatEvent_processUpdate() + try: + self.mockSoapGetInfo( + event.updateStatus, + (transaction_date.toZone('UTC').asdatetime(), transaction_id), + (mocked_data_kw, mocked_signature, mocked_sent_text, mocked_received_text), + ) + finally: + self._dropWechatEvent_processUpdate() + + event_message_list = event.contentValues(portal_type="Wechat Event Message") + self.assertEqual(len(event_message_list), 2) + + sent_message = [x for x in event_message_list \ + if x.getTitle() == 'Sent SOAP'][0] + self.assertEqual(sent_message.getTextContent(), mocked_sent_text) + + received_message = [x for x in event_message_list \ + if x.getTitle() == 'Received SOAP'][0] + self.assertEqual(received_message.getPredecessor(), + sent_message.getRelativeUrl()) + self.assertEqual(received_message.getTextContent(), mocked_received_text) + + self.assertEqual( + 'Visited by WechatEvent_processUpdate', + event.workflow_history['edit_workflow'][-1]['comment']) + diff --git a/master/bt5/slapos_wechat/TestTemplateItem/portal_components/test.erp5.testSlapOSWechatWorkflow.xml b/master/bt5/slapos_wechat/TestTemplateItem/portal_components/test.erp5.testSlapOSWechatWorkflow.xml new file mode 100644 index 0000000000000000000000000000000000000000..c6c58aa18bc232d7fcc7d67a9c9583b3a811b026 --- /dev/null +++ b/master/bt5/slapos_wechat/TestTemplateItem/portal_components/test.erp5.testSlapOSWechatWorkflow.xml @@ -0,0 +1,124 @@ +<?xml version="1.0"?> +<ZopeData> + <record id="1" aka="AAAAAAAAAAE="> + <pickle> + <global name="Test Component" module="erp5.portal_type"/> + </pickle> + <pickle> + <dictionary> + <item> + <key> <string>_recorded_property_dict</string> </key> + <value> + <persistent> <string encoding="base64">AAAAAAAAAAI=</string> </persistent> + </value> + </item> + <item> + <key> <string>default_reference</string> </key> + <value> <string>testSlapOSWechatWorkflow</string> </value> + </item> + <item> + <key> <string>description</string> </key> + <value> + <none/> + </value> + </item> + <item> + <key> <string>id</string> </key> + <value> <string>test.erp5.testSlapOSWechatWorkflow</string> </value> + </item> + <item> + <key> <string>portal_type</string> </key> + <value> <string>Test Component</string> </value> + </item> + <item> + <key> <string>sid</string> </key> + <value> + <none/> + </value> + </item> + <item> + <key> <string>text_content_error_message</string> </key> + <value> + <tuple/> + </value> + </item> + <item> + <key> <string>text_content_warning_message</string> </key> + <value> + <tuple/> + </value> + </item> + <item> + <key> <string>version</string> </key> + <value> <string>erp5</string> </value> + </item> + <item> + <key> <string>workflow_history</string> </key> + <value> + <persistent> <string encoding="base64">AAAAAAAAAAM=</string> </persistent> + </value> + </item> + </dictionary> + </pickle> + </record> + <record id="2" aka="AAAAAAAAAAI="> + <pickle> + <global name="PersistentMapping" module="Persistence.mapping"/> + </pickle> + <pickle> + <dictionary> + <item> + <key> <string>data</string> </key> + <value> + <dictionary/> + </value> + </item> + </dictionary> + </pickle> + </record> + <record id="3" aka="AAAAAAAAAAM="> + <pickle> + <global name="PersistentMapping" module="Persistence.mapping"/> + </pickle> + <pickle> + <dictionary> + <item> + <key> <string>data</string> </key> + <value> + <dictionary> + <item> + <key> <string>component_validation_workflow</string> </key> + <value> + <persistent> <string encoding="base64">AAAAAAAAAAQ=</string> </persistent> + </value> + </item> + </dictionary> + </value> + </item> + </dictionary> + </pickle> + </record> + <record id="4" aka="AAAAAAAAAAQ="> + <pickle> + <global name="WorkflowHistoryList" module="Products.ERP5Type.patches.WorkflowTool"/> + </pickle> + <pickle> + <tuple> + <none/> + <list> + <dictionary> + <item> + <key> <string>action</string> </key> + <value> <string>validate</string> </value> + </item> + <item> + <key> <string>validation_state</string> </key> + <value> <string>validated</string> </value> + </item> + </dictionary> + </list> + <none/> + </tuple> + </pickle> + </record> +</ZopeData> diff --git a/master/bt5/slapos_wechat/bt/template_test_id_list b/master/bt5/slapos_wechat/bt/template_test_id_list index 8c2cd79ba95d74dd8609e436c79cfab12b50e33c..f0cb8f91c7ef1f0378a0b75f229383ba7fa2b5b1 100644 --- a/master/bt5/slapos_wechat/bt/template_test_id_list +++ b/master/bt5/slapos_wechat/bt/template_test_id_list @@ -1 +1,2 @@ -test.erp5.testSlapOSWechatSkins \ No newline at end of file +test.erp5.testSlapOSWechatSkins +test.erp5.testSlapOSWechatWorkflow \ No newline at end of file