storage_backend/component/tests/test_build_component.py

274 lines
9.2 KiB
Python
Raw Normal View History

2024-11-08 02:15:16 +07:00
# Copyright 2017 Camptocamp SA
# License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl.html)
import mock
from odoo.addons.component.core import AbstractComponent, Component
from .common import TransactionComponentRegistryCase
class TestBuildComponent(TransactionComponentRegistryCase):
"""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().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)