mirror of
https://github.com/django-components/django-components.git
synced 2025-09-26 07:29:09 +00:00
refactor: prepare registry for custom template tags and docs (#566)
Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
This commit is contained in:
parent
c202c5a901
commit
d6dec450ed
11 changed files with 491 additions and 94 deletions
|
@ -73,14 +73,11 @@ class AppendAttributesTest(BaseTestCase):
|
|||
|
||||
|
||||
class HtmlAttrsTests(BaseTestCase):
|
||||
def setUp(self):
|
||||
super().setUp()
|
||||
|
||||
self.template_str: types.django_html = """
|
||||
{% load component_tags %}
|
||||
{% component "test" attrs:@click.stop="dispatch('click_event')" attrs:x-data="{hello: 'world'}" attrs:class=class_var %}
|
||||
{% endcomponent %}
|
||||
""" # noqa: E501
|
||||
template_str: types.django_html = """
|
||||
{% load component_tags %}
|
||||
{% component "test" attrs:@click.stop="dispatch('click_event')" attrs:x-data="{hello: 'world'}" attrs:class=class_var %}
|
||||
{% endcomponent %}
|
||||
""" # noqa: E501
|
||||
|
||||
@parametrize_context_behavior(["django", "isolated"])
|
||||
def test_tag_positional_args(self):
|
||||
|
|
|
@ -615,10 +615,6 @@ class ContextVarsIsFilledTests(BaseTestCase):
|
|||
)
|
||||
registry.register("negated_conditional_slot", self.ComponentWithNegatedConditionalSlot)
|
||||
|
||||
def tearDown(self) -> None:
|
||||
super().tearDown()
|
||||
registry.clear()
|
||||
|
||||
@parametrize_context_behavior(["django", "isolated"])
|
||||
def test_is_filled_vars(self):
|
||||
template: types.django_html = """
|
||||
|
|
|
@ -67,10 +67,6 @@ class MultistyleComponent(Component):
|
|||
|
||||
@override_settings(COMPONENTS={"RENDER_DEPENDENCIES": True})
|
||||
class ComponentMediaRenderingTests(BaseTestCase):
|
||||
def setUp(self):
|
||||
# NOTE: registry is global, so need to clear before each test
|
||||
registry.clear()
|
||||
|
||||
def test_no_dependencies_when_no_components_used(self):
|
||||
registry.register(name="test", component=SimpleComponent)
|
||||
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
import unittest
|
||||
|
||||
from django.template import Library
|
||||
|
||||
from django_components import AlreadyRegistered, Component, ComponentRegistry, NotRegistered, register, registry
|
||||
|
||||
from .django_test_setup import setup_test_config
|
||||
|
@ -22,6 +24,7 @@ class MockComponentView(Component):
|
|||
|
||||
class ComponentRegistryTest(unittest.TestCase):
|
||||
def setUp(self):
|
||||
super().setUp()
|
||||
self.registry = ComponentRegistry()
|
||||
|
||||
def test_register_class_decorator(self):
|
||||
|
@ -31,6 +34,23 @@ class ComponentRegistryTest(unittest.TestCase):
|
|||
|
||||
self.assertEqual(registry.get("decorated_component"), TestComponent)
|
||||
|
||||
# Cleanup
|
||||
registry.unregister("decorated_component")
|
||||
|
||||
def test_register_class_decorator_custom_registry(self):
|
||||
my_lib = Library()
|
||||
my_reg = ComponentRegistry(library=my_lib)
|
||||
|
||||
self.assertDictEqual(my_reg.all(), {})
|
||||
self.assertDictEqual(registry.all(), {})
|
||||
|
||||
@register("decorated_component", registry=my_reg)
|
||||
class TestComponent(Component):
|
||||
pass
|
||||
|
||||
self.assertDictEqual(my_reg.all(), {"decorated_component": TestComponent})
|
||||
self.assertDictEqual(registry.all(), {})
|
||||
|
||||
def test_simple_register(self):
|
||||
self.registry.register(name="testcomponent", component=MockComponent)
|
||||
self.assertEqual(self.registry.all(), {"testcomponent": MockComponent})
|
||||
|
@ -46,6 +66,44 @@ class ComponentRegistryTest(unittest.TestCase):
|
|||
},
|
||||
)
|
||||
|
||||
def test_unregisters_only_unused_tags(self):
|
||||
self.assertDictEqual(self.registry._tags, {})
|
||||
# NOTE: We preserve the default component tags
|
||||
self.assertIn("component", self.registry.library.tags)
|
||||
|
||||
# Register two components that use the same tag
|
||||
self.registry.register(name="testcomponent", component=MockComponent)
|
||||
self.registry.register(name="testcomponent2", component=MockComponent)
|
||||
|
||||
self.assertDictEqual(
|
||||
self.registry._tags,
|
||||
{
|
||||
"#component": {"testcomponent", "testcomponent2"},
|
||||
"component": {"testcomponent", "testcomponent2"},
|
||||
},
|
||||
)
|
||||
|
||||
self.assertIn("component", self.registry.library.tags)
|
||||
|
||||
# Unregister only one of the components. The tags should remain
|
||||
self.registry.unregister(name="testcomponent")
|
||||
|
||||
self.assertDictEqual(
|
||||
self.registry._tags,
|
||||
{
|
||||
"#component": {"testcomponent2"},
|
||||
"component": {"testcomponent2"},
|
||||
},
|
||||
)
|
||||
|
||||
self.assertIn("component", self.registry.library.tags)
|
||||
|
||||
# Unregister the second components. The tags should be removed
|
||||
self.registry.unregister(name="testcomponent2")
|
||||
|
||||
self.assertDictEqual(self.registry._tags, {})
|
||||
self.assertIn("component", self.registry.library.tags)
|
||||
|
||||
def test_prevent_registering_different_components_with_the_same_name(self):
|
||||
self.registry.register(name="testcomponent", component=MockComponent)
|
||||
with self.assertRaises(AlreadyRegistered):
|
||||
|
|
|
@ -25,6 +25,7 @@ class TemplateInstrumentationTest(BaseTestCase):
|
|||
saved_render_method: Callable # Assigned during setup.
|
||||
|
||||
def tearDown(self):
|
||||
super().tearDown()
|
||||
Template._render = self.saved_render_method
|
||||
|
||||
def setUp(self):
|
||||
|
@ -92,14 +93,6 @@ class TemplateInstrumentationTest(BaseTestCase):
|
|||
|
||||
|
||||
class BlockCompatTests(BaseTestCase):
|
||||
def setUp(self):
|
||||
registry.clear()
|
||||
super().setUp()
|
||||
|
||||
def tearDown(self):
|
||||
super().tearDown()
|
||||
registry.clear()
|
||||
|
||||
@parametrize_context_behavior(["django", "isolated"])
|
||||
def test_slots_inside_extends(self):
|
||||
registry.register("slotted_component", SlottedComponent)
|
||||
|
|
|
@ -47,10 +47,6 @@ class ComponentTemplateTagTest(BaseTestCase):
|
|||
css = "style.css"
|
||||
js = "script.js"
|
||||
|
||||
def setUp(self):
|
||||
# NOTE: registry is global, so need to clear before each test
|
||||
registry.clear()
|
||||
|
||||
@parametrize_context_behavior(["django", "isolated"])
|
||||
def test_single_component(self):
|
||||
registry.register(name="test", component=self.SimpleComponent)
|
||||
|
@ -190,9 +186,6 @@ class ComponentTemplateTagTest(BaseTestCase):
|
|||
|
||||
|
||||
class MultiComponentTests(BaseTestCase):
|
||||
def setUp(self):
|
||||
registry.clear()
|
||||
|
||||
def register_components(self):
|
||||
registry.register("first_component", SlottedComponent)
|
||||
registry.register("second_component", SlottedComponentWithContext)
|
||||
|
@ -265,18 +258,19 @@ class MultiComponentTests(BaseTestCase):
|
|||
|
||||
|
||||
class ComponentIsolationTests(BaseTestCase):
|
||||
def setUp(self):
|
||||
class SlottedComponent(Component):
|
||||
template: types.django_html = """
|
||||
{% load component_tags %}
|
||||
<custom-template>
|
||||
<header>{% slot "header" %}Default header{% endslot %}</header>
|
||||
<main>{% slot "main" %}Default main{% endslot %}</main>
|
||||
<footer>{% slot "footer" %}Default footer{% endslot %}</footer>
|
||||
</custom-template>
|
||||
"""
|
||||
class SlottedComponent(Component):
|
||||
template: types.django_html = """
|
||||
{% load component_tags %}
|
||||
<custom-template>
|
||||
<header>{% slot "header" %}Default header{% endslot %}</header>
|
||||
<main>{% slot "main" %}Default main{% endslot %}</main>
|
||||
<footer>{% slot "footer" %}Default footer{% endslot %}</footer>
|
||||
</custom-template>
|
||||
"""
|
||||
|
||||
registry.register("test", SlottedComponent)
|
||||
def setUp(self):
|
||||
super().setUp()
|
||||
registry.register("test", self.SlottedComponent)
|
||||
|
||||
@parametrize_context_behavior(["django", "isolated"])
|
||||
def test_instances_of_component_do_not_share_slots(self):
|
||||
|
@ -358,10 +352,6 @@ class ComponentTemplateSyntaxErrorTests(BaseTestCase):
|
|||
super().setUp()
|
||||
registry.register("test", SlottedComponent)
|
||||
|
||||
def tearDown(self) -> None:
|
||||
super().tearDown()
|
||||
registry.clear()
|
||||
|
||||
@parametrize_context_behavior(["django", "isolated"])
|
||||
def test_variable_outside_fill_tag_compiles_w_out_error(self):
|
||||
# As of v0.28 this is valid, provided the component registered under "test"
|
||||
|
|
|
@ -32,10 +32,6 @@ class SlottedComponentWithContext(SlottedComponent):
|
|||
|
||||
|
||||
class ComponentSlottedTemplateTagTest(BaseTestCase):
|
||||
def setUp(self):
|
||||
# NOTE: registry is global, so need to clear before each test
|
||||
registry.clear()
|
||||
|
||||
@parametrize_context_behavior(["django", "isolated"])
|
||||
def test_slotted_template_basic(self):
|
||||
registry.register(name="test1", component=SlottedComponent)
|
||||
|
@ -477,10 +473,6 @@ class ComponentSlottedTemplateTagTest(BaseTestCase):
|
|||
|
||||
|
||||
class SlottedTemplateRegressionTests(BaseTestCase):
|
||||
def setUp(self):
|
||||
# NOTE: registry is global, so need to clear before each test
|
||||
registry.clear()
|
||||
|
||||
@parametrize_context_behavior(["django", "isolated"])
|
||||
def test_slotted_template_that_uses_missing_variable(self):
|
||||
@register("test")
|
||||
|
@ -517,13 +509,8 @@ class SlottedTemplateRegressionTests(BaseTestCase):
|
|||
class SlotDefaultTests(BaseTestCase):
|
||||
def setUp(self):
|
||||
super().setUp()
|
||||
registry.clear()
|
||||
registry.register("test", SlottedComponent)
|
||||
|
||||
def tearDown(self):
|
||||
super().tearDown()
|
||||
registry.clear()
|
||||
|
||||
@parametrize_context_behavior(["django", "isolated"])
|
||||
def test_basic(self):
|
||||
template_str: types.django_html = """
|
||||
|
@ -1115,10 +1102,6 @@ class SlotFillTemplateSyntaxErrorTests(BaseTestCase):
|
|||
super().setUp()
|
||||
registry.register("test", SlottedComponent)
|
||||
|
||||
def tearDown(self):
|
||||
super().tearDown()
|
||||
registry.clear()
|
||||
|
||||
@parametrize_context_behavior(["django", "isolated"])
|
||||
def test_fill_with_no_parent_is_error(self):
|
||||
with self.assertRaises(TemplateSyntaxError):
|
||||
|
|
|
@ -178,13 +178,8 @@ class ConditionalSlotTests(BaseTestCase):
|
|||
|
||||
def setUp(self):
|
||||
super().setUp()
|
||||
registry.clear()
|
||||
registry.register("test", self.ConditionalComponent)
|
||||
|
||||
def tearDown(self):
|
||||
super().tearDown()
|
||||
registry.clear()
|
||||
|
||||
@parametrize_context_behavior(["django", "isolated"])
|
||||
def test_no_content_if_branches_are_false(self):
|
||||
template_str: types.django_html = """
|
||||
|
@ -260,9 +255,6 @@ class SlotIterationTest(BaseTestCase):
|
|||
"objects": objects,
|
||||
}
|
||||
|
||||
def setUp(self):
|
||||
registry.clear()
|
||||
|
||||
# NOTE: Second arg in tuple is expected result. In isolated mode, loops should NOT leak.
|
||||
@parametrize_context_behavior(
|
||||
[
|
||||
|
@ -627,10 +619,6 @@ class ComponentNestingTests(BaseTestCase):
|
|||
registry.register("complex_child", self.ComplexChildComponent)
|
||||
registry.register("complex_parent", self.ComplexParentComponent)
|
||||
|
||||
def tearDown(self) -> None:
|
||||
super().tearDown()
|
||||
registry.clear()
|
||||
|
||||
# NOTE: Second arg in tuple are expected names in nested fills. In "django" mode,
|
||||
# the value should be overridden by the component, while in "isolated" it should
|
||||
# remain top-level context.
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue