Commit 98a0ddb4 authored by Jérome Perrin's avatar Jérome Perrin

Merge remote-tracking branch 'upstream/master' into zope4py3

parents 14a2a922 dfd1873b
Pipeline #39372 failed with stage
in 0 seconds
line_list = []
for line in context.contentValues(
portal_type=context.getPortalAccountingMovementTypeList()):
has_amount = True
if side == 'source':
account = line.getSourceValue(portal_type='Account')
if test_compta_demat_compatibility:
has_amount = bool(
line.getSourceTotalAssetPrice()
if line.hasSourceTotalAssetPrice() else line.getQuantity())
else:
assert side == 'destination'
account = line.getDestinationValue(portal_type='Account')
if test_compta_demat_compatibility:
has_amount = bool(
line.getDestinationTotalAssetPrice()
if line.hasDestinationTotalAssetPrice() else line.getQuantity())
if account is not None and has_amount:
line_list.append(line)
return line_list
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="PythonScript" module="Products.PythonScripts.PythonScript"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>_bind_names</string> </key>
<value>
<object>
<klass>
<global name="_reconstructor" module="copy_reg"/>
</klass>
<tuple>
<global name="NameAssignments" module="Shared.DC.Scripts.Bindings"/>
<global name="object" module="__builtin__"/>
<none/>
</tuple>
<state>
<dictionary>
<item>
<key> <string>_asgns</string> </key>
<value>
<dictionary>
<item>
<key> <string>name_container</string> </key>
<value> <string>container</string> </value>
</item>
<item>
<key> <string>name_context</string> </key>
<value> <string>context</string> </value>
</item>
<item>
<key> <string>name_m_self</string> </key>
<value> <string>script</string> </value>
</item>
<item>
<key> <string>name_subpath</string> </key>
<value> <string>traverse_subpath</string> </value>
</item>
</dictionary>
</value>
</item>
</dictionary>
</state>
</object>
</value>
</item>
<item>
<key> <string>_params</string> </key>
<value> <string>side, test_compta_demat_compatibility</string> </value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>AccountingTransaction_getFECXMLAccountingTransactionLineList</string> </value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
<ecriture xmlns:tal="http://xml.zope.org/namespaces/tal">
<ecriture
xmlns:tal="http://xml.zope.org/namespaces/tal"
tal:define="line_list python:context.AccountingTransaction_getFECXMLAccountingTransactionLineList('destination', options['test_compta_demat_compatibility'])"
tal:condition="line_list">
<EcritureNum tal:content="context/getDestinationReference">Specific Reference</EcritureNum>
<EcritureDate tal:content="python: context.getStopDate().strftime('%Y-%m-%d')">Specific Date</EcritureDate>
<EcritureLib tal:content="context/getTitle">Title</EcritureLib>
......@@ -7,9 +10,8 @@
<tal:block tal:replace="nothing"><EcritureLet></EcritureLet>
<DateLet></DateLet></tal:block>
<ValidDate tal:content="python: context.AccountingTransaction_getDeliverDate().strftime('%Y-%m-%d')">Modification Date</ValidDate>
<tal:block tal:repeat="line python:context.contentValues(portal_type=context.getPortalAccountingMovementTypeList())"><ligne
tal:define="account python:line.getDestinationValue(portal_type='Account')"
tal:condition="python: account is not None and ((line.getDestinationTotalAssetPrice() if line.hasDestinationTotalAssetPrice() else line.getQuantity()) or not options['test_compta_demat_compatibility'])">
<tal:block tal:repeat="line line_list"><ligne
tal:define="account python:line.getDestinationValue(portal_type='Account')">
<CompteNum tal:content="account/Account_getGapId">Reference Compte (Account_getGapId)</CompteNum>
<CompteLib tal:content="line/Movement_getDestinationCompteLib">Translated Title Compte</CompteLib>
<tal:block tal:condition="python: account.getAccountType() in ('asset/receivable', 'liability/payable')"
......
<ecriture xmlns:tal="http://xml.zope.org/namespaces/tal">
<ecriture
xmlns:tal="http://xml.zope.org/namespaces/tal"
tal:define="line_list python:context.AccountingTransaction_getFECXMLAccountingTransactionLineList('source', options['test_compta_demat_compatibility'])"
tal:condition="line_list">
<EcritureNum tal:content="context/getSourceReference">Specific Reference</EcritureNum>
<EcritureDate tal:content="python: context.getStartDate().strftime('%Y-%m-%d')">Specific Date</EcritureDate>
<EcritureLib tal:content="context/getTitle">Title</EcritureLib>
......@@ -7,9 +10,8 @@
<tal:block tal:replace="nothing"><EcritureLet></EcritureLet>
<DateLet></DateLet></tal:block>
<ValidDate tal:content="python: context.AccountingTransaction_getDeliverDate().strftime('%Y-%m-%d')">Modification Date</ValidDate>
<tal:block tal:repeat="line python:context.contentValues(portal_type=context.getPortalAccountingMovementTypeList())"><ligne
tal:define="account python:line.getSourceValue(portal_type='Account')"
tal:condition="python: account is not None and ((line.getSourceTotalAssetPrice() if line.hasSourceTotalAssetPrice() else line.getQuantity()) or not options['test_compta_demat_compatibility'])">
<tal:block tal:repeat="line line_list"><ligne
tal:define="account python:line.getSourceValue(portal_type='Account')">
<CompteNum tal:content="account/Account_getGapId">Reference Compte (Account_getGapId)</CompteNum>
<CompteLib tal:content="line/Movement_getSourceCompteLib">Translated Title Compte</CompteLib>
<tal:block tal:condition="python: account.getAccountType() in ('asset/receivable', 'liability/payable')"
......
......@@ -31,7 +31,6 @@
"""
import six
import unittest
import zipfile
if six.PY2:
from email import message_from_string as message_from_bytes
......@@ -46,6 +45,7 @@ from AccessControl.SecurityManagement import newSecurityManager
from erp5.component.test.testAccounting import AccountingTestCase
class TestAccounting_l10n_fr(AccountingTestCase):
"""Test Accounting L10N FR
"""
......@@ -405,7 +405,29 @@ class TestAccounting_l10n_fr(AccountingTestCase):
def test_ValidDate(self):
account_module = self.portal.account_module
invoice = self._makeOne(
invoice_source = self._makeOne(
portal_type='Purchase Invoice Transaction',
title='Premiere Ecriture',
simulation_state='delivered',
reference='1',
source_section_value=self.organisation_module.supplier,
stop_date=DateTime(2014, 2, 2),
lines=(dict(source_value=account_module.payable,
source_debit=132.00),
dict(source_value=account_module.refundable_vat,
source_credit=22.00),
dict(source_value=account_module.goods_purchase,
source_credit=110.00)))
assert invoice_source.workflow_history['accounting_workflow'][-1]['action'] == 'deliver'
invoice_source.workflow_history['accounting_workflow'][-1]['time'] = DateTime(2001, 2, 3)
tree = etree.fromstring(
invoice_source.AccountingTransaction_viewAsSourceFECXML(
test_compta_demat_compatibility=True))
self.assertEqual(tree.xpath('//ValidDate/text()'), ['2001-02-03'])
invoice_destination = self._makeOne(
portal_type='Purchase Invoice Transaction',
title='Premiere Ecriture',
simulation_state='delivered',
......@@ -419,15 +441,11 @@ class TestAccounting_l10n_fr(AccountingTestCase):
dict(destination_value=account_module.goods_purchase,
destination_credit=110.00)))
assert invoice.workflow_history['accounting_workflow'][-1]['action'] == 'deliver'
invoice.workflow_history['accounting_workflow'][-1]['time'] = DateTime(2001, 2, 3)
assert invoice_destination.workflow_history['accounting_workflow'][-1]['action'] == 'deliver'
invoice_destination.workflow_history['accounting_workflow'][-1]['time'] = DateTime(2001, 2, 3)
tree = etree.fromstring(
invoice.AccountingTransaction_viewAsSourceFECXML(
test_compta_demat_compatibility=True))
self.assertEqual(tree.xpath('//ValidDate/text()'), ['2001-02-03'])
tree = etree.fromstring(
invoice.AccountingTransaction_viewAsDestinationFECXML(
invoice_destination.AccountingTransaction_viewAsDestinationFECXML(
test_compta_demat_compatibility=True))
self.assertEqual(tree.xpath('//ValidDate/text()'), ['2001-02-03'])
......@@ -551,9 +569,92 @@ class TestAccounting_l10n_fr(AccountingTestCase):
'//ecriture/PieceRef[text()="source"]/../ligne/Credit/text()'),
['0.00', '40.00', '200.00'])
def test_SkipEmptyTransactions(self):
# Don't include transactions without lines, because they are
# reported as invalid by Test Compta Demat
account_module = self.portal.account_module
self._makeOne(
portal_type='Purchase Invoice Transaction',
title='destination 0',
simulation_state='delivered',
reference='destination_0_lines',
source_section_value=self.organisation_module.supplier,
stop_date=DateTime(2014, 2, 2),
lines=(
dict(
destination_value=account_module.payable, destination_debit=0.00),
dict(
destination_value=account_module.payable,
destination_debit=10000.00,
destination_asset_debit=0.00),
dict(
destination_value=account_module.refundable_vat,
destination_credit=0.00),
dict(
destination_value=account_module.refundable_vat,
destination_credit=10000.00,
destination_asset_credit=0.00)))
self._makeOne(
portal_type='Purchase Invoice Transaction',
title='destination no',
simulation_state='delivered',
reference='destination_no_lines',
source_section_value=self.organisation_module.supplier,
stop_date=DateTime(2014, 2, 2),
lines=())
self._makeOne(
portal_type='Sale Invoice Transaction',
title='source 0',
simulation_state='delivered',
reference='source_0_lines',
destination_section_value=self.organisation_module.client_2,
start_date=DateTime(2014, 3, 1),
lines=(
dict(source_value=account_module.receivable, source_debit=0.00),
dict(source_value=account_module.collected_vat, source_credit=0.00)))
self._makeOne(
portal_type='Sale Invoice Transaction',
title='source no',
simulation_state='delivered',
reference='source_no_lines',
destination_section_value=self.organisation_module.client_2,
start_date=DateTime(2014, 3, 1),
lines=())
self.tic()
self.portal.accounting_module.AccountingTransactionModule_viewFrenchAccountingTransactionFile(
section_category='group/demo_group',
section_category_strict=False,
at_date=DateTime(2014, 12, 31),
simulation_state=['delivered'])
self.tic()
tree = etree.fromstring(self.getFECFromMailMessage())
self.validateFECXML(tree)
self.assertEqual(tree.xpath('//ecriture'), [])
def test_PieceRefDefaultValue(self):
account_module = self.portal.account_module
invoice = self._makeOne(
invoice_source = self._makeOne(
portal_type='Purchase Invoice Transaction',
title='Premiere Ecriture',
simulation_state='delivered',
source_section_value=self.organisation_module.supplier,
stop_date=DateTime(2014, 2, 2),
lines=(
dict(
source_value=account_module.payable, source_debit=132.00),
dict(
source_value=account_module.refundable_vat,
source_credit=22.00),
dict(
source_value=account_module.goods_purchase,
source_credit=110.00)))
invoice_source.setSourceReference('source_reference')
invoice_destination = self._makeOne(
portal_type='Purchase Invoice Transaction',
title='Premiere Ecriture',
simulation_state='delivered',
......@@ -568,16 +669,14 @@ class TestAccounting_l10n_fr(AccountingTestCase):
dict(
destination_value=account_module.goods_purchase,
destination_credit=110.00)))
invoice.setSourceReference('source_reference')
invoice.setDestinationReference('destination_reference')
invoice_destination.setDestinationReference('destination_reference')
tree = etree.fromstring(
invoice.AccountingTransaction_viewAsSourceFECXML(
invoice_source.AccountingTransaction_viewAsSourceFECXML(
test_compta_demat_compatibility=True))
self.assertEqual(tree.xpath('//EcritureNum/text()'), ['source_reference'])
self.assertEqual(tree.xpath('//PieceRef/text()'), ['source_reference'])
tree = etree.fromstring(
invoice.AccountingTransaction_viewAsDestinationFECXML(
invoice_destination.AccountingTransaction_viewAsDestinationFECXML(
test_compta_demat_compatibility=True))
self.assertEqual(
tree.xpath('//EcritureNum/text()'), ['destination_reference'])
......@@ -585,12 +684,12 @@ class TestAccounting_l10n_fr(AccountingTestCase):
tree.xpath('//PieceRef/text()'), ['destination_reference'])
tree = etree.fromstring(
invoice.AccountingTransaction_viewAsSourceFECXML(
invoice_source.AccountingTransaction_viewAsSourceFECXML(
test_compta_demat_compatibility=False))
self.assertEqual(tree.xpath('//EcritureNum/text()'), ['source_reference'])
self.assertEqual([n.text for n in tree.xpath('//PieceRef')], [None])
tree = etree.fromstring(
invoice.AccountingTransaction_viewAsDestinationFECXML(
invoice_destination.AccountingTransaction_viewAsDestinationFECXML(
test_compta_demat_compatibility=False))
self.assertEqual(
tree.xpath('//EcritureNum/text()'), ['destination_reference'])
......@@ -661,9 +760,3 @@ class TestAccounting_l10n_fr(AccountingTestCase):
tree.xpath(
'//ecriture/PieceRef[text()="source"]/../ligne/Credit/text()'),
['0.00', '345.00'])
def test_suite():
suite = unittest.TestSuite()
suite.addTest(unittest.makeSuite(TestAccounting_l10n_fr))
return suite
from Products.ERP5Type.Document import newTempBase
from DateTime import DateTime
from zExceptions import Unauthorized
if REQUEST is not None:
raise Unauthorized
portal = context.getPortalObject()
# Use only the first entry. This prevents change the rss content
# too often whenever multiple activities are failing over time.
message_list = portal.portal_activities.getMessageTempObjectList(processing_node=-2,
count=1)
if not len(message_list):
return []
message = portal.Base_translateString('You have one or more activity failures.')
# Make compatible with renderjs_runner
web_site = context.getWebSiteValue()
if web_site is None:
web_site_url = portal.absolute_url()
else:
web_site_url = web_site.absolute_url() + "/#"
return [
newTempBase(portal, "rss_entry",
uid=message_list[0].uid,
date=DateTime().earliestTime(),
link="%s/portal_activities" % web_site_url,
title=message)]
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="PythonScript" module="Products.PythonScripts.PythonScript"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>_bind_names</string> </key>
<value>
<object>
<klass>
<global name="_reconstructor" module="copy_reg"/>
</klass>
<tuple>
<global name="NameAssignments" module="Shared.DC.Scripts.Bindings"/>
<global name="object" module="__builtin__"/>
<none/>
</tuple>
<state>
<dictionary>
<item>
<key> <string>_asgns</string> </key>
<value>
<dictionary>
<item>
<key> <string>name_container</string> </key>
<value> <string>container</string> </value>
</item>
<item>
<key> <string>name_context</string> </key>
<value> <string>context</string> </value>
</item>
<item>
<key> <string>name_m_self</string> </key>
<value> <string>script</string> </value>
</item>
<item>
<key> <string>name_subpath</string> </key>
<value> <string>traverse_subpath</string> </value>
</item>
</dictionary>
</value>
</item>
</dictionary>
</state>
</object>
</value>
</item>
<item>
<key> <string>_params</string> </key>
<value> <string>REQUEST=None, **kw</string> </value>
</item>
<item>
<key> <string>_proxy_roles</string> </key>
<value>
<tuple>
<string>Manager</string>
</tuple>
</value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>ERP5Site_getPendingErrorList</string> </value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="ERP5 Form" module="erp5.portal_type"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>_bind_names</string> </key>
<value>
<object>
<klass>
<global name="_reconstructor" module="copy_reg"/>
</klass>
<tuple>
<global name="NameAssignments" module="Shared.DC.Scripts.Bindings"/>
<global name="object" module="__builtin__"/>
<none/>
</tuple>
<state>
<dictionary>
<item>
<key> <string>_asgns</string> </key>
<value>
<dictionary/>
</value>
</item>
</dictionary>
</state>
</object>
</value>
</item>
<item>
<key> <string>_objects</string> </key>
<value>
<tuple/>
</value>
</item>
<item>
<key> <string>action</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>action_title</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>description</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>edit_order</string> </key>
<value>
<list/>
</value>
</item>
<item>
<key> <string>encoding</string> </key>
<value> <string>UTF-8</string> </value>
</item>
<item>
<key> <string>enctype</string> </key>
<value> <string>application/x-www-form-urlencoded</string> </value>
</item>
<item>
<key> <string>group_list</string> </key>
<value>
<list>
<string>bottom</string>
<string>hidden</string>
</list>
</value>
</item>
<item>
<key> <string>groups</string> </key>
<value>
<dictionary>
<item>
<key> <string>bottom</string> </key>
<value>
<list>
<string>listbox</string>
</list>
</value>
</item>
<item>
<key> <string>hidden</string> </key>
<value>
<list/>
</value>
</item>
</dictionary>
</value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>ERP5Site_viewPendingErrorListAsRSS</string> </value>
</item>
<item>
<key> <string>method</string> </key>
<value> <string>POST</string> </value>
</item>
<item>
<key> <string>name</string> </key>
<value> <string>ERP5Site_viewPendingErrorListAsRSS</string> </value>
</item>
<item>
<key> <string>pt</string> </key>
<value> <string>rss_view</string> </value>
</item>
<item>
<key> <string>row_length</string> </key>
<value> <int>4</int> </value>
</item>
<item>
<key> <string>stored_encoding</string> </key>
<value> <string>UTF-8</string> </value>
</item>
<item>
<key> <string>title</string> </key>
<value> <string>Pending Errors</string> </value>
</item>
<item>
<key> <string>unicode_mode</string> </key>
<value> <int>0</int> </value>
</item>
<item>
<key> <string>update_action</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>update_action_title</string> </key>
<value> <string></string> </value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="ProxyField" module="Products.ERP5Form.ProxyField"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>delegated_list</string> </key>
<value>
<list>
<string>all_columns</string>
<string>columns</string>
<string>count_method</string>
<string>editable_columns</string>
<string>hide_rows_on_no_search_criterion</string>
<string>lines</string>
<string>list_method</string>
<string>portal_types</string>
<string>search_columns</string>
<string>selection_name</string>
<string>sort</string>
<string>sort_columns</string>
<string>title</string>
</list>
</value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>listbox</string> </value>
</item>
<item>
<key> <string>message_values</string> </key>
<value>
<dictionary>
<item>
<key> <string>external_validator_failed</string> </key>
<value> <string>The input failed the external validator.</string> </value>
</item>
</dictionary>
</value>
</item>
<item>
<key> <string>overrides</string> </key>
<value>
<dictionary>
<item>
<key> <string>field_id</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>form_id</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>target</string> </key>
<value> <string></string> </value>
</item>
</dictionary>
</value>
</item>
<item>
<key> <string>tales</string> </key>
<value>
<dictionary>
<item>
<key> <string>field_id</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>form_id</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>target</string> </key>
<value> <string></string> </value>
</item>
</dictionary>
</value>
</item>
<item>
<key> <string>values</string> </key>
<value>
<dictionary>
<item>
<key> <string>all_columns</string> </key>
<value>
<list/>
</value>
</item>
<item>
<key> <string>columns</string> </key>
<value>
<list>
<tuple>
<string>title</string>
<string>title</string>
</tuple>
<tuple>
<string>link</string>
<string>link</string>
</tuple>
<tuple>
<string>uid</string>
<string>guid</string>
</tuple>
<tuple>
<string>date</string>
<string>pubDate</string>
</tuple>
</list>
</value>
</item>
<item>
<key> <string>count_method</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>editable_columns</string> </key>
<value>
<list/>
</value>
</item>
<item>
<key> <string>field_id</string> </key>
<value> <string>my_list_mode_listbox</string> </value>
</item>
<item>
<key> <string>form_id</string> </key>
<value> <string>Base_viewFieldLibrary</string> </value>
</item>
<item>
<key> <string>hide_rows_on_no_search_criterion</string> </key>
<value> <int>0</int> </value>
</item>
<item>
<key> <string>lines</string> </key>
<value> <int>30</int> </value>
</item>
<item>
<key> <string>list_method</string> </key>
<value>
<persistent> <string encoding="base64">AAAAAAAAAAI=</string> </persistent>
</value>
</item>
<item>
<key> <string>portal_types</string> </key>
<value>
<list/>
</value>
</item>
<item>
<key> <string>search_columns</string> </key>
<value>
<list/>
</value>
</item>
<item>
<key> <string>selection_name</string> </key>
<value> <string>pending_failure_selection</string> </value>
</item>
<item>
<key> <string>sort</string> </key>
<value>
<list/>
</value>
</item>
<item>
<key> <string>sort_columns</string> </key>
<value>
<list/>
</value>
</item>
<item>
<key> <string>target</string> </key>
<value> <string>Click to edit the target</string> </value>
</item>
<item>
<key> <string>title</string> </key>
<value> <string>Pending Errors</string> </value>
</item>
</dictionary>
</value>
</item>
</dictionary>
</pickle>
</record>
<record id="2" aka="AAAAAAAAAAI=">
<pickle>
<global name="Method" module="Products.Formulator.MethodField"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>method_name</string> </key>
<value> <string>ERP5Site_getPendingErrorList</string> </value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
......@@ -5,7 +5,6 @@
#
##############################################################################
import random
import transaction
from Products.ERP5Type.tests.SecurityTestCase import SecurityTestCase
from Products.ERP5Type.tests.utils import DummyMailHost
......@@ -67,11 +66,6 @@ class TestOfficeJSSDKConfigurator(SecurityTestCase):
# Execute the business configuration if not installed
business_configuration = self.getBusinessConfiguration()
if (business_configuration.getSimulationState() != 'installed'):
self.portal.portal_caches.erp5_site_global_id = '%s' % random.random()
self.portal.portal_caches._p_changed = 1
self.commit()
self.portal.portal_caches.updateCache()
self.bootstrapSite()
self.commit()
......
......@@ -35,7 +35,6 @@ MAIN FILE: generate book in different output formats
import re
import six
from Products.PythonScripts.standard import html_quote
from Products.ERP5Type.Utils import str2bytes, bytes2str, unicode2str
from base64 import b64encode
......@@ -75,15 +74,15 @@ if not book_content:
return
book_aggregate_list = []
book_revision = book.getRevision()
book_modification_date = book.getModificationDate()
book_modification_date = book.getEffectiveDate() or book.getModificationDate()
book_language = book.getLanguage()
# XXX sigh for passing "" around
book_reference = html_quote(override_document_reference) if override_document_reference else book.getReference()
book_short_title = html_quote(override_document_short_title) if override_document_short_title else book.getShortTitle()
book_version = html_quote(override_document_version) if override_document_version else book.getVersion() or "001"
book_description = html_quote(override_document_description) if override_document_description else book.getDescription()
book_title = html_quote(override_document_title) if override_document_title else book.getTitle()
book_reference = override_document_reference if override_document_reference else book.getReference()
book_short_title = override_document_short_title if override_document_short_title else book.getShortTitle()
book_version = override_document_version if override_document_version else book.getVersion() or "001"
book_description = override_document_description if override_document_description else book.getDescription()
book_title = override_document_title if override_document_title else book.getTitle()
if six.PY2 and isinstance(book_content, six.text_type):
book_content = unicode2str(book_content)
......@@ -99,7 +98,7 @@ if override_batch_mode:
book_revision = "1"
book_short_date = book_modification_date.strftime('%Y-%m-%d')
if book_language:
if book_language and 'AcceptLanguage' in book.REQUEST:
book.REQUEST['AcceptLanguage'].set(book_language, 10)
else:
book_language = blank
......
......@@ -497,3 +497,13 @@ class TestCorporateIdentityMethod(ERP5TypeTestCase):
)
self.assertEqual(output, None)
def test_escapeOverridden(self):
book_export = self.portal.web_page_module.template_test_book_input_003_en_html.WebPage_viewAsBook(
format="html",
override_document_description='<script>alert("description");</script>',
override_document_short_title='<script>alert("short title");</script>',
override_document_title='<script>alert("title");</script>',
override_document_version='<script>alert("001");</script>',
override_document_reference='<script>alert("reference");</script>',
)
self.assertNotIn("<script>alert", book_export)
......@@ -127,7 +127,7 @@
<dictionary>
<item>
<key> <string>_text</string> </key>
<value> <string>python: here.getResourceValue().getVariationBaseCategoryItemList(omit_optional_variation=1, display_id=\'translated_title\')</string> </value>
<value> <string>python: here.getResourceValue().getVariationBaseCategoryItemList(display_id=\'translated_title\')</string> </value>
</item>
</dictionary>
</pickle>
......
......@@ -27,7 +27,6 @@
#
##############################################################################
import random
import unittest
from Products.ERP5Type.tests.ERP5TypeFunctionalTestCase import \
......@@ -91,11 +90,6 @@ class TestZeleniumStandaloneUserTutorial(ERP5TypeFunctionalTestCase):
# Execute the business configuration if not installed
business_configuration = self.getBusinessConfiguration()
if (business_configuration.getSimulationState() != 'installed'):
self.portal.portal_caches.erp5_site_global_id = '%s' % random.random()
self.portal.portal_caches._p_changed = 1
self.commit()
self.portal.portal_caches.updateCache()
self.bootstrapSite()
self.commit()
......
......@@ -1775,7 +1775,9 @@ class ActivityTool (BaseTool):
return RESPONSE.redirect(self.absolute_url_path() +
'/manageActivitiesAdvanced?manage_tabs_message=Activities%20Cleared')
security.declarePublic('getMessageTempObjectList')
security.declareProtected( CMFCorePermissions.ManagePortal,
'getMessageTempObjectList')
def getMessageTempObjectList(self, **kw):
"""
Get object list of messages waiting in queues
......
......@@ -315,6 +315,7 @@ class Test(ERP5TypeTestCase):
except ImportError:
import traceback
traceback.print_exc(file=global_stream)
traceback.print_exc() # also print on stderr
global_stream.seek(0)
return global_stream.read()
finally:
......
......@@ -300,9 +300,6 @@ if memcache is not None:
if memcached_plugin is None:
raise ValueError('Memcached Plugin does not exists: %r' % (
plugin_path, ))
global_prefix = self.erp5_site_global_id
if global_prefix:
key_prefix = global_prefix + '_' + key_prefix
return SharedDict(memcached_plugin.getConnection(), prefix=key_prefix)
InitializeClass(MemcachedTool)
......
......@@ -291,12 +291,18 @@ def runLiveTest(test_list, verbosity=1, stream=None, request_server_url=None, **
output = stream
if stream is None:
output = StringIO()
def print_and_write(data):
sys.stderr.write(data)
sys.stderr.flush()
return output.write(data)
print_and_write("**Running Live Test:\n")
ZopeTestCase._print = print_and_write
class StderrIOWrapper:
def __init__(self, wrapped):
self._wrapped_io = wrapped
def write(self, data):
sys.stderr.write(data)
return self._wrapped_io.write(data)
def __getattr__(self, attr):
return getattr(self._wrapped_io, attr)
output = StderrIOWrapper(output)
output.write("**Running Live Test:\n")
ZopeTestCase._print = output.write
with warnings.catch_warnings():
warnings.simplefilter(kw['warnings'])
......@@ -306,6 +312,6 @@ def runLiveTest(test_list, verbosity=1, stream=None, request_server_url=None, **
from AccessControl.SecurityManagement import getSecurityManager, setSecurityManager
sm = getSecurityManager()
try:
result = TestRunner(stream=output, verbosity=verbosity).run(suite)
TestRunner(stream=output, verbosity=verbosity).run(suite)
finally:
setSecurityManager(sm)
......@@ -7,7 +7,6 @@
__version__ = '0.3.0'
import base64
import errno
import os
import random
......@@ -17,6 +16,7 @@ import string
import sys
import time
import traceback
import warnings
from six.moves import configparser
from contextlib import contextmanager
from io import BytesIO
......@@ -273,6 +273,10 @@ class ERP5TypeTestCaseMixin(ProcessingNodeTestCase, PortalTestCase, functional.F
def newPassword(self):
""" Generate a password """
forced_password = os.environ.get('insecure_erp5_test_password')
if forced_password:
warnings.warn("Using password set from environment variable")
return forced_password
return ''.join(random.SystemRandom().sample(string.ascii_letters + string.digits, 20))
def login(self, user_name=None, quiet=0):
......@@ -1317,10 +1321,6 @@ class ERP5TypeCommandLineTestCase(ERP5TypeTestCaseMixin):
reindex=reindex,
create_activities=create_activities,
**kw)
sql = kw.get('erp5_sql_connection_string')
if sql:
app[portal_name]._setProperty('erp5_site_global_id',
base64.standard_b64encode(str2bytes(sql)))
if not quiet:
ZopeTestCase._print('done (%.3fs)\n' % (time.time() - _start))
# Release locks
......@@ -1637,7 +1637,7 @@ optimize()
@onsetup
def fortify():
'''Add some extra checks that we don't have at runtime, not to slow down the
system.
system and adjust the system for unit test environment.
'''
# check that we don't store persistent objects in cache
from Products.ERP5Type.CachePlugins.BaseCache import CacheEntry
......@@ -1662,5 +1662,15 @@ def fortify():
activity_kw, *args, **kw)
Message.__init__ = __init__
# Inject a prefix to keys used by memcached, so that when we are running
# multiple runUnitTest process using the same memcached instance they don't
# have conflicting keys.
import Products.ERP5Type.Tool.MemcachedTool
original_encodeKey = Products.ERP5Type.Tool.MemcachedTool.encodeKey
prefix = str2bytes(''.join(random.sample(string.ascii_letters + string.digits, 6)))
def encodeKey(key):
return prefix + original_encodeKey(key)
Products.ERP5Type.Tool.MemcachedTool.encodeKey = encodeKey
fortify()
......@@ -11,6 +11,8 @@ class SetupSiteError(Exception):
def patch():
import six
import contextlib
import sys
import traceback
from unittest import TestCase, TextTestResult, TextTestRunner
......@@ -21,6 +23,20 @@ def patch():
TestCase.assertRaisesRegex = getattr(TestCase, 'assertRaisesRegexp')
TestCase.assertRegex = getattr(TestCase, 'assertRegexpMatches')
TestCase.assertCountEqual = TestCase.assertItemsEqual
@contextlib.contextmanager
def subTest(self, msg='', **params):
yield
TestCase.subTest = subTest
if sys.version_info < (3, 11):
def enterContext(self, cm):
cls = type(cm)
enter = cls.__enter__
exit = cls.__exit__
result = enter(cm)
self.addCleanup(exit, cm, None, None, None)
return result
TestCase.enterContext = enterContext
TextTestResult_addError = six.get_unbound_function(TextTestResult.addError)
def addError(self, test, err):
......
......@@ -150,6 +150,7 @@ Options:
timer service.
This option only makes sense with --activity_node=
or when not specifying a test to run.
--insecure_password=PWD Use `PWD` instead of generating random passwords for users.
--zserver=ADDRESS[,...] Make ZServer listen on given IPv4 address.
Addresses can be given in the following syntaxs:
- HOST:PORT
......@@ -793,7 +794,8 @@ def main(argument_list=None):
"sys_path=",
"instance_home=",
"log_directory=",
"with_wendelin_core"
"with_wendelin_core",
"insecure_password=",
])
except getopt.GetoptError as msg:
usage(sys.stderr, msg)
......@@ -914,6 +916,8 @@ def main(argument_list=None):
_log_directory = os.path.abspath(arg)
elif opt == "--with_wendelin_core":
os.environ["with_wendelin_core"] = "1"
elif opt == "--insecure_password":
os.environ["insecure_erp5_test_password"] = arg
setupWarnings()
......
......@@ -3255,17 +3255,9 @@ class Test(ERP5TypeTestCase):
self.assertNotEqual(os, None)
'''
def testRunLiveTest(self):
"""
Create a new ZODB Test Component and try to run it as a live tests and
check the expected output
def _runLiveTest(self, test_name):
"""Runs a live test from portal_components
"""
# First try with a test which run successfully
source_code = self._getValidSourceCode()
component = self._newComponent('testRunLiveTest', source_code)
component.validate()
self.tic()
from Products.ERP5Type.tests.runUnitTest import ERP5TypeTestLoader
ERP5TypeTestLoader_loadTestsFromNames = ERP5TypeTestLoader.loadTestsFromNames
def loadTestsFromNames(self, *args, **kwargs):
......@@ -3287,6 +3279,35 @@ class Test(ERP5TypeTestCase):
return ret
# ERP5TypeLiveTestCase.runLiveTest patches ERP5TypeTestCase bases, thus it
# needs to be restored after calling runLiveTest
base_tuple = ERP5TypeTestCase.__bases__
ERP5TypeTestLoader.loadTestsFromNames = loadTestsFromNames
from six.moves import cStringIO as StringIO
stderr = StringIO()
_real_stderr = sys.stderr
sys.stderr = stderr
try:
self._component_tool.runLiveTest(test_name)
finally:
ERP5TypeTestCase.__bases__ = base_tuple
ERP5TypeTestLoader.loadTestsFromNames = ERP5TypeTestLoader_loadTestsFromNames
sys.stderr = _real_stderr
test_output = self._component_tool.readTestOutput()
self.assertEqual(stderr.getvalue(), test_output)
return test_output
def testRunLiveTest(self):
"""
Create a new ZODB Test Component and try to run it as a live tests and
check the expected output
"""
# First try with a test which run successfully
source_code = self._getValidSourceCode()
component = self._newComponent('testRunLiveTest', source_code)
component.validate()
self.tic()
self.assertEqual(component.getValidationState(), 'validated')
self.assertModuleImportable('testRunLiveTest')
self._component_tool.reset(force=True,
......@@ -3295,19 +3316,7 @@ class Test(ERP5TypeTestCase):
# set a request key, that should not be set from the test request
self.portal.REQUEST.set('foo', 'something from main request')
def runLiveTest(test_name):
# ERP5TypeLiveTestCase.runLiveTest patches ERP5TypeTestCase bases, thus it
# needs to be restored after calling runLiveTest
base_tuple = ERP5TypeTestCase.__bases__
ERP5TypeTestLoader.loadTestsFromNames = loadTestsFromNames
try:
self._component_tool.runLiveTest(test_name)
finally:
ERP5TypeTestCase.__bases__ = base_tuple
ERP5TypeTestLoader.loadTestsFromNames = ERP5TypeTestLoader_loadTestsFromNames
return self._component_tool.readTestOutput()
output = runLiveTest('testRunLiveTest')
output = self._runLiveTest('testRunLiveTest')
expected_msg_re = re.compile('Ran 1 test.*OK', re.DOTALL)
self.assertRegex(output, expected_msg_re)
......@@ -3325,7 +3334,7 @@ class Test(ERP5TypeTestCase):
self._component_tool.reset(force=True,
reset_portal_type_at_transaction_boundary=True)
output = runLiveTest('testRunLiveTest')
output = self._runLiveTest('testRunLiveTest')
expected_msg_re = re.compile(r'Ran 2 tests.*FAILED \(failures=1\)', re.DOTALL)
self.assertRegex(output, expected_msg_re)
......@@ -3350,7 +3359,7 @@ class Test(ERP5TypeTestCase):
self._component_tool.reset(force=True,
reset_portal_type_at_transaction_boundary=True)
output = runLiveTest('testRunLiveTest')
output = self._runLiveTest('testRunLiveTest')
expected_msg_re = re.compile('Ran 3 test.*OK', re.DOTALL)
self.assertRegex(output, expected_msg_re)
......@@ -3364,44 +3373,11 @@ break_at_import()
component.validate()
self.tic()
from Products.ERP5Type.tests.runUnitTest import ERP5TypeTestLoader
ERP5TypeTestLoader_loadTestsFromNames = ERP5TypeTestLoader.loadTestsFromNames
def loadTestsFromNames(self, *args, **kwargs):
"""
Monkey patched to simulate a reset right after importing the ZODB Test
Component whose Unit Tests are going to be executed
"""
ret = ERP5TypeTestLoader_loadTestsFromNames(self, *args, **kwargs)
from Products.ERP5.ERP5Site import getSite
getSite().portal_components.reset(force=True)
# Simulate a new REQUEST while the old one has been GC'ed
import erp5.component
erp5.component.ref_manager.clear()
import gc
gc.collect()
return ret
self.assertEqual(component.getValidationState(), 'validated')
self._component_tool.reset(force=True,
reset_portal_type_at_transaction_boundary=True)
def runLiveTest(test_name):
# ERP5TypeLiveTestCase.runLiveTest patches ERP5TypeTestCase bases, thus it
# needs to be restored after calling runLiveTest
base_tuple = ERP5TypeTestCase.__bases__
ERP5TypeTestLoader.loadTestsFromNames = loadTestsFromNames
try:
self._component_tool.runLiveTest(test_name)
finally:
ERP5TypeTestCase.__bases__ = base_tuple
ERP5TypeTestLoader.loadTestsFromNames = ERP5TypeTestLoader_loadTestsFromNames
return self._component_tool.readTestOutput()
output = runLiveTest('testRunLiveTestImportError')
output = self._runLiveTest('testRunLiveTestImportError')
relative_url = 'portal_components/test.erp5.testRunLiveTestImportError'
if six.PY2:
module_file = '<' + relative_url + '>'
......@@ -3417,7 +3393,7 @@ break_at_import()
%(error_message)s
''' % dict(module_file=module_file, error_message=error_message), output)
output = runLiveTest('testDoesNotExist_import_error_because_module_does_not_exist')
output = self._runLiveTest('testDoesNotExist_import_error_because_module_does_not_exist')
if six.PY2:
expected_output = "ImportError: No module named testDoesNotExist_import_error_because_module_does_not_exist"
else:
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment