Commit dd2505f5 authored by Arnaud Fontaine's avatar Arnaud Fontaine

WIP: Fix testDynamicClassGeneration failures.

parent cf937f3e
...@@ -31,6 +31,7 @@ from Products.ERP5Type.mixin.component import ComponentMixin ...@@ -31,6 +31,7 @@ from Products.ERP5Type.mixin.component import ComponentMixin
from Products.ERP5Type.mixin.text_content_history import TextContentHistoryMixin from Products.ERP5Type.mixin.text_content_history import TextContentHistoryMixin
from AccessControl import ClassSecurityInfo from AccessControl import ClassSecurityInfo
from Products.ERP5Type import Permissions from Products.ERP5Type import Permissions
from Products.ERP5Type.ConsistencyMessage import ConsistencyMessage
import zope.interface import zope.interface
from Products.ERP5Type.interfaces.component import IComponent from Products.ERP5Type.interfaces.component import IComponent
...@@ -62,3 +63,24 @@ class DocumentComponent(ComponentMixin, TextContentHistoryMixin): ...@@ -62,3 +63,24 @@ class DocumentComponent(ComponentMixin, TextContentHistoryMixin):
@staticmethod @staticmethod
def getIdPrefix(): def getIdPrefix():
return 'document' return 'document'
_message_reference_class_not_defined = "Class ${reference} must be defined"
def checkConsistency(self, *args, **kw):
"""
Per convention, a Document Component must have at least a class whose name
is the same as the Reference so that it can be assigned to Portal Types.
XXX: Very basic check for now.
"""
error_list = super(DocumentComponent, self).checkConsistency(*args ,**kw)
reference = self.getReference()
text_content = self.getTextContent()
if (reference and text_content and # Already checked in the parent class
'class %s(' % reference not in text_content):
error_list.append(ConsistencyMessage(
self,
self.getRelativeUrl(),
message=self._message_reference_class_not_defined,
mapping={'reference': reference}))
return error_list
...@@ -28,6 +28,7 @@ ...@@ -28,6 +28,7 @@
############################################################################## ##############################################################################
from Products.ERP5Type.Core.DocumentComponent import DocumentComponent from Products.ERP5Type.Core.DocumentComponent import DocumentComponent
from Products.ERP5Type.ConsistencyMessage import ConsistencyMessage
class InterfaceComponent(DocumentComponent): class InterfaceComponent(DocumentComponent):
""" """
...@@ -43,3 +44,20 @@ class InterfaceComponent(DocumentComponent): ...@@ -43,3 +44,20 @@ class InterfaceComponent(DocumentComponent):
@staticmethod @staticmethod
def getIdPrefix(): def getIdPrefix():
return 'interface' return 'interface'
_message_reference_wrong_naming = "Interface Reference must start with 'I'"
def checkConsistency(self, *args, **kw):
"""
Per convention, an Interface class must start with 'I'
"""
error_list = super(InterfaceComponent, self).checkConsistency(*args, **kw)
reference = self.getReference()
if (reference and # Already checked in the parent class
not reference.startswith('I')):
error_list.append(ConsistencyMessage(
self,
self.getRelativeUrl(),
message=self._message_reference_wrong_naming,
mapping={}))
return error_list
...@@ -43,3 +43,20 @@ class MixinComponent(DocumentComponent): ...@@ -43,3 +43,20 @@ class MixinComponent(DocumentComponent):
@staticmethod @staticmethod
def getIdPrefix(): def getIdPrefix():
return 'mixin' return 'mixin'
_message_reference_wrong_naming = "Mixin Reference must end with 'Mixin'"
def checkConsistency(self, *args, **kw):
"""
Per convention, a Mixin class must end with 'Mixin'
"""
error_list = super(MixinComponent, self).checkConsistency(*args, **kw)
reference = self.getReference()
if (reference and # Already checked in the parent class
not reference.endswith('Mixin')):
error_list.append(ConsistencyMessage(
self,
self.getRelativeUrl(),
message=self._message_reference_wrong_naming,
mapping={}))
return error_list
...@@ -1372,13 +1372,22 @@ class _TestZodbComponent(SecurityTestCase): ...@@ -1372,13 +1372,22 @@ class _TestZodbComponent(SecurityTestCase):
self._component_tool.reset(force=True, self._component_tool.reset(force=True,
reset_portal_type_at_transaction_boundary=True) reset_portal_type_at_transaction_boundary=True)
def _newComponent(self, reference, text_content, version='erp5', id_=None): def _generateReference(self, base_name):
return base_name
def _getValidSourceCode(self, class_name):
raise NotImplementedError
def _newComponent(self, reference, text_content=None, version='erp5', id_=None):
""" """
Create new Component Create new Component
""" """
if id_ is None: if id_ is None:
id_ = '%s.%s.%s' % (self._document_class.getIdPrefix(), version, reference) id_ = '%s.%s.%s' % (self._document_class.getIdPrefix(), version, reference)
if text_content is None:
text_content = self._getValidSourceCode(reference)
return self._component_tool.newContent( return self._component_tool.newContent(
id=id_, id=id_,
version=version, version=version,
...@@ -1465,9 +1474,8 @@ class _TestZodbComponent(SecurityTestCase): ...@@ -1465,9 +1474,8 @@ class _TestZodbComponent(SecurityTestCase):
'', ['Manager', 'Member', 'Assignee', '', ['Manager', 'Member', 'Assignee',
'Assignor', 'Author', 'Auditor', 'Associate'], []) 'Assignor', 'Author', 'Auditor', 'Associate'], [])
test_component = self._newComponent( reference = self._generateReference('TestValidateInvalidateComponent')
'TestValidateInvalidateComponent', test_component = self._newComponent(reference)
'def foobar(*args, **kwargs):\n return "ValidateInvalidate"')
self.failIfUserCanPassWorkflowTransition('ERP5TypeTestCase_NonDeveloper', self.failIfUserCanPassWorkflowTransition('ERP5TypeTestCase_NonDeveloper',
'validate_action', 'validate_action',
...@@ -1487,11 +1495,11 @@ class _TestZodbComponent(SecurityTestCase): ...@@ -1487,11 +1495,11 @@ class _TestZodbComponent(SecurityTestCase):
finally: finally:
setSecurityManager(sm) setSecurityManager(sm)
self.failIfModuleImportable('TestValidateInvalidateComponent') self.failIfModuleImportable(reference)
self.portal.portal_workflow.doActionFor(test_component, 'validate_action') self.portal.portal_workflow.doActionFor(test_component, 'validate_action')
self.tic() self.tic()
self.assertModuleImportable('TestValidateInvalidateComponent') self.assertModuleImportable(reference)
self.failIfUserCanPassWorkflowTransition('ERP5TypeTestCase_NonDeveloper', self.failIfUserCanPassWorkflowTransition('ERP5TypeTestCase_NonDeveloper',
'invalidate_action', 'invalidate_action',
...@@ -1511,11 +1519,11 @@ class _TestZodbComponent(SecurityTestCase): ...@@ -1511,11 +1519,11 @@ class _TestZodbComponent(SecurityTestCase):
self.portal.portal_workflow.doActionFor(test_component, 'validate_action') self.portal.portal_workflow.doActionFor(test_component, 'validate_action')
self.tic() self.tic()
self.assertModuleImportable('TestValidateInvalidateComponent') self.assertModuleImportable(reference)
self.portal.portal_workflow.doActionFor(test_component, 'invalidate_action') self.portal.portal_workflow.doActionFor(test_component, 'invalidate_action')
self.tic() self.tic()
self.failIfModuleImportable('TestValidateInvalidateComponent') self.failIfModuleImportable(reference)
sm = getSecurityManager() sm = getSecurityManager()
try: try:
...@@ -1528,9 +1536,9 @@ class _TestZodbComponent(SecurityTestCase): ...@@ -1528,9 +1536,9 @@ class _TestZodbComponent(SecurityTestCase):
self.portal.portal_workflow.doActionFor(test_component, 'delete_action') self.portal.portal_workflow.doActionFor(test_component, 'delete_action')
self.tic() self.tic()
self.failIfModuleImportable('TestValidateInvalidateComponent') self.failIfModuleImportable(reference)
self.assertEqual([o for o in self.portal.portal_components.contentValues() self.assertEqual([o for o in self.portal.portal_components.contentValues()
if o.getReference() == 'TestValidateInvalidateComponent'], if o.getReference() == reference],
[]) [])
def testInvalidId(self): def testInvalidId(self):
...@@ -1538,27 +1546,23 @@ class _TestZodbComponent(SecurityTestCase): ...@@ -1538,27 +1546,23 @@ class _TestZodbComponent(SecurityTestCase):
Check whether checkConsistency has been properly implemented for checking Check whether checkConsistency has been properly implemented for checking
Component ID which should follow the format 'getIdPrefix().VERSION.REFERENCE' Component ID which should follow the format 'getIdPrefix().VERSION.REFERENCE'
""" """
id_prefix = self._document_class.getIdPrefix() valid_reference = self._generateReference("TestWithInvalidId")
version = "erp5" component = self._newComponent(valid_reference)
reference = "TestWithInvalidId"
valid_id = "%s.%s.%s" % (id_prefix, version, reference)
component = self._newComponent(reference,
'def foobar():\n return 42',
version,
valid_id)
self.tic() self.tic()
self.assertEqual(component.checkConsistency(), []) self.assertEqual(component.checkConsistency(), [])
for invalid_id in ("INVALID_PREFIX.%s.%s" % (version, reference), valid_id_prefix = self._document_class.getIdPrefix()
"%s.INVALID_VERSION.%s" % (id_prefix, reference), valid_id = component.getId()
"%s.%s.INVALID_REFERENCE" % (id_prefix, version)): valid_version = component.getVersion()
for invalid_id in ("INVALID_PREFIX.%s.%s" % (valid_version, valid_reference),
"%s.INVALID_VERSION.%s" % (valid_id_prefix, valid_reference),
"%s.%s.INVALID_REFERENCE" % (valid_id_prefix, valid_version)):
component.setId(invalid_id) component.setId(invalid_id)
self.tic() self.tic()
self.assertEqual( self.assertEqual(
[m.getMessage().translate() for m in component.checkConsistency()], [m.getMessage().translate() for m in component.checkConsistency()],
[self.portal.Base_translateString(ComponentMixin._message_invalid_id, [self.portal.Base_translateString(ComponentMixin._message_invalid_id,
mapping={'id_prefix': id_prefix})]) mapping={'id_prefix': valid_id_prefix})])
component.setId(valid_id) component.setId(valid_id)
self.tic() self.tic()
...@@ -1573,12 +1577,10 @@ class _TestZodbComponent(SecurityTestCase): ...@@ -1573,12 +1577,10 @@ class _TestZodbComponent(SecurityTestCase):
validated but not when an error was encountered (implemented in validated but not when an error was encountered (implemented in
dynamic_class_generation_interaction_workflow) dynamic_class_generation_interaction_workflow)
""" """
valid_reference = 'TestReferenceWithReservedKeywords' valid_reference = self._generateReference('TestReferenceWithReservedKeywords')
ComponentTool.reset = assertResetCalled ComponentTool.reset = assertResetCalled
try: try:
component = self._newComponent(valid_reference, component = self._newComponent(valid_reference)
'def foobar():\n return 42')
component.validate() component.validate()
self.tic() self.tic()
...@@ -1609,25 +1611,23 @@ class _TestZodbComponent(SecurityTestCase): ...@@ -1609,25 +1611,23 @@ class _TestZodbComponent(SecurityTestCase):
'find_module': ComponentMixin._message_invalid_reference, 'find_module': ComponentMixin._message_invalid_reference,
'load_module': ComponentMixin._message_invalid_reference} 'load_module': ComponentMixin._message_invalid_reference}
invalid_id_error_message = self.portal.Base_translateString(
ComponentMixin._message_invalid_id,
mapping={'id_prefix': self._document_class.getIdPrefix()})
for invalid_reference, error_message in invalid_reference_dict.iteritems(): for invalid_reference, error_message in invalid_reference_dict.iteritems():
# Reset should not be performed # Reset should not be performed
ComponentTool.reset = assertResetNotCalled ComponentTool.reset = assertResetNotCalled
try: try:
component.setReference(invalid_reference) component.setReference(invalid_reference)
# 'Class XXX must be defined' error from Document Components checked
# in its own test method
component.setTextContent(self._getValidSourceCode(invalid_reference))
self.tic() self.tic()
finally: finally:
ComponentTool.reset = ComponentTool._original_reset ComponentTool.reset = ComponentTool._original_reset
# Should be in modified state as an error has been encountered # Should be in modified state as an error has been encountered
self.assertEqual(component.getValidationState(), 'modified') self.assertEqual(component.getValidationState(), 'modified')
self.assertEqual([m.getMessage().translate() self.assertTrue(error_message in [m.getMessage().translate()
for m in component.checkConsistency()], for m in component.checkConsistency()])
[invalid_id_error_message,
error_message])
self.assertEqual(component.getTextContentErrorMessageList(), []) self.assertEqual(component.getTextContentErrorMessageList(), [])
self.assertEqual(component.getTextContentWarningMessageList(), []) self.assertEqual(component.getTextContentWarningMessageList(), [])
self.assertEqual(component.getReference(), invalid_reference) self.assertEqual(component.getReference(), invalid_reference)
...@@ -1638,9 +1638,12 @@ class _TestZodbComponent(SecurityTestCase): ...@@ -1638,9 +1638,12 @@ class _TestZodbComponent(SecurityTestCase):
# Set a valid reference and check that the Component is in validated state # Set a valid reference and check that the Component is in validated state
# and no error was raised # and no error was raised
self.tic()
ComponentTool.reset = assertResetCalled ComponentTool.reset = assertResetCalled
try: try:
component.setReference(valid_reference) component.setReference(valid_reference)
# 'Class XXX must be defined' error from Document Components
component.setTextContent(self._getValidSourceCode(valid_reference))
self.tic() self.tic()
self.assertEqual(ComponentTool._reset_performed, True) self.assertEqual(ComponentTool._reset_performed, True)
...@@ -1665,14 +1668,11 @@ class _TestZodbComponent(SecurityTestCase): ...@@ -1665,14 +1668,11 @@ class _TestZodbComponent(SecurityTestCase):
validated but not when an error was encountered (implemented in validated but not when an error was encountered (implemented in
dynamic_class_generation_interaction_workflow) dynamic_class_generation_interaction_workflow)
""" """
reference = 'TestVersionWithReservedKeywords' reference = self._generateReference('TestVersionWithReservedKeywords')
valid_version = 'erp5' valid_version = 'erp5'
ComponentTool.reset = assertResetCalled ComponentTool.reset = assertResetCalled
try: try:
component = self._newComponent(reference, component = self._newComponent(reference, version=valid_version)
'def foobar():\n return 42',
valid_version)
component.validate() component.validate()
self.tic() self.tic()
...@@ -1755,20 +1755,24 @@ class _TestZodbComponent(SecurityTestCase): ...@@ -1755,20 +1755,24 @@ class _TestZodbComponent(SecurityTestCase):
""" """
# Error/Warning properties must be set everytime the source code is # Error/Warning properties must be set everytime the source code is
# modified, even in Draft state # modified, even in Draft state
component = self._newComponent('TestComponentWithSyntaxError', 'print "ok"') reference = self._generateReference('TestComponentWithSyntaxError')
component = self._newComponent(reference)
valid_code = component.getTextContent()
self.tic() self.tic()
self.assertEqual(component.checkConsistency(), []) self.assertEqual(component.checkConsistency(), [])
self.assertEqual(component.getTextContentErrorMessageList(), []) self.assertEqual(component.getTextContentErrorMessageList(), [])
self.assertEqual(component.getTextContentWarningMessageList(), []) self.assertEqual(component.getTextContentWarningMessageList(), [])
component.setTextContent('import sys') component.setTextContent("""import sys
""" + valid_code)
self.tic() self.tic()
self.assertEqual(component.checkConsistency(), []) self.assertEqual(component.checkConsistency(), [])
self.assertEqual(component.getTextContentErrorMessageList(), []) self.assertEqual(component.getTextContentErrorMessageList(), [])
self.assertEqual(component.getTextContentWarningMessageList(), self.assertEqual(component.getTextContentWarningMessageList(),
["W: 1, 0: Unused import sys (unused-import)"]) ["W: 1, 0: Unused import sys (unused-import)"])
component.setTextContent('import unexistent_module') component.setTextContent("""import unexistent_module
""" + valid_code)
self.tic() self.tic()
self.assertEqual( self.assertEqual(
[m.getMessage().translate() for m in component.checkConsistency()], [m.getMessage().translate() for m in component.checkConsistency()],
...@@ -1778,7 +1782,6 @@ class _TestZodbComponent(SecurityTestCase): ...@@ -1778,7 +1782,6 @@ class _TestZodbComponent(SecurityTestCase):
self.assertEqual(component.getTextContentWarningMessageList(), self.assertEqual(component.getTextContentWarningMessageList(),
["W: 1, 0: Unused import unexistent_module (unused-import)"]) ["W: 1, 0: Unused import unexistent_module (unused-import)"])
valid_code = 'def foobar():\n return 42'
ComponentTool.reset = assertResetCalled ComponentTool.reset = assertResetCalled
try: try:
component.setTextContent(valid_code) component.setTextContent(valid_code)
...@@ -1796,7 +1799,7 @@ class _TestZodbComponent(SecurityTestCase): ...@@ -1796,7 +1799,7 @@ class _TestZodbComponent(SecurityTestCase):
self.assertEqual(component.getTextContentWarningMessageList(), []) self.assertEqual(component.getTextContentWarningMessageList(), [])
self.assertEqual(component.getTextContent(), valid_code) self.assertEqual(component.getTextContent(), valid_code)
self.assertEqual(component.getTextContent(validated_only=True), valid_code) self.assertEqual(component.getTextContent(validated_only=True), valid_code)
self.assertModuleImportable('TestComponentWithSyntaxError') self.assertModuleImportable(reference)
# Check that checkConsistency returns the proper error message for the # Check that checkConsistency returns the proper error message for the
# following Python errors # following Python errors
...@@ -1807,15 +1810,18 @@ class _TestZodbComponent(SecurityTestCase): ...@@ -1807,15 +1810,18 @@ class _TestZodbComponent(SecurityTestCase):
[ComponentMixin._message_text_content_not_set], [ComponentMixin._message_text_content_not_set],
[], [],
[]), []),
('def foobar(*args, **kwargs)\n return 42', ("""def foobar(*args, **kwargs)
return 42
""" + valid_code,
["Error in Source Code: E: 1, 0: invalid syntax (syntax-error)"], ["Error in Source Code: E: 1, 0: invalid syntax (syntax-error)"],
["E: 1, 0: invalid syntax (syntax-error)"], ["E: 1, 0: invalid syntax (syntax-error)"],
[]), []),
# Make sure that foobar NameError is at the end to make sure that after # Make sure that foobar NameError is at the end to make sure that after
# defining foobar function, it is not available at all # defining foobar function, it is not available at all
('foobar', ("""foobar2
["Error in Source Code: E: 1, 0: Undefined variable 'foobar' (undefined-variable)"], """ + valid_code,
["E: 1, 0: Undefined variable 'foobar' (undefined-variable)"], ["Error in Source Code: E: 1, 0: Undefined variable 'foobar2' (undefined-variable)"],
["E: 1, 0: Undefined variable 'foobar2' (undefined-variable)"],
["W: 1, 0: Statement seems to have no effect (pointless-statement)"])) ["W: 1, 0: Statement seems to have no effect (pointless-statement)"]))
for (invalid_code, for (invalid_code,
...@@ -1842,7 +1848,7 @@ class _TestZodbComponent(SecurityTestCase): ...@@ -1842,7 +1848,7 @@ class _TestZodbComponent(SecurityTestCase):
self.assertEqual(component.getTextContent(validated_only=True), valid_code) self.assertEqual(component.getTextContent(validated_only=True), valid_code)
self._component_tool.reset(force=True, self._component_tool.reset(force=True,
reset_portal_type_at_transaction_boundary=True) reset_portal_type_at_transaction_boundary=True)
self.assertModuleImportable('TestComponentWithSyntaxError') self.assertModuleImportable(reference)
# Set a valid source code and check that the Component is in validated # Set a valid source code and check that the Component is in validated
# state and no error was raised # state and no error was raised
...@@ -1862,7 +1868,7 @@ class _TestZodbComponent(SecurityTestCase): ...@@ -1862,7 +1868,7 @@ class _TestZodbComponent(SecurityTestCase):
self.assertEqual(component.getTextContentWarningMessageList(), []) self.assertEqual(component.getTextContentWarningMessageList(), [])
self.assertEqual(component.getTextContent(), valid_code) self.assertEqual(component.getTextContent(), valid_code)
self.assertEqual(component.getTextContent(validated_only=True), valid_code) self.assertEqual(component.getTextContent(validated_only=True), valid_code)
self.assertModuleImportable('TestComponentWithSyntaxError') self.assertModuleImportable(reference)
def testImportVersionedComponentOnly(self): def testImportVersionedComponentOnly(self):
""" """
...@@ -1870,9 +1876,11 @@ class _TestZodbComponent(SecurityTestCase): ...@@ -1870,9 +1876,11 @@ class _TestZodbComponent(SecurityTestCase):
sometimes it may be useful to import a specific version of a Component, sometimes it may be useful to import a specific version of a Component,
available as erp5.component.XXX.VERSION_version.COMPONENT_NAME. available as erp5.component.XXX.VERSION_version.COMPONENT_NAME.
""" """
imported_reference = self._generateReference('TestImportedVersionedComponentOnly')
component = self._newComponent( component = self._newComponent(
'TestImportedVersionedComponentOnly', imported_reference,
"""def foo(*args, **kwargs): self._getValidSourceCode(imported_reference) + """
def foo(*args, **kwargs):
return "TestImportedVersionedComponentOnly" return "TestImportedVersionedComponentOnly"
""") """)
...@@ -1883,49 +1891,46 @@ class _TestZodbComponent(SecurityTestCase): ...@@ -1883,49 +1891,46 @@ class _TestZodbComponent(SecurityTestCase):
# Create a new Component which uses a specific version of the previously # Create a new Component which uses a specific version of the previously
# created Component # created Component
reference = self._generateReference('TestImportVersionedComponentOnly')
component_import = self._newComponent( component_import = self._newComponent(
'TestImportVersionedComponentOnly', reference,
"""from %s.erp5_version.TestImportedVersionedComponentOnly import foo self._getValidSourceCode(reference) + """
from %s.erp5_version.%s import foo
def bar(*args, **kwargs): def bar(*args, **kwargs):
return 'Bar' + foo(*args, **kwargs) return 'Bar' + foo(*args, **kwargs)
""" % top_module_name) """ % (top_module_name, imported_reference))
component_import.validate() component_import.validate()
self.tic() self.tic()
# Versioned package and its alias must be available # Versioned package and its alias must be available
self.assertModuleImportable('TestImportVersionedComponentOnly', self.assertModuleImportable(reference,
expected_default_version='erp5_version') expected_default_version='erp5_version')
# Versioned Component of imported Component must be importable and check # Versioned Component of imported Component must be importable and check
# later that the module has not been added to the top-level package # later that the module has not been added to the top-level package
self.assertModuleImportable('erp5_version.TestImportedVersionedComponentOnly') self.assertModuleImportable('erp5_version.%s' % imported_reference)
top_module = __import__(top_module_name, level=0, top_module = __import__(top_module_name, level=0,
fromlist=[top_module_name]) fromlist=[top_module_name])
self._importModule('erp5_version.TestImportedVersionedComponentOnly') self._importModule('erp5_version.%s' % imported_reference)
# Function defined in versioned Component must be available and callable # Function defined in versioned Component must be available and callable
self.assertHasAttribute( versioned_module = getattr(top_module.erp5_version, imported_reference)
top_module.erp5_version.TestImportedVersionedComponentOnly, 'foo') self.assertHasAttribute(versioned_module, 'foo')
self.assertEqual(versioned_module.foo(), 'TestImportedVersionedComponentOnly')
self.assertEqual(
top_module.erp5_version.TestImportedVersionedComponentOnly.foo(),
'TestImportedVersionedComponentOnly')
# The alias module on the top-level package must not have been created as # The alias module on the top-level package must not have been created as
# only the versioned Component has been used # only the versioned Component has been used
self.failIfHasAttribute(top_module, 'TestImportedVersionedComponentOnly') self.failIfHasAttribute(top_module, imported_reference)
# As well as functions defined on unversioned Component # As well as functions defined on unversioned Component
self._importModule('TestImportVersionedComponentOnly') self._importModule(reference)
self.assertHasAttribute(top_module.TestImportVersionedComponentOnly, 'bar') module = getattr(top_module, reference)
self.assertHasAttribute(module, 'bar')
self.assertEqual( self.assertEqual(module.bar(), 'BarTestImportedVersionedComponentOnly')
top_module.TestImportVersionedComponentOnly.bar(),
'BarTestImportedVersionedComponentOnly')
def testVersionPriority(self): def testVersionPriority(self):
""" """
...@@ -1933,9 +1938,13 @@ def bar(*args, **kwargs): ...@@ -1933,9 +1938,13 @@ def bar(*args, **kwargs):
version priorities on ERP5Site and checking whether the proper Component version priorities on ERP5Site and checking whether the proper Component
is loaded is loaded
""" """
reference = self._generateReference('TestVersionPriority')
source_code = self._getValidSourceCode(reference)
component_erp5_version = self._newComponent( component_erp5_version = self._newComponent(
'TestVersionPriority', reference,
"""def function_foo(*args, **kwargs): source_code + """
def function_foo(*args, **kwargs):
return "TestERP5VersionPriority" return "TestERP5VersionPriority"
""") """)
...@@ -1943,8 +1952,9 @@ def bar(*args, **kwargs): ...@@ -1943,8 +1952,9 @@ def bar(*args, **kwargs):
self.tic() self.tic()
component_foo_version = self._newComponent( component_foo_version = self._newComponent(
'TestVersionPriority', reference,
"""def function_foo(*args, **kwargs): source_code + """
def function_foo(*args, **kwargs):
return "TestFooVersionPriority" return "TestFooVersionPriority"
""", """,
'foo') 'foo')
...@@ -1952,21 +1962,21 @@ def bar(*args, **kwargs): ...@@ -1952,21 +1962,21 @@ def bar(*args, **kwargs):
component_foo_version.validate() component_foo_version.validate()
self.tic() self.tic()
self.assertModuleImportable('TestVersionPriority', self.assertModuleImportable(reference,
expected_default_version='erp5_version') expected_default_version='erp5_version')
# Component for 'foo_version' must not be importable as 'foo' has not been # Component for 'foo_version' must not be importable as 'foo' has not been
# added to ERP5Site version priorities # added to ERP5Site version priorities
self.failIfModuleImportable('foo_version.TestVersionPriority') self.failIfModuleImportable('foo_version.%s' % reference)
top_module_name = self._document_class._getDynamicModuleNamespace() top_module_name = self._document_class._getDynamicModuleNamespace()
top_module = __import__(top_module_name, level=0, top_module = __import__(top_module_name, level=0,
fromlist=[top_module_name]) fromlist=[top_module_name])
self._importModule('TestVersionPriority') self._importModule(reference)
self.assertHasAttribute(top_module.TestVersionPriority, 'function_foo') module = getattr(top_module, reference)
self.assertEqual(top_module.TestVersionPriority.function_foo(), self.assertHasAttribute(module, 'function_foo')
"TestERP5VersionPriority") self.assertEqual(module.function_foo(), "TestERP5VersionPriority")
from Products.ERP5.ERP5Site import getSite from Products.ERP5.ERP5Site import getSite
site = getSite() site = getSite()
...@@ -1981,14 +1991,14 @@ def bar(*args, **kwargs): ...@@ -1981,14 +1991,14 @@ def bar(*args, **kwargs):
self.assertEqual(ComponentTool._reset_performed, True) self.assertEqual(ComponentTool._reset_performed, True)
self.assertModuleImportable( self.assertModuleImportable(
'TestVersionPriority', reference,
expected_default_version='foo_version', expected_default_version='foo_version',
expected_additional_version_tuple=('erp5_version',)) expected_additional_version_tuple=('erp5_version',))
self._importModule('TestVersionPriority') self._importModule(reference)
self.assertHasAttribute(top_module.TestVersionPriority, 'function_foo') module = getattr(top_module, reference)
self.assertEqual(top_module.TestVersionPriority.function_foo(), self.assertHasAttribute(module, 'function_foo')
"TestFooVersionPriority") self.assertEqual(module.function_foo(), "TestFooVersionPriority")
finally: finally:
ComponentTool.reset = ComponentTool._original_reset ComponentTool.reset = ComponentTool._original_reset
...@@ -2001,9 +2011,7 @@ def bar(*args, **kwargs): ...@@ -2001,9 +2011,7 @@ def bar(*args, **kwargs):
XXX-arnau: test with different users and workflows XXX-arnau: test with different users and workflows
""" """
component = self._newComponent('TestDeveloperRoleSecurity', component = self._newComponent(self._generateReference('TestDeveloperRoleSecurity'))
'def foo():\n print "ok"')
self.tic() self.tic()
# Anonymous should not even be able to view/access Component Tool # Anonymous should not even be able to view/access Component Tool
...@@ -2055,6 +2063,11 @@ class TestZodbExtensionComponent(_TestZodbComponent): ...@@ -2055,6 +2063,11 @@ class TestZodbExtensionComponent(_TestZodbComponent):
_portal_type = 'Extension Component' _portal_type = 'Extension Component'
_document_class = ExtensionComponent _document_class = ExtensionComponent
def _getValidSourceCode(self, *_):
return '''def foobar(*args, **kwargs):
return 'Anything'
'''
def testExternalMethod(self): def testExternalMethod(self):
""" """
Check that ExternalMethod monkey-patch to use ZODB Components works well Check that ExternalMethod monkey-patch to use ZODB Components works well
...@@ -2153,6 +2166,34 @@ class TestZodbDocumentComponent(_TestZodbComponent): ...@@ -2153,6 +2166,34 @@ class TestZodbDocumentComponent(_TestZodbComponent):
_portal_type = 'Document Component' _portal_type = 'Document Component'
_document_class = DocumentComponent _document_class = DocumentComponent
def _getValidSourceCode(self, class_name):
return '''from Products.ERP5.Document.Person import Person
class %s(Person):
pass
''' % class_name
def testAtLeastOneClassNamedAfterReference(self):
component = self._newComponent(
self._generateReference('TestClassNamedAfterReference'))
self.tic()
self.assertEqual(component.checkConsistency(), [])
self.assertEqual(component.getTextContentErrorMessageList(), [])
self.assertEqual(component.getTextContentWarningMessageList(), [])
component.setTextContent("""from Products.ERP5.Document.Person import Person
class DifferentFromReference(Person):
pass
""")
self.assertEqual(
[m.getMessage().translate() for m in component.checkConsistency()],
[self.portal.Base_translateString(
self._document_class._message_reference_class_not_defined,
mapping={'reference': component.getReference()})])
self.assertEqual(component.getTextContentErrorMessageList(), [])
self.assertEqual(component.getTextContentWarningMessageList(), [])
def testAssignToPortalTypeClass(self): def testAssignToPortalTypeClass(self):
""" """
Create a new Document Component inheriting from Person Document and try to Create a new Document Component inheriting from Person Document and try to
...@@ -2172,7 +2213,7 @@ class TestZodbDocumentComponent(_TestZodbComponent): ...@@ -2172,7 +2213,7 @@ class TestZodbDocumentComponent(_TestZodbComponent):
test_component = self._newComponent( test_component = self._newComponent(
'TestPortalType', 'TestPortalType',
""" """
from Products.ERP5Type.Document.Person import Person from Products.ERP5.Document.Person import Person
class TestPortalType(Person): class TestPortalType(Person):
def test42(self): def test42(self):
...@@ -2225,52 +2266,35 @@ class TestPortalType(Person): ...@@ -2225,52 +2266,35 @@ class TestPortalType(Person):
person_type.setTypeClass('Person') person_type.setTypeClass('Person')
self.commit() self.commit()
def testDocumentWithImport(self): def testImportFromAnotherComponent(self):
""" """
Create two new Components and check whether one can import the other one Create two new Components and check whether one can import the other one
after the latter has been validated after the latter has been validated
""" """
self.failIfModuleImportable('TestDocumentWithImport') self.failIfModuleImportable('TestWithImport')
self.failIfModuleImportable('TestDocumentImported') self.failIfModuleImportable('TestImported')
# Create a new Document Component inheriting from Person Document which
# defines only one additional method (meaningful to make sure that the
# class (and not the module) has been added to the class when the
# TypeClass is changed)
test_imported_component = self._newComponent(
'TestDocumentImported',
"""
from Products.ERP5Type.Document.Person import Person
class TestDocumentImported(Person):
def test42(self):
return 42
""")
test_imported_component = self._newComponent('TestImported')
test_component = self._newComponent( test_component = self._newComponent(
'TestDocumentWithImport', 'TestWithImport',
""" """
from Products.ERP5.Document.Person import Person from %s.TestImported import TestImported
from erp5.component.document.TestDocumentImported import TestDocumentImported
class TestDocumentWithImport(TestDocumentImported):
def test42(self):
return 4242
""")
class TestWithImport(TestImported):
pass
""" % self._document_class._getDynamicModuleNamespace())
self.tic() self.tic()
self.failIfModuleImportable('TestWithImport')
self.failIfModuleImportable('TestDocumentWithImport') self.failIfModuleImportable('TestImported')
self.failIfModuleImportable('TestDocumentImported')
test_imported_component.validate() test_imported_component.validate()
test_component.validate() test_component.validate()
self.tic() self.tic()
# TestPortalWithImport must be imported first to check if # TestWithImport must be imported first to check if TestImported could be
# TestPortalImported could be imported without being present before # imported without being present before
self.assertModuleImportable('TestDocumentWithImport') self.assertModuleImportable('TestWithImport')
self.assertModuleImportable('TestDocumentImported') self.assertModuleImportable('TestImported')
from Products.ERP5Type.Core.TestComponent import TestComponent from Products.ERP5Type.Core.TestComponent import TestComponent
...@@ -2282,14 +2306,8 @@ class TestZodbTestComponent(_TestZodbComponent): ...@@ -2282,14 +2306,8 @@ class TestZodbTestComponent(_TestZodbComponent):
_portal_type = 'Test Component' _portal_type = 'Test Component'
_document_class = TestComponent _document_class = TestComponent
def testRunLiveTest(self): def _getValidSourceCode(self, *_):
""" return '''from Products.ERP5Type.tests.ERP5TypeTestCase import ERP5TypeTestCase
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 = '''
from Products.ERP5Type.tests.ERP5TypeTestCase import ERP5TypeTestCase
class Test(ERP5TypeTestCase): class Test(ERP5TypeTestCase):
def getTitle(self): def getTitle(self):
...@@ -2314,6 +2332,13 @@ class Test(ERP5TypeTestCase): ...@@ -2314,6 +2332,13 @@ class Test(ERP5TypeTestCase):
self.assertEqual(0, 0) self.assertEqual(0, 0)
''' '''
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 = self._newComponent('testRunLiveTest', source_code)
component.validate() component.validate()
self.tic() self.tic()
...@@ -2391,6 +2416,105 @@ class Test(ERP5TypeTestCase): ...@@ -2391,6 +2416,105 @@ class Test(ERP5TypeTestCase):
types_tool._delObject(name) types_tool._delObject(name)
self.commit() self.commit()
from Products.ERP5Type.Core.InterfaceComponent import InterfaceComponent
class TestZodbInterfaceComponent(TestZodbDocumentComponent):
"""
Tests specific to ZODB Interface Component.
"""
_portal_type = 'Interface Component'
_document_class = InterfaceComponent
def _generateReference(self, base_name):
return 'I' + base_name
def _getValidSourceCode(self, class_name):
return '''from zope.interface import Interface
class %s(Interface):
def test42():
"""
Return 42
"""
''' % class_name
def testNamingConsistency(self):
valid_reference = 'ITestNaming'
component = self._newComponent(valid_reference)
component.validate()
self.tic()
self.assertEqual(component.getValidationState(), 'validated')
self.assertEqual(component.checkConsistency(), [])
self.assertEqual(component.getTextContentErrorMessageList(), [])
self.assertEqual(component.getTextContentWarningMessageList(), [])
self.assertEqual(component.getReference(), valid_reference)
self.assertEqual(component.getReference(validated_only=True), valid_reference)
self.assertModuleImportable(valid_reference)
invalid_reference = 'TestNaming'
ComponentTool.reset = assertResetNotCalled
try:
component.setReference(invalid_reference)
# Checked in another test methods
component.setId("%s.%s.%s" % (self._document_class.getIdPrefix(),
component.getVersion(),
invalid_reference))
component.setTextContent(self._getValidSourceCode(invalid_reference))
self.tic()
finally:
ComponentTool.reset = ComponentTool._original_reset
self.assertEqual(component.getValidationState(), 'modified')
self.assertEqual([m.getMessage().translate()
for m in component.checkConsistency()],
["Interface Reference must start with 'I'"])
self.assertEqual(component.getTextContentErrorMessageList(), [])
self.assertEqual(component.getTextContentWarningMessageList(), [])
self.assertEqual(component.getReference(), invalid_reference)
self.assertEqual(component.getReference(validated_only=True), valid_reference)
def testAssignToPortalTypeClass(self):
"""
Create a new Document Component inheriting from Person Document and try to
assign it to Person Portal Type, then create a new Person and check
whether it has been successfully added to its Portal Type class bases and
that the newly-defined function on ZODB Component can be called as well as
methods from Person Document
"""
import erp5.portal_type
person_type = self.portal.portal_types.Person
person_type_class = erp5.portal_type.Person
component = self._newComponent('ITestPortalType')
self.tic()
self.failIfModuleImportable('ITestPortalType')
self.assertFalse('ITestPortalType' in person_type.getInterfaceTypeList())
component.validate()
self.assertModuleImportable('ITestPortalType')
self.assertTrue('ITestPortalType' in person_type.getInterfaceTypeList())
from erp5.component.interface.ITestPortalType import ITestPortalType
person_type_class.loadClass()
implemented_by_list = list(implementedBy(person_type_class))
self.assertFalse(ITestPortalType in implemented_by_list)
person_original_interface_type_list = list(person_type.getTypeInterfaceList())
try:
person_type.setTypeInterfaceList(person_original_interface_type_list +
['ITestPortalType'])
self.commit()
self.assertEqual(person_type_class.__isghost__, True)
person_type_class.loadClass()
implemented_by_list = list(implementedBy(person_type_class))
self.assertTrue(ITestPortalType in implemented_by_list)
finally:
person_type.setTypeInterfaceList(person_original_interface_type_list)
self.commit()
def test_suite(): def test_suite():
suite = unittest.TestSuite() suite = unittest.TestSuite()
suite.addTest(unittest.makeSuite(TestPortalTypeClass)) suite.addTest(unittest.makeSuite(TestPortalTypeClass))
......
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