273 lines
9.3 KiB
Python
273 lines
9.3 KiB
Python
# -*- coding: utf-8 -*-
|
|
# Copyright 2017 Camptocamp SA
|
|
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html)
|
|
|
|
import mock
|
|
from odoo.addons.component.core import AbstractComponent, Component
|
|
from .common import ComponentRegistryCase
|
|
|
|
|
|
class TestBuildComponent(ComponentRegistryCase):
|
|
""" Test build of components
|
|
|
|
All the tests in this suite are based on the same principle with
|
|
variations:
|
|
|
|
* Create new Components (classes inheriting from
|
|
:class:`component.core.Component` or
|
|
:class:`component.core.AbstractComponent`
|
|
* Call :meth:`component.core.Component._build_component` on them
|
|
in order to build the 'final class' composed from all the ``_inherit``
|
|
and push it in the components registry (``self.comp_registry`` here)
|
|
* Assert that classes are built, registered, have correct ``__bases__``...
|
|
|
|
"""
|
|
|
|
def test_no_name(self):
|
|
""" Ensure that a component has a _name """
|
|
class Component1(Component):
|
|
pass
|
|
|
|
msg = '.*must have a _name.*'
|
|
with self.assertRaisesRegex(TypeError, msg):
|
|
Component1._build_component(self.comp_registry)
|
|
|
|
def test_register(self):
|
|
""" Able to register components in components registry """
|
|
class Component1(Component):
|
|
_name = 'component1'
|
|
|
|
class Component2(Component):
|
|
_name = 'component2'
|
|
|
|
# build the 'final classes' for the components and check that we find
|
|
# them in the components registry
|
|
Component1._build_component(self.comp_registry)
|
|
Component2._build_component(self.comp_registry)
|
|
self.assertEqual(
|
|
['base', 'component1', 'component2'],
|
|
list(self.comp_registry)
|
|
)
|
|
|
|
def test_inherit_bases(self):
|
|
""" Check __bases__ of Component with _inherit """
|
|
class Component1(Component):
|
|
_name = 'component1'
|
|
|
|
class Component2(Component):
|
|
_inherit = 'component1'
|
|
|
|
class Component3(Component):
|
|
_inherit = 'component1'
|
|
|
|
Component1._build_component(self.comp_registry)
|
|
Component2._build_component(self.comp_registry)
|
|
Component3._build_component(self.comp_registry)
|
|
self.assertEqual(
|
|
(Component3,
|
|
Component2,
|
|
Component1,
|
|
self.comp_registry['base']),
|
|
self.comp_registry['component1'].__bases__
|
|
)
|
|
|
|
def test_prototype_inherit_bases(self):
|
|
""" Check __bases__ of Component with _inherit and different _name """
|
|
class Component1(Component):
|
|
_name = 'component1'
|
|
|
|
class Component2(Component):
|
|
_name = 'component2'
|
|
_inherit = 'component1'
|
|
|
|
class Component3(Component):
|
|
_name = 'component3'
|
|
_inherit = 'component1'
|
|
|
|
class Component4(Component):
|
|
_name = 'component4'
|
|
_inherit = ['component2', 'component3']
|
|
|
|
Component1._build_component(self.comp_registry)
|
|
Component2._build_component(self.comp_registry)
|
|
Component3._build_component(self.comp_registry)
|
|
Component4._build_component(self.comp_registry)
|
|
self.assertEqual(
|
|
(Component1,
|
|
self.comp_registry['base']),
|
|
self.comp_registry['component1'].__bases__
|
|
)
|
|
self.assertEqual(
|
|
(Component2,
|
|
self.comp_registry['component1'],
|
|
self.comp_registry['base']),
|
|
self.comp_registry['component2'].__bases__
|
|
)
|
|
self.assertEqual(
|
|
(Component3,
|
|
self.comp_registry['component1'],
|
|
self.comp_registry['base']),
|
|
self.comp_registry['component3'].__bases__
|
|
)
|
|
self.assertEqual(
|
|
(Component4,
|
|
self.comp_registry['component2'],
|
|
self.comp_registry['component3'],
|
|
self.comp_registry['base']),
|
|
self.comp_registry['component4'].__bases__
|
|
)
|
|
|
|
def test_custom_build(self):
|
|
""" Check that we can hook at the end of a Component build """
|
|
class Component1(Component):
|
|
_name = 'component1'
|
|
|
|
@classmethod
|
|
def _complete_component_build(cls):
|
|
# This method should be called after the Component
|
|
# is built, and before it is pushed in the registry
|
|
cls._build_done = True
|
|
|
|
Component1._build_component(self.comp_registry)
|
|
# we inspect that our custom build has been executed
|
|
self.assertTrue(
|
|
self.comp_registry['component1']._build_done
|
|
)
|
|
|
|
def test_inherit_attrs(self):
|
|
""" Check attributes inheritance of Components with _inherit """
|
|
class Component1(Component):
|
|
_name = 'component1'
|
|
|
|
msg = 'ping'
|
|
|
|
def say(self):
|
|
return 'foo'
|
|
|
|
class Component2(Component):
|
|
_name = 'component2'
|
|
_inherit = 'component1'
|
|
|
|
msg = 'pong'
|
|
|
|
def say(self):
|
|
return super(Component2, self).say() + ' bar'
|
|
|
|
Component1._build_component(self.comp_registry)
|
|
Component2._build_component(self.comp_registry)
|
|
# we initialize the components, normally we should pass
|
|
# an instance of WorkContext, but we don't need a real one
|
|
# for this test
|
|
component1 = self.comp_registry['component1'](mock.Mock())
|
|
component2 = self.comp_registry['component2'](mock.Mock())
|
|
self.assertEqual('ping', component1.msg)
|
|
self.assertEqual('pong', component2.msg)
|
|
self.assertEqual('foo', component1.say())
|
|
self.assertEqual('foo bar', component2.say())
|
|
|
|
def test_duplicate_component(self):
|
|
""" Check that we can't have 2 components with the same name """
|
|
class Component1(Component):
|
|
_name = 'component1'
|
|
|
|
class Component2(Component):
|
|
_name = 'component1'
|
|
|
|
Component1._build_component(self.comp_registry)
|
|
msg = 'Component.*already exists.*'
|
|
with self.assertRaisesRegex(TypeError, msg):
|
|
Component2._build_component(self.comp_registry)
|
|
|
|
def test_no_parent(self):
|
|
""" Ensure we can't _inherit a non-existent component """
|
|
class Component1(Component):
|
|
_name = 'component1'
|
|
_inherit = 'component1'
|
|
|
|
msg = 'Component.*does not exist in registry.*'
|
|
with self.assertRaisesRegex(TypeError, msg):
|
|
Component1._build_component(self.comp_registry)
|
|
|
|
def test_no_parent2(self):
|
|
""" Ensure we can't _inherit by prototype a non-existent component """
|
|
class Component1(Component):
|
|
_name = 'component1'
|
|
|
|
class Component2(Component):
|
|
_name = 'component2'
|
|
_inherit = ['component1', 'component3']
|
|
|
|
Component1._build_component(self.comp_registry)
|
|
msg = 'Component.*inherits from non-existing component.*'
|
|
with self.assertRaisesRegex(TypeError, msg):
|
|
Component2._build_component(self.comp_registry)
|
|
|
|
def test_add_inheritance(self):
|
|
""" Ensure we can add a new inheritance """
|
|
class Component1(Component):
|
|
_name = 'component1'
|
|
|
|
class Component2(Component):
|
|
_name = 'component2'
|
|
|
|
class Component2bis(Component):
|
|
_name = 'component2'
|
|
_inherit = ['component2', 'component1']
|
|
|
|
Component1._build_component(self.comp_registry)
|
|
Component2._build_component(self.comp_registry)
|
|
Component2bis._build_component(self.comp_registry)
|
|
|
|
self.assertEqual(
|
|
(Component2bis,
|
|
Component2,
|
|
self.comp_registry['component1'],
|
|
self.comp_registry['base']),
|
|
self.comp_registry['component2'].__bases__
|
|
)
|
|
|
|
def test_check_parent_component_over_abstract(self):
|
|
""" Component can inherit from AbstractComponent """
|
|
class Component1(AbstractComponent):
|
|
_name = 'component1'
|
|
|
|
class Component2(Component):
|
|
_name = 'component2'
|
|
_inherit = 'component1'
|
|
|
|
Component1._build_component(self.comp_registry)
|
|
Component2._build_component(self.comp_registry)
|
|
self.assertTrue(
|
|
self.comp_registry['component1']._abstract
|
|
)
|
|
self.assertFalse(
|
|
self.comp_registry['component2']._abstract
|
|
)
|
|
|
|
def test_check_parent_abstract_over_component(self):
|
|
""" Prevent AbstractComponent to inherit from Component """
|
|
class Component1(Component):
|
|
_name = 'component1'
|
|
|
|
class Component2(AbstractComponent):
|
|
_name = 'component2'
|
|
_inherit = 'component1'
|
|
|
|
Component1._build_component(self.comp_registry)
|
|
msg = '.*cannot inherit from the non-abstract.*'
|
|
with self.assertRaisesRegex(TypeError, msg):
|
|
Component2._build_component(self.comp_registry)
|
|
|
|
def test_check_transform_abstract_to_component(self):
|
|
""" Prevent AbstractComponent to be transformed to Component """
|
|
class Component1(AbstractComponent):
|
|
_name = 'component1'
|
|
|
|
class Component1bis(Component):
|
|
_inherit = 'component1'
|
|
|
|
Component1._build_component(self.comp_registry)
|
|
msg = '.*transforms the abstract component.*into a non-abstract.*'
|
|
with self.assertRaisesRegex(TypeError, msg):
|
|
Component1bis._build_component(self.comp_registry)
|